From 0149265ee83581cf2fb150dcd5d8734c02926261 Mon Sep 17 00:00:00 2001
From: CasperW
Date: Sat, 21 Nov 2009 15:36:38 +0100
Subject: Improved avatar responsiveness.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 80 +++++++++++++++++++-----
1 file changed, 65 insertions(+), 15 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 424c25b..99f3141 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes
// {
// m_log.Debug("[ScenePresence] Destructor called");
// }
-
+
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
@@ -144,7 +144,6 @@ namespace OpenSim.Region.Framework.Scenes
private int m_perfMonMS;
private bool m_setAlwaysRun;
-
private bool m_forceFly;
private bool m_flyDisabled;
@@ -166,7 +165,8 @@ namespace OpenSim.Region.Framework.Scenes
protected RegionInfo m_regionInfo;
protected ulong crossingFromRegion;
- private readonly Vector3[] Dir_Vectors = new Vector3[6];
+ private readonly Vector3[] Dir_Vectors = new Vector3[9];
+ private bool m_isNudging = false;
// Position of agent's camera in world (region cordinates)
protected Vector3 m_CameraCenter;
@@ -230,6 +230,8 @@ namespace OpenSim.Region.Framework.Scenes
DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
+ DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
+ DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
}
@@ -714,21 +716,41 @@ namespace OpenSim.Region.Framework.Scenes
Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
Dir_Vectors[4] = Vector3.UnitZ; //UP
Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
- Dir_Vectors[5] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
+ Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
+ Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
+ Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
}
private Vector3[] GetWalkDirectionVectors()
{
- Vector3[] vector = new Vector3[6];
+ Vector3[] vector = new Vector3[9];
vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
vector[2] = Vector3.UnitY; //LEFT
vector[3] = -Vector3.UnitY; //RIGHT
vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
- vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge
+ vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
+ vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
+ vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge
return vector;
}
+
+ private bool[] GetDirectionIsNudge()
+ {
+ bool[] isNudge = new bool[9];
+ isNudge[0] = false; //FORWARD
+ isNudge[1] = false; //BACK
+ isNudge[2] = false; //LEFT
+ isNudge[3] = false; //RIGHT
+ isNudge[4] = false; //UP
+ isNudge[5] = false; //DOWN
+ isNudge[6] = true; //FORWARD_NUDGE
+ isNudge[7] = true; //BACK_NUDGE
+ isNudge[8] = true; //DOWN_Nudge
+ return isNudge;
+ }
+
#endregion
@@ -1147,7 +1169,6 @@ namespace OpenSim.Region.Framework.Scenes
// // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
// return;
//}
-
m_perfMonMS = Environment.TickCount;
++m_movementUpdateCount;
@@ -1229,7 +1250,6 @@ namespace OpenSim.Region.Framework.Scenes
m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
}
}
-
lock (scriptedcontrols)
{
if (scriptedcontrols.Count > 0)
@@ -1261,7 +1281,6 @@ namespace OpenSim.Region.Framework.Scenes
{
return;
}
-
if (m_allowMovement)
{
int i = 0;
@@ -1289,6 +1308,11 @@ namespace OpenSim.Region.Framework.Scenes
update_rotation = true;
}
+ //guilty until proven innocent..
+ bool Nudging = true;
+ //Basically, if there is at least one non-nudge control then we don't need
+ //to worry about stopping the avatar
+
if (m_parentID == 0)
{
bool bAllowUpdateMoveToPosition = false;
@@ -1303,6 +1327,12 @@ namespace OpenSim.Region.Framework.Scenes
else
dirVectors = Dir_Vectors;
+ bool[] isNudge = GetDirectionIsNudge();
+
+
+
+
+
foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
{
if (((uint)flags & (uint)DCF) != 0)
@@ -1312,6 +1342,10 @@ namespace OpenSim.Region.Framework.Scenes
try
{
agent_control_v3 += dirVectors[i];
+ if (isNudge[i] == false)
+ {
+ Nudging = false;
+ }
}
catch (IndexOutOfRangeException)
{
@@ -1373,6 +1407,9 @@ namespace OpenSim.Region.Framework.Scenes
// Ignore z component of vector
Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
LocalVectorToTarget2D.Normalize();
+
+ //We're not nudging
+ Nudging = false;
agent_control_v3 += LocalVectorToTarget2D;
// update avatar movement flags. the avatar coordinate system is as follows:
@@ -1450,7 +1487,7 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.DebugFormat(
// "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
- AddNewMovement(agent_control_v3, q);
+ AddNewMovement(agent_control_v3, q, Nudging);
if (update_movementflag)
Animator.UpdateMovementAnimations();
@@ -1886,7 +1923,7 @@ namespace OpenSim.Region.Framework.Scenes
///
/// The vector in which to move. This is relative to the rotation argument
/// The direction in which this avatar should now face.
- public void AddNewMovement(Vector3 vec, Quaternion rotation)
+ public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
{
if (m_isChildAgent)
{
@@ -1960,7 +1997,7 @@ namespace OpenSim.Region.Framework.Scenes
// TODO: Add the force instead of only setting it to support multiple forces per frame?
m_forceToApply = direc;
-
+ m_isNudging = Nudging;
m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
}
@@ -1975,7 +2012,7 @@ namespace OpenSim.Region.Framework.Scenes
const float POSITION_TOLERANCE = 0.05f;
//const int TIME_MS_TOLERANCE = 3000;
- SendPrimUpdates();
+
if (m_newCoarseLocations)
{
@@ -2011,6 +2048,9 @@ namespace OpenSim.Region.Framework.Scenes
CheckForBorderCrossing();
CheckForSignificantMovement(); // sends update to the modules.
}
+
+ //Sending prim updates AFTER the avatar terse updates are sent
+ SendPrimUpdates();
}
#endregion
@@ -2864,14 +2904,24 @@ namespace OpenSim.Region.Framework.Scenes
{
if (m_forceToApply.HasValue)
{
- Vector3 force = m_forceToApply.Value;
+ Vector3 force = m_forceToApply.Value;
m_updateflag = true;
-// movementvector = force;
Velocity = force;
m_forceToApply = null;
}
+ else
+ {
+ if (m_isNudging)
+ {
+ Vector3 force = Vector3.Zero;
+
+ m_updateflag = true;
+ Velocity = force;
+ m_isNudging = false;
+ }
+ }
}
public override void SetText(string text, Vector3 color, double alpha)
--
cgit v1.1
From f1522e62042d11604ad70a39b26dc94953e9db7d Mon Sep 17 00:00:00 2001
From: KittoFlora
Date: Sun, 22 Nov 2009 08:31:35 +0100
Subject: Add non-scripted sit, fix scripted sit.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 99 +++++++++++++++++-------
1 file changed, 69 insertions(+), 30 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1dedcf1..aa538dc 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -89,7 +89,8 @@ namespace OpenSim.Region.Framework.Scenes
/// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
/// issue #1716
///
- private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
+// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
+ private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
public UUID currentParcelUUID = UUID.Zero;
@@ -113,7 +114,8 @@ namespace OpenSim.Region.Framework.Scenes
public Vector3 lastKnownAllowedPosition;
public bool sentMessageAboutRestrictedParcelFlyingDown;
public Vector4 CollisionPlane = Vector4.UnitW;
-
+
+ private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
private Vector3 m_lastPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
@@ -1531,7 +1533,7 @@ namespace OpenSim.Region.Framework.Scenes
Velocity = Vector3.Zero;
SendFullUpdateToAllClients();
- //HandleAgentSit(ControllingClient, m_requestedSitTargetUUID);
+ HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
}
//ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
m_requestedSitTargetUUID = UUID.Zero;
@@ -1644,7 +1646,7 @@ namespace OpenSim.Region.Framework.Scenes
bool SitTargetisSet =
(!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
-
+ // this test is probably failing
if (SitTargetisSet && SitTargetUnOccupied)
{
//switch the target to this prim
@@ -1671,26 +1673,37 @@ namespace OpenSim.Region.Framework.Scenes
{
// TODO: determine position to sit at based on scene geometry; don't trust offset from client
// see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
-
+
+ // part is the prim to sit on
+ // offset is the vector distance from that prim center to the click-spot
+ // UUID is the UUID of the Avatar doing the clicking
+
+ m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
+
// Is a sit target available?
Vector3 avSitOffSet = part.SitTargetPosition;
Quaternion avSitOrientation = part.SitTargetOrientation;
UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
- bool SitTargetisSet =
- (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f &&
- avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f));
+// bool SitTargetisSet =
+// (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f &&
+// avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f));
+ bool SitTargetisSet = ((Vector3.Zero != avSitOffSet) || (Quaternion.Identity != avSitOrientation));
+
+//Console.WriteLine("SendSitResponse offset=" + offset + " UnOccup=" + SitTargetUnOccupied +
+// " TargSet=" + SitTargetisSet);
+
if (SitTargetisSet && SitTargetUnOccupied)
{
part.SetAvatarOnSitTarget(UUID);
offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
sitOrientation = avSitOrientation;
- autopilot = false;
+ autopilot = false; // Jump direct to scripted llSitPos()
}
- pos = part.AbsolutePosition + offset;
+ pos = part.AbsolutePosition + offset; // Region position where clicked
//if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
//{
// offset = pos;
@@ -1703,17 +1716,17 @@ namespace OpenSim.Region.Framework.Scenes
m_sitAvatarHeight = m_physicsActor.Size.Z;
if (autopilot)
- {
+ { // its not a scripted sit
if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5)
{
- autopilot = false;
+ autopilot = false; // close enough
RemoveFromPhysicalScene();
- AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight);
- }
+ AbsolutePosition = pos + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to Prim
+ } // else the autopilot will get us close
}
else
- {
+ { // its a scripted sit
RemoveFromPhysicalScene();
}
}
@@ -1816,26 +1829,41 @@ namespace OpenSim.Region.Framework.Scenes
{
if (part.GetAvatarOnSitTarget() == UUID)
{
+ // Scripted sit
Vector3 sitTargetPos = part.SitTargetPosition;
Quaternion sitTargetOrient = part.SitTargetOrientation;
-
- //Quaternion vq = new Quaternion(sitTargetPos.X, sitTargetPos.Y+0.2f, sitTargetPos.Z+0.2f, 0);
- //Quaternion nq = new Quaternion(-sitTargetOrient.X, -sitTargetOrient.Y, -sitTargetOrient.Z, sitTargetOrient.w);
-
- //Quaternion result = (sitTargetOrient * vq) * nq;
-
m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
m_pos += SIT_TARGET_ADJUSTMENT;
m_bodyRot = sitTargetOrient;
- //Rotation = sitTargetOrient;
m_parentPosition = part.AbsolutePosition;
-
- //SendTerseUpdateToAllClients();
}
else
{
- m_pos -= part.AbsolutePosition;
+ // Non-scripted sit by Kitto Flora 21Nov09
+ // Calculate angle of line from prim to Av
+ float y_diff = (m_avInitialPos.Y - part.AbsolutePosition.Y);
+ float x_diff = ( m_avInitialPos.X - part.AbsolutePosition.X);
+ if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
+ if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
+ float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
+ Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
+ // Av sits at world euler <0,0, z>, translated by part rotation
+ m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
+ m_pos = new Vector3(0f, 0f, 0.05f) +
+ (new Vector3(0.0f, 0f, 0.625f) * partIRot) +
+ (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot); // sit at center of prim
m_parentPosition = part.AbsolutePosition;
+ //Set up raytrace to find top surface of prim
+ Vector3 size = part.Scale;
+ float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
+ Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
+ Vector3 down = new Vector3(0f, 0f, -1f);
+ m_scene.PhysicsScene.RaycastWorld(
+ start, // Vector3 position,
+ down, // Vector3 direction,
+ mag, // float length,
+ SitAltitudeCallback); // retMethod
}
}
else
@@ -1850,11 +1878,22 @@ namespace OpenSim.Region.Framework.Scenes
Animator.TrySetMovementAnimation(sitAnimation);
SendFullUpdateToAllClients();
- // This may seem stupid, but Our Full updates don't send avatar rotation :P
- // So we're also sending a terse update (which has avatar rotation)
- // [Update] We do now.
- //SendTerseUpdateToAllClients();
}
+
+ public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance)
+ {
+// Console.WriteLine("[RAYCASTRESULT]: Hit={0}, Point={1}, ID={2}, Dist={3}", hitYN, collisionPoint, localid, distance);
+ if(hitYN)
+ {
+ // m_pos = Av offset from prim center to make look like on center
+ // m_parentPosition = Actual center pos of prim
+ // collisionPoint = spot on prim where we want to sit
+ SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
+ Vector3 offset = (collisionPoint - m_parentPosition) * Quaternion.Inverse(part.RotationOffset);
+ m_pos += offset;
+// Console.WriteLine("m_pos={0}, offset={1} newsit={2}", m_pos, offset, newsit);
+ }
+ }
///
/// Event handler for the 'Always run' setting on the client
@@ -3578,4 +3617,4 @@ namespace OpenSim.Region.Framework.Scenes
}
}
}
-}
\ No newline at end of file
+}
--
cgit v1.1
From d1147136946daf14724183b3191119be44ff8b16 Mon Sep 17 00:00:00 2001
From: CasperW
Date: Tue, 24 Nov 2009 18:02:12 +0100
Subject: Drop all locking of part.TaskInventory in favour of a
ReaderWriterLockSlim lock handler. This gives us: - Faster prim inventory
actions. Multiple threads can read at once. - Fixes the known prim inventory
thread locks - In the event of a thread lock occurring, it will usually self
heal after sixty seconds with an error message in the console
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 16 +++++++---------
1 file changed, 7 insertions(+), 9 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 4e5fee1..4c8c94f 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1615,21 +1615,19 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
if (part != null)
{
+ part.TaskInventory.LockItemsForRead(true);
TaskInventoryDictionary taskIDict = part.TaskInventory;
if (taskIDict != null)
{
- lock (taskIDict)
+ foreach (UUID taskID in taskIDict.Keys)
{
- foreach (UUID taskID in taskIDict.Keys)
- {
- UnRegisterControlEventsToScript(LocalId, taskID);
- taskIDict[taskID].PermsMask &= ~(
- 2048 | //PERMISSION_CONTROL_CAMERA
- 4); // PERMISSION_TAKE_CONTROLS
- }
+ UnRegisterControlEventsToScript(LocalId, taskID);
+ taskIDict[taskID].PermsMask &= ~(
+ 2048 | //PERMISSION_CONTROL_CAMERA
+ 4); // PERMISSION_TAKE_CONTROLS
}
-
}
+ part.TaskInventory.LockItemsForRead(false);
// Reset sit target.
if (part.GetAvatarOnSitTarget() == UUID)
part.SetAvatarOnSitTarget(UUID.Zero);
--
cgit v1.1
From 32c464ad1f43cbee9492108c1bec7f874a20cd47 Mon Sep 17 00:00:00 2001
From: KittoFlora
Date: Wed, 25 Nov 2009 08:03:09 +0100
Subject: Fixed animation sequencing: SitHere, Falling, Stand/Walk etc. Login
Init Av Animation at Stand.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 34 ++++++++++++++++--------
1 file changed, 23 insertions(+), 11 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 4e5fee1..a65b84b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -90,6 +90,7 @@ namespace OpenSim.Region.Framework.Scenes
/// issue #1716
///
// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
+ // Value revised by KF 091121 by comparison with SL.
private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
public UUID currentParcelUUID = UUID.Zero;
@@ -205,6 +206,9 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_followCamAuto;
private int m_movementUpdateCount;
+ private int m_lastColCount = -1; //KF: Look for Collision chnages
+ private int m_updateCount = 0; //KF: Update Anims for a while
+ private static readonly int UPDATE_COUNT = 10; // how many frames to update for
private const int NumMovementsBetweenRayCast = 5;
@@ -662,9 +666,7 @@ namespace OpenSim.Region.Framework.Scenes
AdjustKnownSeeds();
- // TODO: I think, this won't send anything, as we are still a child here...
- Animator.TrySetMovementAnimation("STAND");
-
+ Animator.TrySetMovementAnimation("STAND");
// we created a new ScenePresence (a new child agent) in a fresh region.
// Request info about all the (root) agents in this region
// Note: This won't send data *to* other clients in that region (children don't send)
@@ -1018,7 +1020,9 @@ namespace OpenSim.Region.Framework.Scenes
{
AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
}
-
+
+ m_updateCount = UPDATE_COUNT; //KF: Trigger Anim updates to catch falling anim.
+
ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
}
@@ -1266,9 +1270,7 @@ namespace OpenSim.Region.Framework.Scenes
if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
{
- // TODO: This doesn't prevent the user from walking yet.
- // Setting parent ID would fix this, if we knew what value
- // to use. Or we could add a m_isSitting variable.
+ m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
}
@@ -1926,7 +1928,6 @@ namespace OpenSim.Region.Framework.Scenes
public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance)
{
-// Console.WriteLine("[RAYCASTRESULT]: Hit={0}, Point={1}, ID={2}, Dist={3}", hitYN, collisionPoint, localid, distance);
if(hitYN)
{
// m_pos = Av offset from prim center to make look like on center
@@ -2964,6 +2965,7 @@ namespace OpenSim.Region.Framework.Scenes
m_updateflag = true;
Velocity = force;
m_isNudging = false;
+ m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
}
}
}
@@ -3015,19 +3017,29 @@ namespace OpenSim.Region.Framework.Scenes
// Event called by the physics plugin to tell the avatar about a collision.
private void PhysicsCollisionUpdate(EventArgs e)
{
+ if (m_updateCount > 0) //KF: Update Anims for a short period. Many Anim
+ { // changes are very asynchronous.
+ Animator.UpdateMovementAnimations();
+ m_updateCount--;
+ }
+
if (e == null)
return;
- //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f))
// The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
// as of this comment the interval is set in AddToPhysicalScene
- Animator.UpdateMovementAnimations();
-
+
CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
Dictionary coldata = collisionData.m_objCollisionList;
CollisionPlane = Vector4.UnitW;
+ if (m_lastColCount != coldata.Count)
+ {
+ m_updateCount = 10;
+ m_lastColCount = coldata.Count;
+ }
+
if (coldata.Count != 0)
{
switch (Animator.CurrentMovementAnimation)
--
cgit v1.1
From b9d22aa8213b62eb0c368b345ccfc105367c1aba Mon Sep 17 00:00:00 2001
From: CasperW
Date: Thu, 26 Nov 2009 01:59:08 +0100
Subject: Add nudge right and left to avatar movement (faster reaction times
when stepping left or right.)
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 4c8c94f..9b04422 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -169,7 +169,7 @@ namespace OpenSim.Region.Framework.Scenes
protected RegionInfo m_regionInfo;
protected ulong crossingFromRegion;
- private readonly Vector3[] Dir_Vectors = new Vector3[9];
+ private readonly Vector3[] Dir_Vectors = new Vector3[11];
private bool m_isNudging = false;
// Position of agent's camera in world (region cordinates)
@@ -236,6 +236,8 @@ namespace OpenSim.Region.Framework.Scenes
DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
+ DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
+ DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
}
@@ -722,12 +724,14 @@ namespace OpenSim.Region.Framework.Scenes
Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
- Dir_Vectors[8] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
+ Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
+ Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
+ Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
}
private Vector3[] GetWalkDirectionVectors()
{
- Vector3[] vector = new Vector3[9];
+ Vector3[] vector = new Vector3[11];
vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
vector[2] = Vector3.UnitY; //LEFT
@@ -736,13 +740,15 @@ namespace OpenSim.Region.Framework.Scenes
vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
- vector[8] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge
+ vector[8] = Vector3.UnitY; //LEFT_NUDGE
+ vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
+ vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge
return vector;
}
private bool[] GetDirectionIsNudge()
{
- bool[] isNudge = new bool[9];
+ bool[] isNudge = new bool[11];
isNudge[0] = false; //FORWARD
isNudge[1] = false; //BACK
isNudge[2] = false; //LEFT
@@ -751,7 +757,9 @@ namespace OpenSim.Region.Framework.Scenes
isNudge[5] = false; //DOWN
isNudge[6] = true; //FORWARD_NUDGE
isNudge[7] = true; //BACK_NUDGE
- isNudge[8] = true; //DOWN_Nudge
+ isNudge[8] = true; //LEFT_NUDGE
+ isNudge[9] = true; //RIGHT_NUDGE
+ isNudge[10] = true; //DOWN_Nudge
return isNudge;
}
--
cgit v1.1
From 63b6b9cdce6382e2285b1a9d76e68a0ac10602ef Mon Sep 17 00:00:00 2001
From: CasperW
Date: Thu, 26 Nov 2009 02:35:27 +0100
Subject: Added animation support for my last commit
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 9b04422..a1bb244 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -742,7 +742,7 @@ namespace OpenSim.Region.Framework.Scenes
vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
vector[8] = Vector3.UnitY; //LEFT_NUDGE
vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
- vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_Nudge
+ vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
return vector;
}
--
cgit v1.1
From 5dedacca3c9692948f29f5198dd444efe7c8526d Mon Sep 17 00:00:00 2001
From: KittoFlora
Date: Thu, 26 Nov 2009 20:37:08 +0100
Subject: First attempt at mult-sit on large single prims.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 91 +++++++++++++++---------
1 file changed, 58 insertions(+), 33 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a65b84b..e677cfd 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -117,6 +117,7 @@ namespace OpenSim.Region.Framework.Scenes
public Vector4 CollisionPlane = Vector4.UnitW;
private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
+ private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
private Vector3 m_lastPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
@@ -1644,9 +1645,9 @@ namespace OpenSim.Region.Framework.Scenes
{
AddToPhysicalScene(false);
}
-
m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight);
m_parentPosition = Vector3.Zero;
+//Console.WriteLine("Stand Pos {0}", m_pos);
m_parentID = 0;
SendFullUpdateToAllClients();
@@ -1740,21 +1741,37 @@ namespace OpenSim.Region.Framework.Scenes
//Console.WriteLine("SendSitResponse offset=" + offset + " UnOccup=" + SitTargetUnOccupied +
// " TargSet=" + SitTargetisSet);
-
- if (SitTargetisSet && SitTargetUnOccupied)
- {
- part.SetAvatarOnSitTarget(UUID);
- offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z);
- sitOrientation = avSitOrientation;
- autopilot = false; // Jump direct to scripted llSitPos()
- }
+ // Sit analysis rewritten by KF 091125
+ if (SitTargetisSet) // scipted sit
+ {
+ if (SitTargetUnOccupied)
+ {
+ part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
+ offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
+ sitOrientation = avSitOrientation; // Change rotatione to the scripted one
+ autopilot = false; // Jump direct to scripted llSitPos()
+ }
+ else return;
+ }
+ else // Not Scripted
+ {
+ if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) // large prim
+ {
+ Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ m_avUnscriptedSitPos = offset * partIRot; // sit where clicked
+ pos = part.AbsolutePosition + (offset * partIRot);
+ }
+ else // small prim
+ {
+ if (SitTargetUnOccupied)
+ {
+ m_avUnscriptedSitPos = Vector3.Zero; // Sit on unoccupied small prim center
+ pos = part.AbsolutePosition;
+ }
+ else return; // occupied small
+ } // end large/small
+ } // end Scripted/not
- pos = part.AbsolutePosition + offset; // Region position where clicked
- //if (Math.Abs(part.AbsolutePosition.Z - AbsolutePosition.Z) > 1)
- //{
- // offset = pos;
- //autopilot = false;
- //}
if (m_physicsActor != null)
{
// If we're not using the client autopilot, we're immediately warping the avatar to the location
@@ -1887,8 +1904,9 @@ namespace OpenSim.Region.Framework.Scenes
{
// Non-scripted sit by Kitto Flora 21Nov09
// Calculate angle of line from prim to Av
- float y_diff = (m_avInitialPos.Y - part.AbsolutePosition.Y);
- float x_diff = ( m_avInitialPos.X - part.AbsolutePosition.X);
+ Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
+ float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
+ float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
@@ -1896,23 +1914,30 @@ namespace OpenSim.Region.Framework.Scenes
// NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
// Av sits at world euler <0,0, z>, translated by part rotation
m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
- m_pos = new Vector3(0f, 0f, 0.05f) +
- (new Vector3(0.0f, 0f, 0.625f) * partIRot) +
- (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot); // sit at center of prim
m_parentPosition = part.AbsolutePosition;
- //Set up raytrace to find top surface of prim
- Vector3 size = part.Scale;
- float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
- Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
- Vector3 down = new Vector3(0f, 0f, -1f);
- m_scene.PhysicsScene.RaycastWorld(
- start, // Vector3 position,
- down, // Vector3 direction,
- mag, // float length,
- SitAltitudeCallback); // retMethod
- }
- }
- else
+ if(m_avUnscriptedSitPos != Vector3.Zero)
+ { // sit where clicked on big prim
+ m_pos = m_avUnscriptedSitPos + (new Vector3(0.0f, 0f, 0.625f) * partIRot);
+ }
+ else
+ { // sit at center of small prim
+ m_pos = new Vector3(0f, 0f, 0.05f) +
+ (new Vector3(0.0f, 0f, 0.625f) * partIRot) +
+ (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot);
+ //Set up raytrace to find top surface of prim
+ Vector3 size = part.Scale;
+ float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
+ Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
+ Vector3 down = new Vector3(0f, 0f, -1f);
+ m_scene.PhysicsScene.RaycastWorld(
+ start, // Vector3 position,
+ down, // Vector3 direction,
+ mag, // float length,
+ SitAltitudeCallback); // retMethod
+ } // end small/big
+ } // end scripted/not
+ }
+ else // no Av
{
return;
}
--
cgit v1.1
From cc8246206d5044aff0b306a4bcaf4b321fb826c9 Mon Sep 17 00:00:00 2001
From: KittoFlora
Date: Sat, 5 Dec 2009 09:03:02 +0100
Subject: Secnond revision of Sit and Stand for unscripted prims; Comment out
spammy debug messages in Interregion....
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 253 +++++++++++++----------
1 file changed, 140 insertions(+), 113 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cebd108..817b9df 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -197,6 +197,7 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_autopilotMoving;
private Vector3 m_autoPilotTarget;
private bool m_sitAtAutoTarget;
+ private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
private string m_nextSitAnimation = String.Empty;
@@ -1524,7 +1525,6 @@ namespace OpenSim.Region.Framework.Scenes
m_sitAtAutoTarget = false;
PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
//proxy.PCode = (byte)PCode.ParticleSystem;
-
proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
proxyObjectGroup.AttachToScene(m_scene);
@@ -1566,7 +1566,7 @@ namespace OpenSim.Region.Framework.Scenes
}
m_moveToPositionInProgress = true;
m_moveToPositionTarget = new Vector3(locx, locy, locz);
- }
+ }
catch (Exception ex)
{
//Why did I get this error?
@@ -1646,16 +1646,22 @@ namespace OpenSim.Region.Framework.Scenes
m_parentPosition = part.GetWorldPosition();
ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
}
+ // part.GetWorldRotation() is the rotation of the object being sat on
+ // Rotation is the sittiing Av's rotation
+
+ Quaternion wr = Quaternion.Inverse(Quaternion.Inverse(Rotation) * Quaternion.Inverse(part.GetWorldRotation())); // world or. of the av
+ Vector3 so = new Vector3(1.0f, 0f, 0f) * wr; // 1M infront of av
+ Vector3 wso = so + part.GetWorldPosition() + ( m_pos * part.GetWorldRotation()); // + av sit offset!
if (m_physicsActor == null)
{
AddToPhysicalScene(false);
}
- m_pos += m_parentPosition + new Vector3(0.0f, 0.0f, 2.0f*m_sitAvatarHeight);
+ AbsolutePosition = wso; //KF: Fix stand up.
m_parentPosition = Vector3.Zero;
-//Console.WriteLine("Stand Pos {0}", m_pos);
-
- m_parentID = 0;
+
+ m_parentID = 0;
+ part.IsOccupied = false;
SendFullUpdateToAllClients();
m_requestedSitTargetID = 0;
if ((m_physicsActor != null) && (m_avHeight > 0))
@@ -1694,13 +1700,9 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 avSitOffSet = part.SitTargetPosition;
Quaternion avSitOrientation = part.SitTargetOrientation;
UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
-
- bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
- bool SitTargetisSet =
- (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 1f &&
- avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 0f));
- // this test is probably failing
- if (SitTargetisSet && SitTargetUnOccupied)
+ bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
+ bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
+ if (SitTargetisSet && !SitTargetOccupied)
{
//switch the target to this prim
return part;
@@ -1714,7 +1716,7 @@ namespace OpenSim.Region.Framework.Scenes
private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset)
{
bool autopilot = true;
- Vector3 pos = new Vector3();
+ Vector3 autopilotTarget = new Vector3();
Quaternion sitOrientation = Quaternion.Identity;
Vector3 cameraEyeOffset = Vector3.Zero;
Vector3 cameraAtOffset = Vector3.Zero;
@@ -1722,98 +1724,104 @@ namespace OpenSim.Region.Framework.Scenes
//SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
SceneObjectPart part = FindNextAvailableSitTarget(targetID);
- if (part != null)
- {
- // TODO: determine position to sit at based on scene geometry; don't trust offset from client
- // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
+ if (part == null) return;
+
+ // TODO: determine position to sit at based on scene geometry; don't trust offset from client
+ // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
- // part is the prim to sit on
- // offset is the vector distance from that prim center to the click-spot
- // UUID is the UUID of the Avatar doing the clicking
-
- m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
+ // part is the prim to sit on
+ // offset is the world-ref vector distance from that prim center to the click-spot
+ // UUID is the UUID of the Avatar doing the clicking
- // Is a sit target available?
- Vector3 avSitOffSet = part.SitTargetPosition;
- Quaternion avSitOrientation = part.SitTargetOrientation;
- UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
-
- bool SitTargetUnOccupied = (!(avOnTargetAlready != UUID.Zero));
-// bool SitTargetisSet =
-// (!(avSitOffSet.X == 0f && avSitOffSet.Y == 0f && avSitOffSet.Z == 0f && avSitOrientation.W == 0f &&
-// avSitOrientation.X == 0f && avSitOrientation.Y == 0f && avSitOrientation.Z == 1f));
-
- bool SitTargetisSet = ((Vector3.Zero != avSitOffSet) || (Quaternion.Identity != avSitOrientation));
-
-//Console.WriteLine("SendSitResponse offset=" + offset + " UnOccup=" + SitTargetUnOccupied +
-// " TargSet=" + SitTargetisSet);
- // Sit analysis rewritten by KF 091125
- if (SitTargetisSet) // scipted sit
- {
- if (SitTargetUnOccupied)
- {
- part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
- offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
- sitOrientation = avSitOrientation; // Change rotatione to the scripted one
- autopilot = false; // Jump direct to scripted llSitPos()
- }
- else return;
+ m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
+
+ // Is a sit target available?
+ Vector3 avSitOffSet = part.SitTargetPosition;
+ Quaternion avSitOrientation = part.SitTargetOrientation;
+
+ bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
+ Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+
+//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
+ // Sit analysis rewritten by KF 091125
+ if (SitTargetisSet) // scipted sit
+ {
+ if (!part.IsOccupied)
+ {
+//Console.WriteLine("Scripted, unoccupied");
+ part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
+ offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
+ sitOrientation = avSitOrientation; // Change rotatione to the scripted one
+ autopilot = false; // Jump direct to scripted llSitPos()
}
- else // Not Scripted
- {
- if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) ) // large prim
- {
- Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
- m_avUnscriptedSitPos = offset * partIRot; // sit where clicked
- pos = part.AbsolutePosition + (offset * partIRot);
- }
- else // small prim
- {
- if (SitTargetUnOccupied)
- {
- m_avUnscriptedSitPos = Vector3.Zero; // Sit on unoccupied small prim center
- pos = part.AbsolutePosition;
- }
- else return; // occupied small
- } // end large/small
- } // end Scripted/not
-
- if (m_physicsActor != null)
- {
- // If we're not using the client autopilot, we're immediately warping the avatar to the location
- // We can remove the physicsActor until they stand up.
- m_sitAvatarHeight = m_physicsActor.Size.Z;
-
- if (autopilot)
- { // its not a scripted sit
- if (Util.GetDistanceTo(AbsolutePosition, pos) < 4.5)
- {
- autopilot = false; // close enough
+ else
+ {
+//Console.WriteLine("Scripted, occupied");
+ return;
+ }
+ }
+ else // Not Scripted
+ {
+ if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
+ {
+ // large prim & offset, ignore if other Avs sitting
+// offset.Z -= 0.05f;
+ m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
+ autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
+
+//Console.WriteLine(" offset ={0}", offset);
+//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
+//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
+
+ }
+ else // small offset
+ {
+//Console.WriteLine("Small offset");
+ if (!part.IsOccupied)
+ {
+ m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
+ autopilotTarget = part.AbsolutePosition;
+ }
+ else return; // occupied small
+ } // end large/small
+ } // end Scripted/not
+ cameraAtOffset = part.GetCameraAtOffset();
+ cameraEyeOffset = part.GetCameraEyeOffset();
+ forceMouselook = part.GetForceMouselook();
- RemoveFromPhysicalScene();
- AbsolutePosition = pos + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to Prim
- } // else the autopilot will get us close
- }
- else
- { // its a scripted sit
+ if (m_physicsActor != null)
+ {
+ // If we're not using the client autopilot, we're immediately warping the avatar to the location
+ // We can remove the physicsActor until they stand up.
+ m_sitAvatarHeight = m_physicsActor.Size.Z;
+ if (autopilot)
+ { // its not a scripted sit
+// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
+ if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
+ {
+ autopilot = false; // close enough
RemoveFromPhysicalScene();
- }
+ AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
+ } // else the autopilot will get us close
+ }
+ else
+ { // its a scripted sit
+ RemoveFromPhysicalScene();
}
-
- cameraAtOffset = part.GetCameraAtOffset();
- cameraEyeOffset = part.GetCameraEyeOffset();
- forceMouselook = part.GetForceMouselook();
}
+ else return; // physactor is null!
- ControllingClient.SendSitResponse(targetID, offset, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
- m_requestedSitTargetUUID = targetID;
+ Vector3 offsetr = offset * partIRot;
+ ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
// This calls HandleAgentSit twice, once from here, and the client calls
// HandleAgentSit itself after it gets to the location
// It doesn't get to the location until we've moved them there though
// which happens in HandleAgentSit :P
m_autopilotMoving = autopilot;
- m_autoPilotTarget = pos;
+ m_autoPilotTarget = autopilotTarget;
m_sitAtAutoTarget = autopilot;
+ m_initialSitTarget = autopilotTarget;
if (!autopilot)
HandleAgentSit(remoteClient, UUID);
}
@@ -1898,6 +1906,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (part.GetAvatarOnSitTarget() == UUID)
{
+//Console.WriteLine("Scripted Sit");
// Scripted sit
Vector3 sitTargetPos = part.SitTargetPosition;
Quaternion sitTargetOrient = part.SitTargetOrientation;
@@ -1905,42 +1914,44 @@ namespace OpenSim.Region.Framework.Scenes
m_pos += SIT_TARGET_ADJUSTMENT;
m_bodyRot = sitTargetOrient;
m_parentPosition = part.AbsolutePosition;
+ part.IsOccupied = true;
}
else
{
+//Console.WriteLine("NON Scripted Sit");
+ // if m_avUnscriptedSitPos is zero then Av sits above center
+ // Else Av sits at m_avUnscriptedSitPos
+
// Non-scripted sit by Kitto Flora 21Nov09
// Calculate angle of line from prim to Av
+ Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
- Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
// NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
// Av sits at world euler <0,0, z>, translated by part rotation
m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
+
m_parentPosition = part.AbsolutePosition;
- if(m_avUnscriptedSitPos != Vector3.Zero)
- { // sit where clicked on big prim
- m_pos = m_avUnscriptedSitPos + (new Vector3(0.0f, 0f, 0.625f) * partIRot);
- }
- else
- { // sit at center of small prim
- m_pos = new Vector3(0f, 0f, 0.05f) +
- (new Vector3(0.0f, 0f, 0.625f) * partIRot) +
- (new Vector3(0.25f, 0f, 0.0f) * m_bodyRot);
- //Set up raytrace to find top surface of prim
- Vector3 size = part.Scale;
- float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
- Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
- Vector3 down = new Vector3(0f, 0f, -1f);
- m_scene.PhysicsScene.RaycastWorld(
+ part.IsOccupied = true;
+ m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
+ (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
+ (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
+ m_avUnscriptedSitPos; // adds click offset, if any
+ //Set up raytrace to find top surface of prim
+ Vector3 size = part.Scale;
+ float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
+ Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
+ Vector3 down = new Vector3(0f, 0f, -1f);
+//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
+ m_scene.PhysicsScene.RaycastWorld(
start, // Vector3 position,
down, // Vector3 direction,
mag, // float length,
SitAltitudeCallback); // retMethod
- } // end small/big
} // end scripted/not
}
else // no Av
@@ -1957,19 +1968,24 @@ namespace OpenSim.Region.Framework.Scenes
SendFullUpdateToAllClients();
}
- public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance)
+ public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance) // KF: Nov 2009
{
+ // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
+ // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
if(hitYN)
{
// m_pos = Av offset from prim center to make look like on center
// m_parentPosition = Actual center pos of prim
// collisionPoint = spot on prim where we want to sit
+ // collisionPoint.Z = global sit surface height
SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
- Vector3 offset = (collisionPoint - m_parentPosition) * Quaternion.Inverse(part.RotationOffset);
+ Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ float offZ = collisionPoint.Z - m_initialSitTarget.Z;
+ Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
+//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
m_pos += offset;
-// Console.WriteLine("m_pos={0}, offset={1} newsit={2}", m_pos, offset, newsit);
}
- }
+ } // End SitAltitudeCallback KF.
///
/// Event handler for the 'Always run' setting on the client
@@ -3716,5 +3732,16 @@ namespace OpenSim.Region.Framework.Scenes
m_reprioritization_called = false;
}
}
+
+ private Vector3 Quat2Euler(Quaternion rot){
+ float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
+ (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
+ float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
+ float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
+ (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
+ return(new Vector3(x,y,z));
+ }
+
+
}
}
--
cgit v1.1
From f9ae9afaacc82ee0284b1f7dc88ad880aabe23af Mon Sep 17 00:00:00 2001
From: Melanie
Date: Sun, 6 Dec 2009 03:10:34 +0000
Subject: Fix build break from conflicted merge
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3d4490a..f6bcb59 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1972,7 +1972,7 @@ namespace OpenSim.Region.Framework.Scenes
SendFullUpdateToAllClients();
}
- public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance)
+ public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
{
if(hitYN)
{
--
cgit v1.1
From 0d1d437bd3bf608448d71ea7de8e4f7cfb0371f0 Mon Sep 17 00:00:00 2001
From: KittoFlora
Date: Sun, 6 Dec 2009 21:11:59 +0100
Subject: Fix linked physical daughter prim position update.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 --
1 file changed, 2 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 817b9df..5d0218f 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1642,7 +1642,6 @@ namespace OpenSim.Region.Framework.Scenes
// Reset sit target.
if (part.GetAvatarOnSitTarget() == UUID)
part.SetAvatarOnSitTarget(UUID.Zero);
-
m_parentPosition = part.GetWorldPosition();
ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
}
@@ -1659,7 +1658,6 @@ namespace OpenSim.Region.Framework.Scenes
}
AbsolutePosition = wso; //KF: Fix stand up.
m_parentPosition = Vector3.Zero;
-
m_parentID = 0;
part.IsOccupied = false;
SendFullUpdateToAllClients();
--
cgit v1.1
From b056c243e46daa3370f8d330b70a37b5f856e9ec Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Sat, 12 Dec 2009 10:12:59 -0500
Subject: Commit partial work because of repo change
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 83 ++++++++++++++++++++----
1 file changed, 72 insertions(+), 11 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index c553ca0..d0c20ff 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1660,16 +1660,27 @@ namespace OpenSim.Region.Framework.Scenes
}
// part.GetWorldRotation() is the rotation of the object being sat on
// Rotation is the sittiing Av's rotation
-
- Quaternion wr = Quaternion.Inverse(Quaternion.Inverse(Rotation) * Quaternion.Inverse(part.GetWorldRotation())); // world or. of the av
- Vector3 so = new Vector3(1.0f, 0f, 0f) * wr; // 1M infront of av
- Vector3 wso = so + part.GetWorldPosition() + ( m_pos * part.GetWorldRotation()); // + av sit offset!
+
+ Quaternion partRot;
+ if (part.LinkNum == 1)
+ { // Root prim of linkset
+ partRot = part.ParentGroup.RootPart.RotationOffset;
+ }
+ else
+ { // single or child prim
+ partRot = part.GetWorldRotation();
+ }
+ Quaternion partIRot = Quaternion.Inverse(partRot);
+
+ Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
+ Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ( m_pos * partRot); // + av sit offset!
if (m_physicsActor == null)
{
AddToPhysicalScene(false);
}
- AbsolutePosition = wso; //KF: Fix stand up.
+ AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
m_parentPosition = Vector3.Zero;
m_parentID = 0;
part.IsOccupied = false;
@@ -1752,8 +1763,17 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion avSitOrientation = part.SitTargetOrientation;
bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
- Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
-
+ // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ Quaternion partRot;
+ if (part.LinkNum == 1)
+ { // Root prim of linkset
+ partRot = part.ParentGroup.RootPart.RotationOffset;
+ }
+ else
+ { // single or child prim
+ partRot = part.GetWorldRotation();
+ }
+ Quaternion partIRot = Quaternion.Inverse(partRot);
//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
// Sit analysis rewritten by KF 091125
if (SitTargetisSet) // scipted sit
@@ -1800,6 +1820,8 @@ namespace OpenSim.Region.Framework.Scenes
cameraAtOffset = part.GetCameraAtOffset();
cameraEyeOffset = part.GetCameraEyeOffset();
forceMouselook = part.GetForceMouselook();
+ if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
+ if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
if (m_physicsActor != null)
{
@@ -1823,7 +1845,29 @@ namespace OpenSim.Region.Framework.Scenes
}
else return; // physactor is null!
- Vector3 offsetr = offset * partIRot;
+ Vector3 offsetr; // = offset * partIRot;
+ // KF: In a linkset, offsetr needs to be relative to the group root! 091208
+ // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
+ if (part.LinkNum < 2)
+ { // Single, or Root prim of linkset, target is ClickOffset * RootRot
+ offsetr = offset * partIRot;
+ }
+ else
+ { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
+ offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
+ (offset * partRot);
+ }
+
+Console.WriteLine(" ");
+Console.WriteLine("link number ={0}", part.LinkNum);
+Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
+Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
+Console.WriteLine("Click offst ={0}", offset);
+Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
+Console.WriteLine("offsetr ={0}", offsetr);
+Console.WriteLine("Camera At ={0}", cameraAtOffset);
+Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
+
ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
// This calls HandleAgentSit twice, once from here, and the client calls
@@ -2142,13 +2186,20 @@ namespace OpenSim.Region.Framework.Scenes
}
else
{
-//Console.WriteLine("NON Scripted Sit");
// if m_avUnscriptedSitPos is zero then Av sits above center
// Else Av sits at m_avUnscriptedSitPos
// Non-scripted sit by Kitto Flora 21Nov09
// Calculate angle of line from prim to Av
- Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ Quaternion partIRot;
+ if (part.LinkNum == 1)
+ { // Root prim of linkset
+ partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+ }
+ else
+ { // single or child prim
+ partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ }
Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
@@ -2203,11 +2254,21 @@ namespace OpenSim.Region.Framework.Scenes
// collisionPoint = spot on prim where we want to sit
// collisionPoint.Z = global sit surface height
SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
- Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ Quaternion partIRot;
+ if (part.LinkNum == 1)
+ { // Root prim of linkset
+ partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+ }
+ else
+ { // single or child prim
+ partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ }
float offZ = collisionPoint.Z - m_initialSitTarget.Z;
Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
m_pos += offset;
+ ControllingClient.SendClearFollowCamProperties(part.UUID);
+
}
} // End SitAltitudeCallback KF.
--
cgit v1.1
From b8b4517211d332f76c022075f81cfefd41877d14 Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Tue, 15 Dec 2009 01:49:23 -0500
Subject: Removed excessive call to UpdateMovementAnimations which prevented
GroundSit; Corrected cause of 'sit on roof'.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 48 ++++++++++++------------
1 file changed, 23 insertions(+), 25 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index d0c20ff..c67463a 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -670,8 +670,7 @@ namespace OpenSim.Region.Framework.Scenes
AdjustKnownSeeds();
-
- Animator.TrySetMovementAnimation("STAND");
+ Animator.TrySetMovementAnimation("STAND");
// we created a new ScenePresence (a new child agent) in a fresh region.
// Request info about all the (root) agents in this region
// Note: This won't send data *to* other clients in that region (children don't send)
@@ -1691,7 +1690,6 @@ namespace OpenSim.Region.Framework.Scenes
SetHeight(m_avHeight);
}
}
-
Animator.TrySetMovementAnimation("STAND");
}
@@ -1858,15 +1856,15 @@ namespace OpenSim.Region.Framework.Scenes
(offset * partRot);
}
-Console.WriteLine(" ");
-Console.WriteLine("link number ={0}", part.LinkNum);
-Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
-Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
-Console.WriteLine("Click offst ={0}", offset);
-Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
-Console.WriteLine("offsetr ={0}", offsetr);
-Console.WriteLine("Camera At ={0}", cameraAtOffset);
-Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
+//Console.WriteLine(" ");
+//Console.WriteLine("link number ={0}", part.LinkNum);
+//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
+//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
+//Console.WriteLine("Click offst ={0}", offset);
+//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
+//Console.WriteLine("offsetr ={0}", offsetr);
+//Console.WriteLine("Camera At ={0}", cameraAtOffset);
+//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
@@ -2218,7 +2216,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
m_avUnscriptedSitPos; // adds click offset, if any
//Set up raytrace to find top surface of prim
Vector3 size = part.Scale;
- float mag = 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
+ float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
Vector3 down = new Vector3(0f, 0f, -1f);
//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
@@ -2267,7 +2265,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
m_pos += offset;
- ControllingClient.SendClearFollowCamProperties(part.UUID);
+// ControllingClient.SendClearFollowCamProperties(part.UUID);
}
} // End SitAltitudeCallback KF.
@@ -3297,7 +3295,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
m_updateflag = true;
Velocity = force;
m_isNudging = false;
- m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
+ m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
}
}
}
@@ -3349,19 +3347,19 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
// Event called by the physics plugin to tell the avatar about a collision.
private void PhysicsCollisionUpdate(EventArgs e)
{
- if (m_updateCount > 0) //KF: Update Anims for a short period. Many Anim
- { // changes are very asynchronous.
- Animator.UpdateMovementAnimations();
- m_updateCount--;
- }
-
if (e == null)
return;
-
- // The Physics Scene will send updates every 500 ms grep: m_physicsActor.SubscribeEvents(
+
+ // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
// as of this comment the interval is set in AddToPhysicalScene
if (Animator!=null)
- Animator.UpdateMovementAnimations();
+ {
+ if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
+ { // else its will lock out other animation changes, like ground sit.
+ Animator.UpdateMovementAnimations();
+ m_updateCount--;
+ }
+ }
CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
Dictionary coldata = collisionData.m_objCollisionList;
@@ -3370,7 +3368,7 @@ Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
if (m_lastColCount != coldata.Count)
{
- m_updateCount = 10;
+ m_updateCount = UPDATE_COUNT;
m_lastColCount = coldata.Count;
}
--
cgit v1.1
From 6483470ec5e9000fb6a85bbdfe5b79be6f336a74 Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Thu, 17 Dec 2009 02:54:02 -0500
Subject: Fix GetWorldRotation(), and a host of related Sit fixes.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 73 ++++++++++++------------
1 file changed, 37 insertions(+), 36 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index c67463a..865f649 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1661,14 +1661,14 @@ namespace OpenSim.Region.Framework.Scenes
// Rotation is the sittiing Av's rotation
Quaternion partRot;
- if (part.LinkNum == 1)
- { // Root prim of linkset
- partRot = part.ParentGroup.RootPart.RotationOffset;
- }
- else
- { // single or child prim
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partRot = part.ParentGroup.RootPart.RotationOffset;
+// }
+// else
+// { // single or child prim
partRot = part.GetWorldRotation();
- }
+// }
Quaternion partIRot = Quaternion.Inverse(partRot);
Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
@@ -1763,14 +1763,14 @@ namespace OpenSim.Region.Framework.Scenes
bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
// Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
Quaternion partRot;
- if (part.LinkNum == 1)
- { // Root prim of linkset
- partRot = part.ParentGroup.RootPart.RotationOffset;
- }
- else
- { // single or child prim
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partRot = part.ParentGroup.RootPart.RotationOffset;
+// }
+// else
+// { // single or child prim
partRot = part.GetWorldRotation();
- }
+// }
Quaternion partIRot = Quaternion.Inverse(partRot);
//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
// Sit analysis rewritten by KF 091125
@@ -1846,15 +1846,15 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 offsetr; // = offset * partIRot;
// KF: In a linkset, offsetr needs to be relative to the group root! 091208
// offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
- if (part.LinkNum < 2)
- { // Single, or Root prim of linkset, target is ClickOffset * RootRot
+ // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
+ // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
offsetr = offset * partIRot;
- }
- else
- { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
- offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
- (offset * partRot);
- }
+//
+ // else
+ // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
+ // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
+ // (offset * partRot);
+ // }
//Console.WriteLine(" ");
//Console.WriteLine("link number ={0}", part.LinkNum);
@@ -2170,6 +2170,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (part != null)
{
+//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
if (part.GetAvatarOnSitTarget() == UUID)
{
//Console.WriteLine("Scripted Sit");
@@ -2190,14 +2191,14 @@ namespace OpenSim.Region.Framework.Scenes
// Non-scripted sit by Kitto Flora 21Nov09
// Calculate angle of line from prim to Av
Quaternion partIRot;
- if (part.LinkNum == 1)
- { // Root prim of linkset
- partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
- }
- else
- { // single or child prim
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+// }
+// else
+// { // single or child prim
partIRot = Quaternion.Inverse(part.GetWorldRotation());
- }
+// }
Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
@@ -2253,14 +2254,14 @@ namespace OpenSim.Region.Framework.Scenes
// collisionPoint.Z = global sit surface height
SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
Quaternion partIRot;
- if (part.LinkNum == 1)
- { // Root prim of linkset
- partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
- }
- else
- { // single or child prim
+// if (part.LinkNum == 1)
+/// { // Root prim of linkset
+// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+// }
+// else
+// { // single or child prim
partIRot = Quaternion.Inverse(part.GetWorldRotation());
- }
+// }
float offZ = collisionPoint.Z - m_initialSitTarget.Z;
Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
--
cgit v1.1
From e3c14660478bdd3af8c792b4b6b48ffffbbe19f9 Mon Sep 17 00:00:00 2001
From: CasperW
Date: Mon, 21 Dec 2009 13:22:52 +0100
Subject: Fixed a nasty crash in StandUp() that occurred when the part got
killed with an avatar sitting on it.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 54 ++++++++++++++++++------
1 file changed, 41 insertions(+), 13 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 865f649..abdd1a0 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -118,7 +118,8 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
- private Vector3 m_lastPosition;
+ private Vector3 m_lastPosition;
+ private Vector3 m_lastWorldPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
//private int m_lastTerseSent;
@@ -1667,24 +1668,45 @@ namespace OpenSim.Region.Framework.Scenes
// }
// else
// { // single or child prim
- partRot = part.GetWorldRotation();
-// }
+
+// }
+ if (part == null) //CW: Part may be gone. llDie() for example.
+ {
+ partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ partRot = part.GetWorldRotation();
+ }
+
Quaternion partIRot = Quaternion.Inverse(partRot);
Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
- Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ( m_pos * partRot); // + av sit offset!
- if (m_physicsActor == null)
- {
- AddToPhysicalScene(false);
+
+ if (m_physicsActor == null)
+ {
+ AddToPhysicalScene(false);
+ }
+ //CW: If the part isn't null then we can set the current position
+ if (part != null)
+ {
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
+ AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
+ part.IsOccupied = false;
+ }
+ else
+ {
+ //CW: Since the part doesn't exist, a coarse standup position isn't an issue
+ AbsolutePosition = m_lastWorldPosition;
}
- AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
- m_parentPosition = Vector3.Zero;
+
+ m_parentPosition = Vector3.Zero;
m_parentID = 0;
- part.IsOccupied = false;
SendFullUpdateToAllClients();
m_requestedSitTargetID = 0;
+
if ((m_physicsActor != null) && (m_avHeight > 0))
{
SetHeight(m_avHeight);
@@ -1778,7 +1800,7 @@ namespace OpenSim.Region.Framework.Scenes
{
if (!part.IsOccupied)
{
-//Console.WriteLine("Scripted, unoccupied");
+//Console.WriteLine("Scripted, unoccupied");
part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
sitOrientation = avSitOrientation; // Change rotatione to the scripted one
@@ -1831,13 +1853,19 @@ namespace OpenSim.Region.Framework.Scenes
// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
{
- autopilot = false; // close enough
+ autopilot = false; // close enough
+ m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
+ Not using the part's position because returning the AV to the last known standing
+ position is likely to be more friendly, isn't it? */
RemoveFromPhysicalScene();
AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
} // else the autopilot will get us close
}
else
- { // its a scripted sit
+ { // its a scripted sit
+ m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
+ I *am* using the part's position this time because we have no real idea how far away
+ the avatar is from the sit target. */
RemoveFromPhysicalScene();
}
}
--
cgit v1.1
From 7371c7662a05d2c1dae1c110905817bb873cf934 Mon Sep 17 00:00:00 2001
From: CasperW
Date: Sat, 26 Dec 2009 18:14:12 +0100
Subject: Fix for landing points. Only one scenario is not fully covered by
this change, and that is people who teleport from neighbouring regions, who
won't get affected by the landing point.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 25 ++++++++++++++++++++----
1 file changed, 21 insertions(+), 4 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a3ad7ca..c3bc96a 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -836,9 +836,24 @@ namespace OpenSim.Region.Framework.Scenes
{
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
pos.Y = crossedBorder.BorderLine.Z - 1;
+ }
+
+ //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
+ //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
+ //they'll bypass the landing point. But I can't think of any decent way of fixing this.
+ if (KnownChildRegionHandles.Count == 0)
+ {
+ ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
+ if (land != null)
+ {
+ //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godlevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ {
+ pos = land.LandData.UserLocation;
+ }
+ }
}
-
if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
{
Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
@@ -973,9 +988,10 @@ namespace OpenSim.Region.Framework.Scenes
public void Teleport(Vector3 pos)
{
bool isFlying = false;
- if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
+ if (m_physicsActor != null)
+ isFlying = m_physicsActor.Flying;
+
RemoveFromPhysicalScene();
Velocity = Vector3.Zero;
AbsolutePosition = pos;
@@ -986,7 +1002,8 @@ namespace OpenSim.Region.Framework.Scenes
SetHeight(m_appearance.AvatarHeight);
}
- SendTerseUpdateToAllClients();
+ SendTerseUpdateToAllClients();
+
}
public void TeleportWithMomentum(Vector3 pos)
--
cgit v1.1
From 689514a40a52d71f9cfaaedbb295a57b1d7c728a Mon Sep 17 00:00:00 2001
From: Melanie
Date: Tue, 9 Mar 2010 23:10:14 +0000
Subject: Cache UserLevel in ScenePresence on SP creation. Change
IsAdministrator to use that stored value.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 28 ++++++++++++++++--------
1 file changed, 19 insertions(+), 9 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 93e66e0..f1be4d8 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -150,7 +150,8 @@ namespace OpenSim.Region.Framework.Scenes
private float m_sitAvatarHeight = 2.0f;
- private float m_godlevel;
+ private int m_godLevel;
+ private int m_userLevel;
private bool m_invulnerable = true;
@@ -304,9 +305,14 @@ namespace OpenSim.Region.Framework.Scenes
get { return m_invulnerable; }
}
- public float GodLevel
+ public int UserLevel
{
- get { return m_godlevel; }
+ get { return m_userLevel; }
+ }
+
+ public int GodLevel
+ {
+ get { return m_godLevel; }
}
public ulong RegionHandle
@@ -678,6 +684,10 @@ namespace OpenSim.Region.Framework.Scenes
m_regionInfo = reginfo;
m_localId = m_scene.AllocateLocalId();
+ UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
+
+ m_userLevel = account.UserLevel;
+
IGroupsModule gm = m_scene.RequestModuleInterface();
if (gm != null)
m_grouptitle = gm.GetGroupTitle(m_uuid);
@@ -3164,17 +3174,17 @@ namespace OpenSim.Region.Framework.Scenes
if (account != null)
{
if (account.UserLevel > 0)
- m_godlevel = account.UserLevel;
+ m_godLevel = account.UserLevel;
else
- m_godlevel = 200;
+ m_godLevel = 200;
}
}
else
{
- m_godlevel = 0;
+ m_godLevel = 0;
}
- ControllingClient.SendAdminResponse(token, (uint)m_godlevel);
+ ControllingClient.SendAdminResponse(token, (uint)m_godLevel);
}
#region Child Agent Updates
@@ -3265,7 +3275,7 @@ namespace OpenSim.Region.Framework.Scenes
cAgent.ControlFlags = (uint)m_AgentControlFlags;
if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
- cAgent.GodLevel = (byte)m_godlevel;
+ cAgent.GodLevel = (byte)m_godLevel;
else
cAgent.GodLevel = (byte) 0;
@@ -3354,7 +3364,7 @@ namespace OpenSim.Region.Framework.Scenes
m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags;
if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
- m_godlevel = cAgent.GodLevel;
+ m_godLevel = cAgent.GodLevel;
m_setAlwaysRun = cAgent.AlwaysRun;
uint i = 0;
--
cgit v1.1
From a1cd3b5b88cc2cc3fcd552085dc9ab46f9d9b10f Mon Sep 17 00:00:00 2001
From: Melanie
Date: Mon, 15 Mar 2010 17:54:39 +0000
Subject: Change GodLevel to UserLevel so gods can teleport freely without
having to enter god mode first
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 24179a9..2661dc3 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -879,7 +879,7 @@ namespace OpenSim.Region.Framework.Scenes
if (land != null)
{
//Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
- if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
{
pos = land.LandData.UserLocation;
}
--
cgit v1.1
From 6df969894c1943dceeefd3765951daaf0a2eb94c Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Wed, 17 Mar 2010 13:30:48 -0400
Subject: Fix AbsolutePosition for autopilot/sit.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 24179a9..608e84c 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -463,7 +463,8 @@ namespace OpenSim.Region.Framework.Scenes
get
{
PhysicsActor actor = m_physicsActor;
- if (actor != null)
+// if (actor != null)
+ if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
m_pos = actor.Position;
return m_parentPosition + m_pos;
@@ -484,7 +485,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- m_pos = value;
+ if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
+ m_pos = value;
m_parentPosition = Vector3.Zero;
}
}
@@ -1267,6 +1269,7 @@ namespace OpenSim.Region.Framework.Scenes
m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
m_pos = m_LastFinitePos;
+
if (!m_pos.IsFinite())
{
m_pos.X = 127f;
@@ -1904,6 +1907,7 @@ namespace OpenSim.Region.Framework.Scenes
{
m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
autopilotTarget = part.AbsolutePosition;
+//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
}
else return; // occupied small
} // end large/small
@@ -2280,7 +2284,8 @@ namespace OpenSim.Region.Framework.Scenes
m_pos += SIT_TARGET_ADJUSTMENT;
m_bodyRot = sitTargetOrient;
m_parentPosition = part.AbsolutePosition;
- part.IsOccupied = true;
+ part.IsOccupied = true;
+Console.WriteLine("Scripted Sit ofset {0}", m_pos);
}
else
{
@@ -3348,6 +3353,7 @@ namespace OpenSim.Region.Framework.Scenes
m_callbackURI = cAgent.CallbackURI;
m_pos = cAgent.Position;
+
m_velocity = cAgent.Velocity;
m_CameraCenter = cAgent.Center;
//m_avHeight = cAgent.Size.Z;
--
cgit v1.1
From 3ea72eeabb12cff4f71523f501450a7df38a17b1 Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Fri, 19 Mar 2010 13:26:34 -0400
Subject: Fix sit with autopilot.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8 +++++---
1 file changed, 5 insertions(+), 3 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 123d6f3..2603fe1 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -455,8 +455,9 @@ namespace OpenSim.Region.Framework.Scenes
get
{
PhysicsActor actor = m_physicsActor;
- if (actor != null)
- m_pos = actor.Position;
+// if (actor != null)
+ if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
+ m_pos = actor.Position;
return m_parentPosition + m_pos;
}
@@ -476,7 +477,8 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- m_pos = value;
+ if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
+ m_pos = value;
m_parentPosition = Vector3.Zero;
}
}
--
cgit v1.1
From 71f42f185a48ef96391b39fa0197c1a8b793e969 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Sat, 24 Apr 2010 16:45:25 +0200
Subject: Plumb a data path to initialize an attachment from an alternate
source
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index c220bf0..a5c0b0d 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3984,7 +3984,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
{
// Rez from inventory
UUID asset
- = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p);
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
m_log.InfoFormat(
"[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
--
cgit v1.1
From 899d521ab41910e09e66849a5c086d7ae32d01a4 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Sat, 24 Apr 2010 18:59:34 +0200
Subject: Use the saved script states
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 37 +++++++++++++++++++++++-
1 file changed, 36 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a5c0b0d..ceb4395 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -26,6 +26,7 @@
*/
using System;
+using System.Xml;
using System.Collections.Generic;
using System.Reflection;
using System.Timers;
@@ -3963,6 +3964,32 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
return;
}
+ XmlDocument doc = new XmlDocument();
+ string stateData = String.Empty;
+
+ IAttachmentsService attServ = m_scene.RequestModuleInterface();
+ if (attServ != null)
+ {
+ m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
+ stateData = attServ.Get(ControllingClient.AgentId.ToString());
+ doc.LoadXml(stateData);
+ }
+
+ Dictionary itemData = new Dictionary();
+
+ XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
+ if (nodes.Count > 0)
+ {
+ foreach (XmlNode n in nodes)
+ {
+ XmlElement elem = (XmlElement)n;
+ string itemID = elem.GetAttribute("ItemID");
+ string xml = elem.InnerXml;
+
+ itemData[new UUID(itemID)] = xml;
+ }
+ }
+
List attPoints = m_appearance.GetAttachedPoints();
foreach (int p in attPoints)
{
@@ -3982,9 +4009,17 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
try
{
+ string xmlData;
+ XmlDocument d = new XmlDocument();
+ if (itemData.TryGetValue(itemID, out xmlData))
+ {
+ d.LoadXml(xmlData);
+ m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
+ }
+
// Rez from inventory
UUID asset
- = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
m_log.InfoFormat(
"[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
--
cgit v1.1
From 87664017773227d07b39382efa2aa94f22bbe6c6 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Mon, 3 May 2010 04:28:30 +0200
Subject: Adapt CM to the new CHANGED_OWNER handling
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 17 +++++++++++++----
1 file changed, 13 insertions(+), 4 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index ceb4395..562232c 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -4011,15 +4011,24 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
{
string xmlData;
XmlDocument d = new XmlDocument();
+ UUID asset;
if (itemData.TryGetValue(itemID, out xmlData))
{
d.LoadXml(xmlData);
m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
- }
- // Rez from inventory
- UUID asset
- = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
+ // Rez from inventory
+ asset
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
+
+ }
+ else
+ {
+ // Rez from inventory (with a null doc to let
+ // CHANGED_OWNER happen)
+ asset
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
+ }
m_log.InfoFormat(
"[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
--
cgit v1.1
From 733a07e061cdcb6095677758a264ba976bb94b93 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Thu, 6 May 2010 00:34:49 +0200
Subject: Plumb the viewer version string through into AgentCircuitData. Now
all that is left os to figure out what black magic turns AgentCircuitData
into AgentData and then copy that into the ScenePresence, where m_Viewer is
already added with this commit and waits for the data.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 ++++++
1 file changed, 6 insertions(+)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 562232c..987180b 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -227,6 +227,7 @@ namespace OpenSim.Region.Framework.Scenes
private int m_lastColCount = -1; //KF: Look for Collision chnages
private int m_updateCount = 0; //KF: Update Anims for a while
private static readonly int UPDATE_COUNT = 10; // how many frames to update for
+ private string m_Viewer = String.Empty;
private const int NumMovementsBetweenRayCast = 5;
@@ -664,6 +665,11 @@ namespace OpenSim.Region.Framework.Scenes
set { m_flyDisabled = value; }
}
+ public string Viewer
+ {
+ get { return m_Viewer; }
+ }
+
#endregion
#region Constructor(s)
--
cgit v1.1
From 2d9a20529d6818093747eb764d86efa11f3874d5 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Thu, 6 May 2010 00:54:21 +0200
Subject: Plumb Viewer version into ScenePresence for initial login. It's still
not carried along
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 1 +
1 file changed, 1 insertion(+)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 987180b..f649dfe 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -668,6 +668,7 @@ namespace OpenSim.Region.Framework.Scenes
public string Viewer
{
get { return m_Viewer; }
+ set { m_Viewer = value; }
}
#endregion
--
cgit v1.1
From 02dea4ce580a08a9a4119ed063ed36704bb44825 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Thu, 6 May 2010 02:02:12 +0200
Subject: Remove the m_Viewer variable and make the property a shortcut to the
proper field in AgentCircuitData instead
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 +----
1 file changed, 1 insertion(+), 4 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index f649dfe..cb24784 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -227,8 +227,6 @@ namespace OpenSim.Region.Framework.Scenes
private int m_lastColCount = -1; //KF: Look for Collision chnages
private int m_updateCount = 0; //KF: Update Anims for a while
private static readonly int UPDATE_COUNT = 10; // how many frames to update for
- private string m_Viewer = String.Empty;
-
private const int NumMovementsBetweenRayCast = 5;
private bool CameraConstraintActive;
@@ -667,8 +665,7 @@ namespace OpenSim.Region.Framework.Scenes
public string Viewer
{
- get { return m_Viewer; }
- set { m_Viewer = value; }
+ get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; }
}
#endregion
--
cgit v1.1
From add7abc1de2fce8db4c6d01cc4b5305bafa4bd87 Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Fri, 7 May 2010 14:12:07 -0400
Subject: Fix Mouse+WASD makes Av rise; Fix PREJUMP.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 23 +++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2603fe1..565438d 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -665,7 +665,7 @@ namespace OpenSim.Region.Framework.Scenes
CreateSceneViewer();
m_animator = new ScenePresenceAnimator(this);
}
-
+
private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
{
m_rootRegionHandle = reginfo.RegionHandle;
@@ -1459,7 +1459,6 @@ namespace OpenSim.Region.Framework.Scenes
}
i++;
}
-
//Paupaw:Do Proper PID for Autopilot here
if (bResetMoveToPosition)
{
@@ -2433,10 +2432,11 @@ namespace OpenSim.Region.Framework.Scenes
Rotation = rotation;
Vector3 direc = vec * rotation;
direc.Normalize();
+ PhysicsActor actor = m_physicsActor;
+ if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
direc *= 0.03f * 128f * m_speedModifier;
- PhysicsActor actor = m_physicsActor;
if (actor != null)
{
if (actor.Flying)
@@ -2458,11 +2458,18 @@ namespace OpenSim.Region.Framework.Scenes
{
if (direc.Z > 2.0f)
{
- direc.Z *= 3.0f;
-
- // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored.
- Animator.TrySetMovementAnimation("PREJUMP");
- Animator.TrySetMovementAnimation("JUMP");
+ if(m_animator.m_animTickJump == -1)
+ {
+ direc.Z *= 3.0f; // jump
+ }
+ else
+ {
+ direc.Z *= 0.1f; // prejump
+ }
+ /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
+ Animator.TrySetMovementAnimation("PREJUMP");
+ Animator.TrySetMovementAnimation("JUMP");
+ */
}
}
}
--
cgit v1.1
From 91b1d17e5bd3ff6ed006744bc529b53a67af1a64 Mon Sep 17 00:00:00 2001
From: Tom Grimshaw
Date: Tue, 18 May 2010 01:09:47 -0700
Subject: Fix for hanging on "Connecting to region".. caused by packets being
processed before the presence has bound to receive events. Fixed this by
adding packets to a queue and then processing them when the presence is
ready.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 102 ++++++++++++-----------
1 file changed, 53 insertions(+), 49 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index d76f029..0b644b9 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -129,7 +129,7 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
- private Vector3 m_lastPosition;
+ private Vector3 m_lastPosition;
private Vector3 m_lastWorldPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
@@ -715,8 +715,11 @@ namespace OpenSim.Region.Framework.Scenes
// Request info about all the (root) agents in this region
// Note: This won't send data *to* other clients in that region (children don't send)
SendInitialFullUpdateToAllClients();
-
RegisterToEvents();
+ if (m_controllingClient != null)
+ {
+ m_controllingClient.ProcessPendingPackets();
+ }
SetDirectionVectors();
}
@@ -858,7 +861,6 @@ namespace OpenSim.Region.Framework.Scenes
m_grouptitle = gm.GetGroupTitle(m_uuid);
m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
-
m_scene.SetRootAgentScene(m_uuid);
// Moved this from SendInitialData to ensure that m_appearance is initialized
@@ -875,22 +877,22 @@ namespace OpenSim.Region.Framework.Scenes
{
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
pos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
- //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
- //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
- //they'll bypass the landing point. But I can't think of any decent way of fixing this.
- if (KnownChildRegionHandles.Count == 0)
- {
- ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
- if (land != null)
- {
- //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
- if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
- {
- pos = land.LandData.UserLocation;
- }
- }
+ }
+
+ //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
+ //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
+ //they'll bypass the landing point. But I can't think of any decent way of fixing this.
+ if (KnownChildRegionHandles.Count == 0)
+ {
+ ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
+ if (land != null)
+ {
+ //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ {
+ pos = land.LandData.UserLocation;
+ }
+ }
}
if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
@@ -1027,8 +1029,8 @@ namespace OpenSim.Region.Framework.Scenes
bool isFlying = false;
if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
+ isFlying = m_physicsActor.Flying;
+
RemoveFromPhysicalScene();
Velocity = Vector3.Zero;
AbsolutePosition = pos;
@@ -1039,7 +1041,7 @@ namespace OpenSim.Region.Framework.Scenes
SetHeight(m_appearance.AvatarHeight);
}
- SendTerseUpdateToAllClients();
+ SendTerseUpdateToAllClients();
}
@@ -1173,7 +1175,6 @@ namespace OpenSim.Region.Framework.Scenes
pos.Z = ground + 1.5f;
AbsolutePosition = pos;
}
-
m_isChildAgent = false;
bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
MakeRootAgent(AbsolutePosition, m_flying);
@@ -1745,14 +1746,14 @@ namespace OpenSim.Region.Framework.Scenes
// else
// { // single or child prim
-// }
- if (part == null) //CW: Part may be gone. llDie() for example.
- {
- partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- partRot = part.GetWorldRotation();
+// }
+ if (part == null) //CW: Part may be gone. llDie() for example.
+ {
+ partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ partRot = part.GetWorldRotation();
}
Quaternion partIRot = Quaternion.Inverse(partRot);
@@ -1760,22 +1761,22 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
-
- if (m_physicsActor == null)
- {
- AddToPhysicalScene(false);
+
+ if (m_physicsActor == null)
+ {
+ AddToPhysicalScene(false);
+ }
+ //CW: If the part isn't null then we can set the current position
+ if (part != null)
+ {
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
+ AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
+ part.IsOccupied = false;
}
- //CW: If the part isn't null then we can set the current position
- if (part != null)
- {
- Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
- AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
- part.IsOccupied = false;
- }
- else
- {
- //CW: Since the part doesn't exist, a coarse standup position isn't an issue
- AbsolutePosition = m_lastWorldPosition;
+ else
+ {
+ //CW: Since the part doesn't exist, a coarse standup position isn't an issue
+ AbsolutePosition = m_lastWorldPosition;
}
m_parentPosition = Vector3.Zero;
@@ -1930,7 +1931,7 @@ namespace OpenSim.Region.Framework.Scenes
// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
{
- autopilot = false; // close enough
+ autopilot = false; // close enough
m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
Not using the part's position because returning the AV to the last known standing
position is likely to be more friendly, isn't it? */
@@ -1939,7 +1940,7 @@ namespace OpenSim.Region.Framework.Scenes
} // else the autopilot will get us close
}
else
- { // its a scripted sit
+ { // its a scripted sit
m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
I *am* using the part's position this time because we have no real idea how far away
the avatar is from the sit target. */
@@ -3744,7 +3745,10 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
m_scene = scene;
RegisterToEvents();
-
+ if (m_controllingClient != null)
+ {
+ m_controllingClient.ProcessPendingPackets();
+ }
/*
AbsolutePosition = client.StartPos;
--
cgit v1.1
From f77f9ecd8f3f94ccc6d69c7625fd1eacfa9250d7 Mon Sep 17 00:00:00 2001
From: Tom Grimshaw
Date: Wed, 19 May 2010 13:44:59 -0700
Subject: Fix a nullref issue in SitAltitudeCallback
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 103 ++++++++++++-----------
1 file changed, 53 insertions(+), 50 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 565438d..68acabe 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -128,7 +128,7 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
- private Vector3 m_lastPosition;
+ private Vector3 m_lastPosition;
private Vector3 m_lastWorldPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
@@ -857,22 +857,22 @@ namespace OpenSim.Region.Framework.Scenes
{
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
pos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
- //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
- //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
- //they'll bypass the landing point. But I can't think of any decent way of fixing this.
- if (KnownChildRegionHandles.Count == 0)
- {
- ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
- if (land != null)
- {
- //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
- if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godlevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
- {
- pos = land.LandData.UserLocation;
- }
- }
+ }
+
+ //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
+ //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
+ //they'll bypass the landing point. But I can't think of any decent way of fixing this.
+ if (KnownChildRegionHandles.Count == 0)
+ {
+ ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
+ if (land != null)
+ {
+ //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_godlevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ {
+ pos = land.LandData.UserLocation;
+ }
+ }
}
if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
@@ -1036,8 +1036,8 @@ namespace OpenSim.Region.Framework.Scenes
bool isFlying = false;
if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
+ isFlying = m_physicsActor.Flying;
+
RemoveFromPhysicalScene();
Velocity = Vector3.Zero;
AbsolutePosition = pos;
@@ -1048,7 +1048,7 @@ namespace OpenSim.Region.Framework.Scenes
SetHeight(m_appearance.AvatarHeight);
}
- SendTerseUpdateToAllClients();
+ SendTerseUpdateToAllClients();
}
@@ -1736,14 +1736,14 @@ namespace OpenSim.Region.Framework.Scenes
// else
// { // single or child prim
-// }
- if (part == null) //CW: Part may be gone. llDie() for example.
- {
- partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- partRot = part.GetWorldRotation();
+// }
+ if (part == null) //CW: Part may be gone. llDie() for example.
+ {
+ partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ partRot = part.GetWorldRotation();
}
Quaternion partIRot = Quaternion.Inverse(partRot);
@@ -1751,22 +1751,22 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
-
- if (m_physicsActor == null)
- {
- AddToPhysicalScene(false);
+
+ if (m_physicsActor == null)
+ {
+ AddToPhysicalScene(false);
}
- //CW: If the part isn't null then we can set the current position
- if (part != null)
- {
- Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
- AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
- part.IsOccupied = false;
- }
- else
- {
- //CW: Since the part doesn't exist, a coarse standup position isn't an issue
- AbsolutePosition = m_lastWorldPosition;
+ //CW: If the part isn't null then we can set the current position
+ if (part != null)
+ {
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
+ AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
+ part.IsOccupied = false;
+ }
+ else
+ {
+ //CW: Since the part doesn't exist, a coarse standup position isn't an issue
+ AbsolutePosition = m_lastWorldPosition;
}
m_parentPosition = Vector3.Zero;
@@ -1920,7 +1920,7 @@ namespace OpenSim.Region.Framework.Scenes
// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
{
- autopilot = false; // close enough
+ autopilot = false; // close enough
m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
Not using the part's position because returning the AV to the last known standing
position is likely to be more friendly, isn't it? */
@@ -1929,7 +1929,7 @@ namespace OpenSim.Region.Framework.Scenes
} // else the autopilot will get us close
}
else
- { // its a scripted sit
+ { // its a scripted sit
m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
I *am* using the part's position this time because we have no real idea how far away
the avatar is from the sit target. */
@@ -2357,11 +2357,14 @@ namespace OpenSim.Region.Framework.Scenes
// { // single or child prim
partIRot = Quaternion.Inverse(part.GetWorldRotation());
// }
- float offZ = collisionPoint.Z - m_initialSitTarget.Z;
- Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
-//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
- m_pos += offset;
-// ControllingClient.SendClearFollowCamProperties(part.UUID);
+ if (m_initialSitTarget != null)
+ {
+ float offZ = collisionPoint.Z - m_initialSitTarget.Z;
+ Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
+ //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
+ m_pos += offset;
+ // ControllingClient.SendClearFollowCamProperties(part.UUID);
+ }
}
} // End SitAltitudeCallback KF.
--
cgit v1.1
From 6933b48a7e94511f1de969b28a61d834888fd2f5 Mon Sep 17 00:00:00 2001
From: Tom Grimshaw
Date: Wed, 19 May 2010 13:49:34 -0700
Subject: Fix a nullref issue in SitAltitudeCallback
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 15 +++++++++------
1 file changed, 9 insertions(+), 6 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 0b644b9..b6081de 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2368,12 +2368,15 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
// else
// { // single or child prim
partIRot = Quaternion.Inverse(part.GetWorldRotation());
-// }
- float offZ = collisionPoint.Z - m_initialSitTarget.Z;
- Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
-//Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
- m_pos += offset;
-// ControllingClient.SendClearFollowCamProperties(part.UUID);
+// }
+ if (m_initialSitTarget != null)
+ {
+ float offZ = collisionPoint.Z - m_initialSitTarget.Z;
+ Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
+ //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
+ m_pos += offset;
+ // ControllingClient.SendClearFollowCamProperties(part.UUID);
+ }
}
} // End SitAltitudeCallback KF.
--
cgit v1.1
From 5532341bf9e477a007e81bdbcc6477923703e2a2 Mon Sep 17 00:00:00 2001
From: Tom Grimshaw
Date: Wed, 19 May 2010 14:04:44 -0700
Subject: Initialise m_initialSitTarget to ZERO_VACTOR for safety's sake as per
convo with kitto
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index b6081de..c89f656 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -213,7 +213,7 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_autopilotMoving;
private Vector3 m_autoPilotTarget;
private bool m_sitAtAutoTarget;
- private Vector3 m_initialSitTarget; //KF: First estimate of where to sit
+ private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
private string m_nextSitAnimation = String.Empty;
--
cgit v1.1
From 72b96e81213c0dd3d586f552bd2cbd9221c5341d Mon Sep 17 00:00:00 2001
From: Melanie
Date: Sun, 23 May 2010 06:12:11 +0100
Subject: Add the SitGround flag back in
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 49a7766..d7660fd 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -140,6 +140,7 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3? m_forceToApply;
private uint m_requestedSitTargetID;
private UUID m_requestedSitTargetUUID;
+ public bool SitGround = false;
private SendCourseLocationsMethod m_sendCourseLocationsMethod;
@@ -1643,7 +1644,7 @@ namespace OpenSim.Region.Framework.Scenes
}
}
- if (update_movementflag)
+ if (update_movementflag && !SitGround)
Animator.UpdateMovementAnimations();
m_scene.EventManager.TriggerOnClientMovement(this);
@@ -1754,6 +1755,8 @@ namespace OpenSim.Region.Framework.Scenes
///
public void StandUp()
{
+ SitGround = false;
+
if (m_parentID != 0)
{
SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
--
cgit v1.1
From 62763cc0fb80caae199ea03d2cb8d031924c111e Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Mon, 14 Jun 2010 00:02:17 +0200
Subject: Report current position instead of position at the time we sat down
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 7 +++++++
1 file changed, 7 insertions(+)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index b6f67f7..7a7816a 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -466,6 +466,13 @@ namespace OpenSim.Region.Framework.Scenes
if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
m_pos = actor.Position;
+ // If we're sitting, we need to update our position
+ if (m_parentID == 0)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
+ m_parentPosition = part.AbsolutePosition;
+ }
+
return m_parentPosition + m_pos;
}
set
--
cgit v1.1
From 1532dbca0ae54ee6427153d7beec95b8cb52e1e3 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Mon, 14 Jun 2010 00:12:39 +0200
Subject: Guard against a potential nullref
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 7a7816a..9c507c2 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -470,7 +470,8 @@ namespace OpenSim.Region.Framework.Scenes
if (m_parentID == 0)
{
SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
- m_parentPosition = part.AbsolutePosition;
+ if (part != null)
+ m_parentPosition = part.AbsolutePosition;
}
return m_parentPosition + m_pos;
--
cgit v1.1
From 9b30f446729e16c165551ecf0756dedb85d8b269 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Mon, 14 Jun 2010 02:28:31 +0200
Subject: D.U.H. #2. Inverted test. Again. Argh!
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 9c507c2..6d2cd88 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -467,7 +467,7 @@ namespace OpenSim.Region.Framework.Scenes
m_pos = actor.Position;
// If we're sitting, we need to update our position
- if (m_parentID == 0)
+ if (m_parentID != 0)
{
SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
if (part != null)
--
cgit v1.1
From 49d7d8534ccd037f4690c5ac6aecd66a460960df Mon Sep 17 00:00:00 2001
From: Tom Grimshaw
Date: Sat, 19 Jun 2010 10:06:09 -0700
Subject: Allow moving an avatar as part of a linkset using
llSetLinkPrimitiveParams. This unlocks an awful lot of poseball-free content,
and is a step towards resolving mantis #59.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 39 ++++++++++++++++++++++--
1 file changed, 37 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index d4fc6cd..76267ab 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -219,6 +219,7 @@ namespace OpenSim.Region.Framework.Scenes
//PauPaw:Proper PID Controler for autopilot************
private bool m_moveToPositionInProgress;
private Vector3 m_moveToPositionTarget;
+ private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
private bool m_followCamAuto;
@@ -537,10 +538,39 @@ namespace OpenSim.Region.Framework.Scenes
}
}
+ public Quaternion OffsetRotation
+ {
+ get { return m_offsetRotation; }
+ set { m_offsetRotation = value; }
+ }
+
public Quaternion Rotation
{
- get { return m_bodyRot; }
- set { m_bodyRot = value; }
+ get {
+ if (m_parentID != 0)
+ {
+ if (m_offsetRotation != null)
+ {
+ return m_offsetRotation;
+ }
+ else
+ {
+ return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ }
+ else
+ {
+ return m_bodyRot;
+ }
+ }
+ set {
+ m_bodyRot = value;
+ if (m_parentID != 0)
+ {
+ m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ }
}
public Quaternion PreviousRotation
@@ -1795,6 +1825,7 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
part.IsOccupied = false;
+ part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
}
else
{
@@ -1804,6 +1835,7 @@ namespace OpenSim.Region.Framework.Scenes
m_parentPosition = Vector3.Zero;
m_parentID = 0;
+ m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
SendFullUpdateToAllClients();
m_requestedSitTargetID = 0;
@@ -1904,6 +1936,7 @@ namespace OpenSim.Region.Framework.Scenes
part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
sitOrientation = avSitOrientation; // Change rotatione to the scripted one
+ OffsetRotation = avSitOrientation;
autopilot = false; // Jump direct to scripted llSitPos()
}
else
@@ -2311,6 +2344,7 @@ namespace OpenSim.Region.Framework.Scenes
m_bodyRot = sitTargetOrient;
m_parentPosition = part.AbsolutePosition;
part.IsOccupied = true;
+ part.ParentGroup.AddAvatar(agentID);
Console.WriteLine("Scripted Sit ofset {0}", m_pos);
}
else
@@ -2341,6 +2375,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
m_parentPosition = part.AbsolutePosition;
part.IsOccupied = true;
+ part.ParentGroup.AddAvatar(agentID);
m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
(new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
(new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
--
cgit v1.1
From fc715a092c9b48ddfbf75eb35e1a052885aecbff Mon Sep 17 00:00:00 2001
From: Tom Grimshaw
Date: Sun, 20 Jun 2010 15:38:48 -0700
Subject: Fix the sit code to ensure that we use the root prim of a linkset as
a reference in the case of an avatar sitting on a child prim. This fixes
various camera issues and fixes mantis #0000059.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 18 +++++++++++++++---
1 file changed, 15 insertions(+), 3 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 76267ab..472c389 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1766,7 +1766,7 @@ namespace OpenSim.Region.Framework.Scenes
if (m_parentID != 0)
{
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
if (part != null)
{
part.TaskInventory.LockItemsForRead(true);
@@ -2028,7 +2028,9 @@ namespace OpenSim.Region.Framework.Scenes
//Console.WriteLine("Camera At ={0}", cameraAtOffset);
//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
- ControllingClient.SendSitResponse(part.UUID, offsetr, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
+ ControllingClient.SendSitResponse(part.ParentGroup.UUID, offsetr + part.OffsetPosition, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+
m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
// This calls HandleAgentSit twice, once from here, and the client calls
// HandleAgentSit itself after it gets to the location
@@ -2398,7 +2400,17 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
return;
}
}
- m_parentID = m_requestedSitTargetID;
+
+ //We want our offsets to reference the root prim, not the child we may have sat on
+ if (!part.IsRoot)
+ {
+ m_parentID = part.ParentGroup.RootPart.LocalId;
+ m_pos += part.OffsetPosition;
+ }
+ else
+ {
+ m_parentID = m_requestedSitTargetID;
+ }
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
--
cgit v1.1
From 9d251b1dc518522979b73fdadc0329067b669149 Mon Sep 17 00:00:00 2001
From: Tom Grimshaw
Date: Sun, 20 Jun 2010 15:57:01 -0700
Subject: Fix the StandUp position to calculate as if we're still using the
child prim id.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 472c389..a376ab1 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1822,7 +1822,7 @@ namespace OpenSim.Region.Framework.Scenes
//CW: If the part isn't null then we can set the current position
if (part != null)
{
- Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
part.IsOccupied = false;
part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
--
cgit v1.1
From 962dade15596d0aeff3baba0b0b85c17524766c6 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Tue, 22 Jun 2010 04:04:59 +0200
Subject: Cause collisions with the avatar to be sent to attachments. Currently
ignores collision filter. Physics collisions are still dodgy, so we don't get
the events we should be getting.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 140 +++++++++++++++++++++++
1 file changed, 140 insertions(+)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index a376ab1..654e9ce 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -228,6 +228,7 @@ namespace OpenSim.Region.Framework.Scenes
private int m_updateCount = 0; //KF: Update Anims for a while
private static readonly int UPDATE_COUNT = 10; // how many frames to update for
private const int NumMovementsBetweenRayCast = 5;
+ private List m_lastColliders = new List();
private bool CameraConstraintActive;
//private int m_moveToPositionStateStatus;
@@ -3595,6 +3596,145 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
}
}
+ List thisHitColliders = new List();
+ List endedColliders = new List();
+ List startedColliders = new List();
+
+ foreach (uint localid in coldata.Keys)
+ {
+ thisHitColliders.Add(localid);
+ if (!m_lastColliders.Contains(localid))
+ {
+ startedColliders.Add(localid);
+ }
+ //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
+ }
+
+ // calculate things that ended colliding
+ foreach (uint localID in m_lastColliders)
+ {
+ if (!thisHitColliders.Contains(localID))
+ {
+ endedColliders.Add(localID);
+ }
+ }
+ //add the items that started colliding this time to the last colliders list.
+ foreach (uint localID in startedColliders)
+ {
+ m_lastColliders.Add(localID);
+ }
+ // remove things that ended colliding from the last colliders list
+ foreach (uint localID in endedColliders)
+ {
+ m_lastColliders.Remove(localID);
+ }
+
+ // do event notification
+ if (startedColliders.Count > 0)
+ {
+ ColliderArgs StartCollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in startedColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ StartCollidingMessage.Colliders = colliding;
+
+ foreach (SceneObjectGroup att in Attachments)
+ Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
+ }
+ }
+
+ if (endedColliders.Count > 0)
+ {
+ ColliderArgs EndCollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in endedColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ EndCollidingMessage.Colliders = colliding;
+
+ foreach (SceneObjectGroup att in Attachments)
+ Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
+ }
+ }
+
+ if (thisHitColliders.Count > 0)
+ {
+ ColliderArgs CollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in thisHitColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ CollidingMessage.Colliders = colliding;
+
+ foreach (SceneObjectGroup att in Attachments)
+ Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
+ }
+ }
+
if (m_invulnerable)
return;
--
cgit v1.1
From 6274317e63e18785a2c3d96514ca371e0a04cf71 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Sat, 26 Jun 2010 06:16:24 +0200
Subject: Fix loading of attachments on login
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 654e9ce..4a4cac9 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -4151,7 +4151,14 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
{
m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
stateData = attServ.Get(ControllingClient.AgentId.ToString());
- doc.LoadXml(stateData);
+ if (stateData != String.Empty)
+ {
+ try
+ {
+ doc.LoadXml(stateData);
+ }
+ catch { }
+ }
}
Dictionary itemData = new Dictionary();
--
cgit v1.1
From edcfaf60c99b7cde324621c2ffcfbb16e4eb4c5e Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Sat, 3 Jul 2010 20:27:00 +0200
Subject: Fix IMs the right way. This sets it up so that timestamps are
actually in PST (to match viewer time), does correct storage and retrieval of
IMs, corrects the session ID and makes sure IMs don't get marked "saved" if
they're live. Removes the group IM save option, which our group IM module
never had in the first place, as saving group chatter makes no sense at all.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 4a4cac9..e51d9ee 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3730,8 +3730,11 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
{
CollidingMessage.Colliders = colliding;
- foreach (SceneObjectGroup att in Attachments)
- Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
+ lock (m_attachments)
+ {
+ foreach (SceneObjectGroup att in m_attachments)
+ Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
+ }
}
}
--
cgit v1.1
From 7f0f11304f0979355d75538ab7326b687b62e76e Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Sun, 11 Jul 2010 14:26:57 +0200
Subject: Add scripted controllers into agent intersim messaging
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 33 ++++++++++++++++++++++++
1 file changed, 33 insertions(+)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5ac7755..efe3365 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3365,6 +3365,18 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
cAgent.Attachments = attachs;
}
+ lock (scriptedcontrols)
+ {
+ ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
+ int i = 0;
+
+ foreach (ScriptControllers c in scriptedcontrols.Values)
+ {
+ controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
+ }
+ cAgent.Controllers = controls;
+ }
+
// Animations
try
{
@@ -3446,6 +3458,27 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
}
catch { }
+ try
+ {
+ lock (scriptedcontrols)
+ {
+ if (cAgent.Controllers != null)
+ {
+ scriptedcontrols.Clear();
+
+ foreach (ControllerData c in cAgent.Controllers)
+ {
+ ScriptControllers sc = new ScriptControllers();
+ sc.itemID = c.ItemID;
+ sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
+ sc.eventControls = (ScriptControlled)c.EventControls;
+
+ scriptedcontrols[sc.itemID] = sc;
+ }
+ }
+ }
+ }
+ catch { }
// Animations
try
{
--
cgit v1.1
From ae99c1393d4555d4cd26249b149078e4cd3d439f Mon Sep 17 00:00:00 2001
From: Tom
Date: Tue, 3 Aug 2010 15:31:04 -0700
Subject: Fix scripted sit offset in child prims
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 18 ++++++++++++++----
1 file changed, 14 insertions(+), 4 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index efe3365..1fc4a81 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1935,8 +1935,14 @@ namespace OpenSim.Region.Framework.Scenes
//Console.WriteLine("Scripted, unoccupied");
part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
- sitOrientation = avSitOrientation; // Change rotatione to the scripted one
- OffsetRotation = avSitOrientation;
+
+ Quaternion nrot = avSitOrientation;
+ if (!part.IsRoot)
+ {
+ nrot = nrot * part.RotationOffset;
+ }
+ sitOrientation = nrot; // Change rotatione to the scripted one
+ OffsetRotation = nrot;
autopilot = false; // Jump direct to scripted llSitPos()
}
else
@@ -2010,7 +2016,7 @@ namespace OpenSim.Region.Framework.Scenes
// offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
// if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
// { // Single, or Root prim of linkset, target is ClickOffset * RootRot
- offsetr = offset * partIRot;
+ //offsetr = offset * partIRot;
//
// else
// { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
@@ -2029,7 +2035,7 @@ namespace OpenSim.Region.Framework.Scenes
//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
//NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
- ControllingClient.SendSitResponse(part.ParentGroup.UUID, offsetr + part.OffsetPosition, sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
// This calls HandleAgentSit twice, once from here, and the client calls
@@ -2343,6 +2349,10 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion sitTargetOrient = part.SitTargetOrientation;
m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
m_pos += SIT_TARGET_ADJUSTMENT;
+ if (!part.IsRoot)
+ {
+ m_pos *= part.RotationOffset;
+ }
m_bodyRot = sitTargetOrient;
m_parentPosition = part.AbsolutePosition;
part.IsOccupied = true;
--
cgit v1.1
From f1c51c8bb4c634cedf9eb57a1bb339d3e8052b10 Mon Sep 17 00:00:00 2001
From: Tom
Date: Tue, 3 Aug 2010 19:51:32 -0700
Subject: Scripted sit target fixes
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 1fc4a81..d857a1c 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1939,7 +1939,7 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion nrot = avSitOrientation;
if (!part.IsRoot)
{
- nrot = nrot * part.RotationOffset;
+ nrot = part.RotationOffset * avSitOrientation;
}
sitOrientation = nrot; // Change rotatione to the scripted one
OffsetRotation = nrot;
--
cgit v1.1
From c5c6627adb79644b93c5871243a9eeeff553829c Mon Sep 17 00:00:00 2001
From: Tom
Date: Fri, 6 Aug 2010 02:39:42 -0700
Subject: Implement CHANGED_REGION_(RE)START and also fix various CHANGED_*
constants which had the wrong values (checked using LSL in SL). This
addresses mantis #217 and mantis #53.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index d857a1c..5fcd1c2 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3939,7 +3939,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
if (m == null) // No script engine loaded
continue;
- m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { 16384 });
+ m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
}
}
}
--
cgit v1.1
From a636af13e77aae588f425b7bc9504854a7ed1261 Mon Sep 17 00:00:00 2001
From: Tom
Date: Fri, 6 Aug 2010 06:37:40 -0700
Subject: Make sure the avatar position gets moved along with a prim it is
sitting on. This fixes mantis #208 and (maybe) issues with chat and sound
coming from the wrong place when sat on a vehicle.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 13 +++++++++++++
1 file changed, 13 insertions(+)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5fcd1c2..44c3d12 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -595,11 +595,21 @@ namespace OpenSim.Region.Framework.Scenes
private uint m_parentID;
+
+ private UUID m_linkedPrim;
+
public uint ParentID
{
get { return m_parentID; }
set { m_parentID = value; }
}
+
+ public UUID LinkedPrim
+ {
+ get { return m_linkedPrim; }
+ set { m_linkedPrim = value; }
+ }
+
public float Health
{
get { return m_health; }
@@ -1835,6 +1845,7 @@ namespace OpenSim.Region.Framework.Scenes
m_parentPosition = Vector3.Zero;
m_parentID = 0;
+ m_linkedPrim = UUID.Zero;
m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
SendFullUpdateToAllClients();
m_requestedSitTargetID = 0;
@@ -2422,6 +2433,8 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
m_parentID = m_requestedSitTargetID;
}
+ m_linkedPrim = part.UUID;
+
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
--
cgit v1.1
From 413b0525db81ebc39a3a79cc2763553058056a5c Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 11:06:07 -0700
Subject: It seems hippo disregards velocities in full updates, so also send a
terse update when an agent sits to avoid drifting off
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8656 +++++++++++-----------
1 file changed, 4328 insertions(+), 4328 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index b3fa2f4..882f4a7 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1,4328 +1,4328 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Xml;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Timers;
-using OpenMetaverse;
-using log4net;
-using OpenSim.Framework;
-using OpenSim.Framework.Client;
-using OpenSim.Region.Framework.Interfaces;
-using OpenSim.Region.Framework.Scenes.Animation;
-using OpenSim.Region.Framework.Scenes.Types;
-using OpenSim.Region.Physics.Manager;
-using GridRegion = OpenSim.Services.Interfaces.GridRegion;
-using OpenSim.Services.Interfaces;
-
-namespace OpenSim.Region.Framework.Scenes
-{
- enum ScriptControlled : uint
- {
- CONTROL_ZERO = 0,
- CONTROL_FWD = 1,
- CONTROL_BACK = 2,
- CONTROL_LEFT = 4,
- CONTROL_RIGHT = 8,
- CONTROL_UP = 16,
- CONTROL_DOWN = 32,
- CONTROL_ROT_LEFT = 256,
- CONTROL_ROT_RIGHT = 512,
- CONTROL_LBUTTON = 268435456,
- CONTROL_ML_LBUTTON = 1073741824
- }
-
- struct ScriptControllers
- {
- public UUID itemID;
- public ScriptControlled ignoreControls;
- public ScriptControlled eventControls;
- }
-
- public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs);
-
- public class ScenePresence : EntityBase, ISceneEntity
- {
-// ~ScenePresence()
-// {
-// m_log.Debug("[ScenePresence] Destructor called");
-// }
-
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
-// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
- private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
- private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
-
- ///
- /// Experimentally determined "fudge factor" to make sit-target positions
- /// the same as in SecondLife. Fudge factor was tested for 36 different
- /// test cases including prims of type box, sphere, cylinder, and torus,
- /// with varying parameters for sit target location, prim size, prim
- /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
- /// issue #1716
- ///
-// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
- // Value revised by KF 091121 by comparison with SL.
- private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
-
- public UUID currentParcelUUID = UUID.Zero;
-
- private ISceneViewer m_sceneViewer;
-
- ///
- /// The animator for this avatar
- ///
- public ScenePresenceAnimator Animator
- {
- get { return m_animator; }
- }
- protected ScenePresenceAnimator m_animator;
-
- ///
- /// The scene objects attached to this avatar. Do not change this list directly - use methods such as
- /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it.
- ///
- public List Attachments
- {
- get { return m_attachments; }
- }
- protected List m_attachments = new List();
-
- private Dictionary scriptedcontrols = new Dictionary();
- private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
- private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
- private bool MouseDown = false;
- private SceneObjectGroup proxyObjectGroup;
- //private SceneObjectPart proxyObjectPart = null;
- public Vector3 lastKnownAllowedPosition;
- public bool sentMessageAboutRestrictedParcelFlyingDown;
- public Vector4 CollisionPlane = Vector4.UnitW;
-
- private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
- private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
- private Vector3 m_lastPosition;
- private Vector3 m_lastWorldPosition;
- private Quaternion m_lastRotation;
- private Vector3 m_lastVelocity;
- //private int m_lastTerseSent;
-
- private bool m_updateflag;
- private byte m_movementflag;
- private Vector3? m_forceToApply;
- private uint m_requestedSitTargetID;
- private UUID m_requestedSitTargetUUID;
- public bool SitGround = false;
-
- private SendCourseLocationsMethod m_sendCourseLocationsMethod;
-
- private bool m_startAnimationSet;
-
- //private Vector3 m_requestedSitOffset = new Vector3();
-
- private Vector3 m_LastFinitePos;
-
- private float m_sitAvatarHeight = 2.0f;
-
- private int m_godLevel;
- private int m_userLevel;
-
- private bool m_invulnerable = true;
-
- private Vector3 m_lastChildAgentUpdatePosition;
- private Vector3 m_lastChildAgentUpdateCamPosition;
-
- private int m_perfMonMS;
-
- private bool m_setAlwaysRun;
- private bool m_forceFly;
- private bool m_flyDisabled;
-
- private float m_speedModifier = 1.0f;
-
- private Quaternion m_bodyRot= Quaternion.Identity;
-
- private Quaternion m_bodyRotPrevious = Quaternion.Identity;
-
- private const int LAND_VELOCITYMAG_MAX = 12;
-
- public bool IsRestrictedToRegion;
-
- public string JID = String.Empty;
-
- private float m_health = 100f;
-
- // Default AV Height
- private float m_avHeight = 127.0f;
-
- protected RegionInfo m_regionInfo;
- protected ulong crossingFromRegion;
-
- private readonly Vector3[] Dir_Vectors = new Vector3[11];
- private bool m_isNudging = false;
-
- // Position of agent's camera in world (region cordinates)
- protected Vector3 m_CameraCenter;
- protected Vector3 m_lastCameraCenter;
-
- protected Timer m_reprioritization_timer;
- protected bool m_reprioritizing;
- protected bool m_reprioritization_called;
-
- // Use these three vectors to figure out what the agent is looking at
- // Convert it to a Matrix and/or Quaternion
- protected Vector3 m_CameraAtAxis;
- protected Vector3 m_CameraLeftAxis;
- protected Vector3 m_CameraUpAxis;
- private AgentManager.ControlFlags m_AgentControlFlags;
- private Quaternion m_headrotation = Quaternion.Identity;
- private byte m_state;
-
- //Reuse the Vector3 instead of creating a new one on the UpdateMovement method
-// private Vector3 movementvector;
-
- private bool m_autopilotMoving;
- private Vector3 m_autoPilotTarget;
- private bool m_sitAtAutoTarget;
- private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
-
- private string m_nextSitAnimation = String.Empty;
-
- //PauPaw:Proper PID Controler for autopilot************
- private bool m_moveToPositionInProgress;
- private Vector3 m_moveToPositionTarget;
- private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
-
- private bool m_followCamAuto;
-
- private int m_movementUpdateCount;
- private int m_lastColCount = -1; //KF: Look for Collision chnages
- private int m_updateCount = 0; //KF: Update Anims for a while
- private static readonly int UPDATE_COUNT = 10; // how many frames to update for
- private const int NumMovementsBetweenRayCast = 5;
- private List m_lastColliders = new List();
-
- private bool CameraConstraintActive;
- //private int m_moveToPositionStateStatus;
- //*****************************************************
-
- // Agent's Draw distance.
- protected float m_DrawDistance;
-
- protected AvatarAppearance m_appearance;
-
- // neighbouring regions we have enabled a child agent in
- // holds the seed cap for the child agent in that region
- private Dictionary m_knownChildRegions = new Dictionary();
-
- ///
- /// Implemented Control Flags
- ///
- private enum Dir_ControlFlags
- {
- DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
- DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
- DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
- DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
- DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
- DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
- DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
- DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
- DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
- DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
- DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
- }
-
- ///
- /// Position at which a significant movement was made
- ///
- private Vector3 posLastSignificantMove;
-
- // For teleports and crossings callbacks
- string m_callbackURI;
- UUID m_originRegionID;
-
- ulong m_rootRegionHandle;
-
- ///
- /// Script engines present in the scene
- ///
- private IScriptModule[] m_scriptEngines;
-
- #region Properties
-
- ///
- /// Physical scene representation of this Avatar.
- ///
- public PhysicsActor PhysicsActor
- {
- set { m_physicsActor = value; }
- get { return m_physicsActor; }
- }
-
- public byte MovementFlag
- {
- set { m_movementflag = value; }
- get { return m_movementflag; }
- }
-
- public bool Updated
- {
- set { m_updateflag = value; }
- get { return m_updateflag; }
- }
-
- public bool Invulnerable
- {
- set { m_invulnerable = value; }
- get { return m_invulnerable; }
- }
-
- public int UserLevel
- {
- get { return m_userLevel; }
- }
-
- public int GodLevel
- {
- get { return m_godLevel; }
- }
-
- public ulong RegionHandle
- {
- get { return m_rootRegionHandle; }
- }
-
- public Vector3 CameraPosition
- {
- get { return m_CameraCenter; }
- }
-
- public Quaternion CameraRotation
- {
- get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); }
- }
-
- public Vector3 CameraAtAxis
- {
- get { return m_CameraAtAxis; }
- }
-
- public Vector3 CameraLeftAxis
- {
- get { return m_CameraLeftAxis; }
- }
-
- public Vector3 CameraUpAxis
- {
- get { return m_CameraUpAxis; }
- }
-
- public Vector3 Lookat
- {
- get
- {
- Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0);
-
- if (a == Vector3.Zero)
- return a;
-
- return Util.GetNormalizedVector(a);
- }
- }
-
- private readonly string m_firstname;
-
- public string Firstname
- {
- get { return m_firstname; }
- }
-
- private readonly string m_lastname;
-
- public string Lastname
- {
- get { return m_lastname; }
- }
-
- private string m_grouptitle;
-
- public string Grouptitle
- {
- get { return m_grouptitle; }
- set { m_grouptitle = value; }
- }
-
- public float DrawDistance
- {
- get { return m_DrawDistance; }
- }
-
- protected bool m_allowMovement = true;
-
- public bool AllowMovement
- {
- get { return m_allowMovement; }
- set { m_allowMovement = value; }
- }
-
- public bool SetAlwaysRun
- {
- get
- {
- if (PhysicsActor != null)
- {
- return PhysicsActor.SetAlwaysRun;
- }
- else
- {
- return m_setAlwaysRun;
- }
- }
- set
- {
- m_setAlwaysRun = value;
- if (PhysicsActor != null)
- {
- PhysicsActor.SetAlwaysRun = value;
- }
- }
- }
-
- public byte State
- {
- get { return m_state; }
- set { m_state = value; }
- }
-
- public uint AgentControlFlags
- {
- get { return (uint)m_AgentControlFlags; }
- set { m_AgentControlFlags = (AgentManager.ControlFlags)value; }
- }
-
- ///
- /// This works out to be the ClientView object associated with this avatar, or it's client connection manager
- ///
- private IClientAPI m_controllingClient;
-
- protected PhysicsActor m_physicsActor;
-
- ///
- /// The client controlling this presence
- ///
- public IClientAPI ControllingClient
- {
- get { return m_controllingClient; }
- }
-
- public IClientCore ClientView
- {
- get { return (IClientCore) m_controllingClient; }
- }
-
- protected Vector3 m_parentPosition;
- public Vector3 ParentPosition
- {
- get { return m_parentPosition; }
- set { m_parentPosition = value; }
- }
-
- ///
- /// Position of this avatar relative to the region the avatar is in
- ///
- public override Vector3 AbsolutePosition
- {
- get
- {
- PhysicsActor actor = m_physicsActor;
-// if (actor != null)
- if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
- m_pos = actor.Position;
-
- // If we're sitting, we need to update our position
- if (m_parentID != 0)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
- if (part != null)
- m_parentPosition = part.AbsolutePosition;
- }
-
- return m_parentPosition + m_pos;
- }
- set
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- {
- try
- {
- lock (m_scene.SyncRoot)
- m_physicsActor.Position = value;
- }
- catch (Exception e)
- {
- m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
- }
- }
-
- if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
- m_pos = value;
- m_parentPosition = Vector3.Zero;
- }
- }
-
- public Vector3 OffsetPosition
- {
- get { return m_pos; }
- set { m_pos = value; }
- }
-
- ///
- /// Current velocity of the avatar.
- ///
- public override Vector3 Velocity
- {
- get
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- m_velocity = actor.Velocity;
-
- return m_velocity;
- }
- set
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- {
- try
- {
- lock (m_scene.SyncRoot)
- actor.Velocity = value;
- }
- catch (Exception e)
- {
- m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message);
- }
- }
-
- m_velocity = value;
- }
- }
-
- public Quaternion OffsetRotation
- {
- get { return m_offsetRotation; }
- set { m_offsetRotation = value; }
- }
-
- public Quaternion Rotation
- {
- get {
- if (m_parentID != 0)
- {
- if (m_offsetRotation != null)
- {
- return m_offsetRotation;
- }
- else
- {
- return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
-
- }
- else
- {
- return m_bodyRot;
- }
- }
- set {
- m_bodyRot = value;
- if (m_parentID != 0)
- {
- m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- }
- }
-
- public Quaternion PreviousRotation
- {
- get { return m_bodyRotPrevious; }
- set { m_bodyRotPrevious = value; }
- }
-
- ///
- /// If this is true, agent doesn't have a representation in this scene.
- /// this is an agent 'looking into' this scene from a nearby scene(region)
- ///
- /// if False, this agent has a representation in this scene
- ///
- private bool m_isChildAgent = true;
-
- public bool IsChildAgent
- {
- get { return m_isChildAgent; }
- set { m_isChildAgent = value; }
- }
-
- private uint m_parentID;
-
-
- private UUID m_linkedPrim;
-
- public uint ParentID
- {
- get { return m_parentID; }
- set { m_parentID = value; }
- }
-
- public UUID LinkedPrim
- {
- get { return m_linkedPrim; }
- set { m_linkedPrim = value; }
- }
-
- public float Health
- {
- get { return m_health; }
- set { m_health = value; }
- }
-
- ///
- /// These are the region handles known by the avatar.
- ///
- public List KnownChildRegionHandles
- {
- get
- {
- if (m_knownChildRegions.Count == 0)
- return new List();
- else
- return new List(m_knownChildRegions.Keys);
- }
- }
-
- public Dictionary KnownRegions
- {
- get { return m_knownChildRegions; }
- set
- {
- m_knownChildRegions = value;
- }
- }
-
- public ISceneViewer SceneViewer
- {
- get { return m_sceneViewer; }
- }
-
- public void AdjustKnownSeeds()
- {
- Dictionary seeds;
-
- if (Scene.CapsModule != null)
- seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
- else
- seeds = new Dictionary();
-
- List old = new List();
- foreach (ulong handle in seeds.Keys)
- {
- uint x, y;
- Utils.LongToUInts(handle, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
- if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
- {
- old.Add(handle);
- }
- }
- DropOldNeighbours(old);
-
- if (Scene.CapsModule != null)
- Scene.CapsModule.SetChildrenSeed(UUID, seeds);
-
- KnownRegions = seeds;
- //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
- //DumpKnownRegions();
- }
-
- public void DumpKnownRegions()
- {
- m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================");
- foreach (KeyValuePair kvp in KnownRegions)
- {
- uint x, y;
- Utils.LongToUInts(kvp.Key, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
- m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
- }
- }
-
- private bool m_inTransit;
- private bool m_mouseLook;
- private bool m_leftButtonDown;
-
- public bool IsInTransit
- {
- get { return m_inTransit; }
- set { m_inTransit = value; }
- }
-
- public float SpeedModifier
- {
- get { return m_speedModifier; }
- set { m_speedModifier = value; }
- }
-
- public bool ForceFly
- {
- get { return m_forceFly; }
- set { m_forceFly = value; }
- }
-
- public bool FlyDisabled
- {
- get { return m_flyDisabled; }
- set { m_flyDisabled = value; }
- }
-
- public string Viewer
- {
- get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; }
- }
-
- #endregion
-
- #region Constructor(s)
-
- public ScenePresence()
- {
- m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
- CreateSceneViewer();
- m_animator = new ScenePresenceAnimator(this);
- }
-
- private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
- {
- m_rootRegionHandle = reginfo.RegionHandle;
- m_controllingClient = client;
- m_firstname = m_controllingClient.FirstName;
- m_lastname = m_controllingClient.LastName;
- m_name = String.Format("{0} {1}", m_firstname, m_lastname);
- m_scene = world;
- m_uuid = client.AgentId;
- m_regionInfo = reginfo;
- m_localId = m_scene.AllocateLocalId();
-
- UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
-
- if (account != null)
- m_userLevel = account.UserLevel;
-
- IGroupsModule gm = m_scene.RequestModuleInterface();
- if (gm != null)
- m_grouptitle = gm.GetGroupTitle(m_uuid);
-
- m_scriptEngines = m_scene.RequestModuleInterfaces();
-
- AbsolutePosition = posLastSignificantMove = m_CameraCenter =
- m_lastCameraCenter = m_controllingClient.StartPos;
-
- m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
- m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
- m_reprioritization_timer.AutoReset = false;
-
- AdjustKnownSeeds();
- Animator.TrySetMovementAnimation("STAND");
- // we created a new ScenePresence (a new child agent) in a fresh region.
- // Request info about all the (root) agents in this region
- // Note: This won't send data *to* other clients in that region (children don't send)
- SendInitialFullUpdateToAllClients();
- RegisterToEvents();
- if (m_controllingClient != null)
- {
- m_controllingClient.ProcessPendingPackets();
- }
- SetDirectionVectors();
- }
-
- public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
- AvatarWearable[] wearables)
- : this(client, world, reginfo)
- {
- m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
- }
-
- public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
- : this(client, world, reginfo)
- {
- m_appearance = appearance;
- }
-
- private void CreateSceneViewer()
- {
- m_sceneViewer = new SceneViewer(this);
- }
-
- public void RegisterToEvents()
- {
- m_controllingClient.OnRequestWearables += SendWearables;
- m_controllingClient.OnSetAppearance += SetAppearance;
- m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
- //m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
- m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
- m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
- m_controllingClient.OnAgentSit += HandleAgentSit;
- m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
- m_controllingClient.OnStartAnim += HandleStartAnim;
- m_controllingClient.OnStopAnim += HandleStopAnim;
- m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
- m_controllingClient.OnAutoPilotGo += DoAutoPilot;
- m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
-
- // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
- // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
- }
-
- private void SetDirectionVectors()
- {
- Dir_Vectors[0] = Vector3.UnitX; //FORWARD
- Dir_Vectors[1] = -Vector3.UnitX; //BACK
- Dir_Vectors[2] = Vector3.UnitY; //LEFT
- Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
- Dir_Vectors[4] = Vector3.UnitZ; //UP
- Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
- Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
- Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
- Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
- Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
- Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
- }
-
- private Vector3[] GetWalkDirectionVectors()
- {
- Vector3[] vector = new Vector3[11];
- vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
- vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
- vector[2] = Vector3.UnitY; //LEFT
- vector[3] = -Vector3.UnitY; //RIGHT
- vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
- vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
- vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
- vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
- vector[8] = Vector3.UnitY; //LEFT_NUDGE
- vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
- vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
- return vector;
- }
-
- private bool[] GetDirectionIsNudge()
- {
- bool[] isNudge = new bool[11];
- isNudge[0] = false; //FORWARD
- isNudge[1] = false; //BACK
- isNudge[2] = false; //LEFT
- isNudge[3] = false; //RIGHT
- isNudge[4] = false; //UP
- isNudge[5] = false; //DOWN
- isNudge[6] = true; //FORWARD_NUDGE
- isNudge[7] = true; //BACK_NUDGE
- isNudge[8] = true; //LEFT_NUDGE
- isNudge[9] = true; //RIGHT_NUDGE
- isNudge[10] = true; //DOWN_Nudge
- return isNudge;
- }
-
-
- #endregion
-
- public uint GenerateClientFlags(UUID ObjectID)
- {
- return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
- }
-
- ///
- /// Send updates to the client about prims which have been placed on the update queue. We don't
- /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
- /// timestamp has already been sent.
- ///
- public void SendPrimUpdates()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- m_sceneViewer.SendPrimUpdates();
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- #region Status Methods
-
- ///
- /// This turns a child agent, into a root agent
- /// This is called when an agent teleports into a region, or if an
- /// agent crosses into this region from a neighbor over the border
- ///
- public void MakeRootAgent(Vector3 pos, bool isFlying)
- {
- m_log.DebugFormat(
- "[SCENE]: Upgrading child to root agent for {0} in {1}",
- Name, m_scene.RegionInfo.RegionName);
-
- //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
-
- IGroupsModule gm = m_scene.RequestModuleInterface();
- if (gm != null)
- m_grouptitle = gm.GetGroupTitle(m_uuid);
-
- m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
- m_scene.SetRootAgentScene(m_uuid);
-
- // Moved this from SendInitialData to ensure that m_appearance is initialized
- // before the inventory is processed in MakeRootAgent. This fixes a race condition
- // related to the handling of attachments
- //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
- if (m_scene.TestBorderCross(pos, Cardinals.E))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
- pos.X = crossedBorder.BorderLine.Z - 1;
- }
-
- if (m_scene.TestBorderCross(pos, Cardinals.N))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
- pos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
- //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
- //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
- //they'll bypass the landing point. But I can't think of any decent way of fixing this.
- if (KnownChildRegionHandles.Count == 0)
- {
- ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
- if (land != null)
- {
- //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
- if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
- {
- pos = land.LandData.UserLocation;
- }
- }
- }
-
- if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
- {
- Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
-
- if (pos.X < 0)
- {
- emergencyPos.X = (int)Constants.RegionSize + pos.X;
- if (!(pos.Y < 0))
- emergencyPos.Y = pos.Y;
- if (!(pos.Z < 0))
- emergencyPos.Z = pos.Z;
- }
- if (pos.Y < 0)
- {
- emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
- if (!(pos.X < 0))
- emergencyPos.X = pos.X;
- if (!(pos.Z < 0))
- emergencyPos.Z = pos.Z;
- }
- if (pos.Z < 0)
- {
- emergencyPos.Z = 128;
- if (!(pos.Y < 0))
- emergencyPos.Y = pos.Y;
- if (!(pos.X < 0))
- emergencyPos.X = pos.X;
- }
- }
-
- if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
- {
- m_log.WarnFormat(
- "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
- pos, Name, UUID);
-
- if (pos.X < 0f) pos.X = 0f;
- if (pos.Y < 0f) pos.Y = 0f;
- if (pos.Z < 0f) pos.Z = 0f;
- }
-
- float localAVHeight = 1.56f;
- if (m_avHeight != 127.0f)
- {
- localAVHeight = m_avHeight;
- }
-
- float posZLimit = 0;
-
- if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
- posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
-
- float newPosZ = posZLimit + localAVHeight / 2;
- if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
- {
- pos.Z = newPosZ;
- }
- AbsolutePosition = pos;
-
- AddToPhysicalScene(isFlying);
-
- if (m_forceFly)
- {
- m_physicsActor.Flying = true;
- }
- else if (m_flyDisabled)
- {
- m_physicsActor.Flying = false;
- }
-
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
- else
- {
- m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName);
- // emergency; this really shouldn't happen
- m_appearance = new AvatarAppearance(UUID);
- }
-
- // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
- // avatar to return to the standing position in mid-air. On login it looks like this is being sent
- // elsewhere anyway
- // Animator.SendAnimPack();
-
- m_scene.SwapRootAgentCount(false);
-
- //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
- //if (userInfo != null)
- // userInfo.FetchInventory();
- //else
- // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid);
-
- // On the next prim update, all objects will be sent
- //
- m_sceneViewer.Reset();
-
- m_isChildAgent = false;
-
- // send the animations of the other presences to me
- m_scene.ForEachScenePresence(delegate(ScenePresence presence)
- {
- if (presence != this)
- presence.Animator.SendAnimPackToClient(ControllingClient);
- });
-
- m_scene.EventManager.TriggerOnMakeRootAgent(this);
- }
-
- ///
- /// This turns a root agent into a child agent
- /// when an agent departs this region for a neighbor, this gets called.
- ///
- /// It doesn't get called for a teleport. Reason being, an agent that
- /// teleports out may not end up anywhere near this region
- ///
- public void MakeChildAgent()
- {
- // It looks like m_animator is set to null somewhere, and MakeChild
- // is called after that. Probably in aborted teleports.
- if (m_animator == null)
- m_animator = new ScenePresenceAnimator(this);
- else
- Animator.ResetAnimations();
-
-// m_log.DebugFormat(
-// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
-// Name, UUID, m_scene.RegionInfo.RegionName);
-
- // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
- // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
- //Velocity = new Vector3(0, 0, 0);
-
- m_isChildAgent = true;
- m_scene.SwapRootAgentCount(true);
- RemoveFromPhysicalScene();
-
- // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into
-
- m_scene.EventManager.TriggerOnMakeChildAgent(this);
- }
-
- ///
- /// Removes physics plugin scene representation of this agent if it exists.
- ///
- private void RemoveFromPhysicalScene()
- {
- if (PhysicsActor != null)
- {
- m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
- m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
- m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
- m_physicsActor.UnSubscribeEvents();
- m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
- PhysicsActor = null;
- }
- }
-
- ///
- ///
- ///
- ///
- public void Teleport(Vector3 pos)
- {
- bool isFlying = false;
-
- if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
- RemoveFromPhysicalScene();
- Velocity = Vector3.Zero;
- AbsolutePosition = pos;
- AddToPhysicalScene(isFlying);
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
-
- SendTerseUpdateToAllClients();
-
- }
-
- public void TeleportWithMomentum(Vector3 pos)
- {
- bool isFlying = false;
- if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
- RemoveFromPhysicalScene();
- AbsolutePosition = pos;
- AddToPhysicalScene(isFlying);
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
-
- SendTerseUpdateToAllClients();
- }
-
- ///
- ///
- ///
- public void StopMovement()
- {
- }
-
- public void StopFlying()
- {
- ControllingClient.StopFlying(this);
- }
-
- public void AddNeighbourRegion(ulong regionHandle, string cap)
- {
- lock (m_knownChildRegions)
- {
- if (!m_knownChildRegions.ContainsKey(regionHandle))
- {
- uint x, y;
- Utils.LongToUInts(regionHandle, out x, out y);
- m_knownChildRegions.Add(regionHandle, cap);
- }
- }
- }
-
- public void RemoveNeighbourRegion(ulong regionHandle)
- {
- lock (m_knownChildRegions)
- {
- if (m_knownChildRegions.ContainsKey(regionHandle))
- {
- m_knownChildRegions.Remove(regionHandle);
- //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
- }
- }
- }
-
- public void DropOldNeighbours(List oldRegions)
- {
- foreach (ulong handle in oldRegions)
- {
- RemoveNeighbourRegion(handle);
- Scene.CapsModule.DropChildSeed(UUID, handle);
- }
- }
-
- public List GetKnownRegionList()
- {
- return new List(m_knownChildRegions.Keys);
- }
-
- #endregion
-
- #region Event Handlers
-
- ///
- /// Sets avatar height in the phyiscs plugin
- ///
- internal void SetHeight(float height)
- {
- m_avHeight = height;
- if (PhysicsActor != null && !IsChildAgent)
- {
- Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight);
- PhysicsActor.Size = SetSize;
- }
- }
-
- ///
- /// Complete Avatar's movement into the region.
- /// This is called upon a very important packet sent from the client,
- /// so it's client-controlled. Never call this method directly.
- ///
- public void CompleteMovement(IClientAPI client)
- {
- //m_log.Debug("[SCENE PRESENCE]: CompleteMovement");
-
- Vector3 look = Velocity;
- if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
- {
- look = new Vector3(0.99f, 0.042f, 0);
- }
-
- // Prevent teleporting to an underground location
- // (may crash client otherwise)
- //
- Vector3 pos = AbsolutePosition;
- float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
- if (pos.Z < ground + 1.5f)
- {
- pos.Z = ground + 1.5f;
- AbsolutePosition = pos;
- }
- m_isChildAgent = false;
- bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
- MakeRootAgent(AbsolutePosition, m_flying);
-
- if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
- {
- m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI);
- Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
- m_callbackURI = null;
- }
-
- //m_log.DebugFormat("Completed movement");
-
- m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
- SendInitialData();
-
- // Create child agents in neighbouring regions
- if (!m_isChildAgent)
- {
- IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
- if (m_agentTransfer != null)
- m_agentTransfer.EnableChildAgents(this);
- else
- m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active");
-
- IFriendsModule friendsModule = m_scene.RequestModuleInterface();
- if (friendsModule != null)
- friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
- }
-
- }
-
- ///
- /// Callback for the Camera view block check. Gets called with the results of the camera view block test
- /// hitYN is true when there's something in the way.
- ///
- ///
- ///
- ///
- ///
- public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
- {
- const float POSITION_TOLERANCE = 0.02f;
- const float VELOCITY_TOLERANCE = 0.02f;
- const float ROTATION_TOLERANCE = 0.02f;
-
- if (m_followCamAuto)
- {
- if (hitYN)
- {
- CameraConstraintActive = true;
- //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance);
-
- Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint);
- ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint)));
- }
- else
- {
- if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
- !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
- !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
- {
- if (CameraConstraintActive)
- {
- ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f));
- CameraConstraintActive = false;
- }
- }
- }
- }
- }
-
- ///
- /// This is the event handler for client movement. If a client is moving, this event is triggering.
- ///
- public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
- {
- //if (m_isChildAgent)
- //{
- // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
- // return;
- //}
-
- m_perfMonMS = Util.EnvironmentTickCount();
-
- ++m_movementUpdateCount;
- if (m_movementUpdateCount < 1)
- m_movementUpdateCount = 1;
-
- #region Sanity Checking
-
- // This is irritating. Really.
- if (!AbsolutePosition.IsFinite())
- {
- RemoveFromPhysicalScene();
- m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
-
- m_pos = m_LastFinitePos;
-
- if (!m_pos.IsFinite())
- {
- m_pos.X = 127f;
- m_pos.Y = 127f;
- m_pos.Z = 127f;
- m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
- }
-
- AddToPhysicalScene(false);
- }
- else
- {
- m_LastFinitePos = m_pos;
- }
-
- #endregion Sanity Checking
-
- #region Inputs
-
- AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
- Quaternion bodyRotation = agentData.BodyRotation;
-
- // Camera location in world. We'll need to raytrace
- // from this location from time to time.
- m_CameraCenter = agentData.CameraCenter;
- if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance)
- {
- ReprioritizeUpdates();
- m_lastCameraCenter = m_CameraCenter;
- }
-
- // Use these three vectors to figure out what the agent is looking at
- // Convert it to a Matrix and/or Quaternion
- m_CameraAtAxis = agentData.CameraAtAxis;
- m_CameraLeftAxis = agentData.CameraLeftAxis;
- m_CameraUpAxis = agentData.CameraUpAxis;
-
- // The Agent's Draw distance setting
- m_DrawDistance = agentData.Far;
-
- // Check if Client has camera in 'follow cam' or 'build' mode.
- Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation);
-
- m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f)
- && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
-
- m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
- m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
-
- #endregion Inputs
-
- if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
- {
- StandUp();
- }
-
- //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
- // Raycast from the avatar's head to the camera to see if there's anything blocking the view
- if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
- {
- if (m_followCamAuto)
- {
- Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
- m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
- }
- }
- lock (scriptedcontrols)
- {
- if (scriptedcontrols.Count > 0)
- {
- SendControlToScripts((uint)flags);
- flags = RemoveIgnoredControls(flags, IgnoredControls);
- }
- }
-
- if (m_autopilotMoving)
- CheckAtSitTarget();
-
- if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
- {
- m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
- Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
-
- // TODO: This doesn't prevent the user from walking yet.
- // Setting parent ID would fix this, if we knew what value
- // to use. Or we could add a m_isSitting variable.
- //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
- SitGround = true;
- }
-
- // In the future, these values might need to go global.
- // Here's where you get them.
- m_AgentControlFlags = flags;
- m_headrotation = agentData.HeadRotation;
- m_state = agentData.State;
-
- PhysicsActor actor = PhysicsActor;
- if (actor == null)
- {
- return;
- }
-
- bool update_movementflag = false;
-
- if (m_allowMovement && !SitGround)
- {
- if (agentData.UseClientAgentPosition)
- {
- m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
- m_moveToPositionTarget = agentData.ClientAgentPosition;
- }
-
- int i = 0;
-
- bool update_rotation = false;
- bool DCFlagKeyPressed = false;
- Vector3 agent_control_v3 = Vector3.Zero;
- Quaternion q = bodyRotation;
-
- bool oldflying = PhysicsActor.Flying;
-
- if (m_forceFly)
- actor.Flying = true;
- else if (m_flyDisabled)
- actor.Flying = false;
- else
- actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
-
- if (actor.Flying != oldflying)
- update_movementflag = true;
-
- if (q != m_bodyRot)
- {
- m_bodyRot = q;
- update_rotation = true;
- }
-
- //guilty until proven innocent..
- bool Nudging = true;
- //Basically, if there is at least one non-nudge control then we don't need
- //to worry about stopping the avatar
-
- if (m_parentID == 0)
- {
- bool bAllowUpdateMoveToPosition = false;
- bool bResetMoveToPosition = false;
-
- Vector3[] dirVectors;
-
- // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
- // this prevents 'jumping' in inappropriate situations.
- if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying))
- dirVectors = GetWalkDirectionVectors();
- else
- dirVectors = Dir_Vectors;
-
- bool[] isNudge = GetDirectionIsNudge();
-
-
-
-
-
- foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
- {
- if (((uint)flags & (uint)DCF) != 0)
- {
- bResetMoveToPosition = true;
- DCFlagKeyPressed = true;
- try
- {
- agent_control_v3 += dirVectors[i];
- if (isNudge[i] == false)
- {
- Nudging = false;
- }
- }
- catch (IndexOutOfRangeException)
- {
- // Why did I get this?
- }
-
- if ((m_movementflag & (uint)DCF) == 0)
- {
- m_movementflag += (byte)(uint)DCF;
- update_movementflag = true;
- }
- }
- else
- {
- if ((m_movementflag & (uint)DCF) != 0)
- {
- m_movementflag -= (byte)(uint)DCF;
- update_movementflag = true;
- }
- else
- {
- bAllowUpdateMoveToPosition = true;
- }
- }
- i++;
- }
- //Paupaw:Do Proper PID for Autopilot here
- if (bResetMoveToPosition)
- {
- m_moveToPositionTarget = Vector3.Zero;
- m_moveToPositionInProgress = false;
- update_movementflag = true;
- bAllowUpdateMoveToPosition = false;
- }
-
- if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
- {
- //Check the error term of the current position in relation to the target position
- if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
- {
- // we are close enough to the target
- m_moveToPositionTarget = Vector3.Zero;
- m_moveToPositionInProgress = false;
- update_movementflag = true;
- }
- else
- {
- try
- {
- // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
- // This movement vector gets added to the velocity through AddNewMovement().
- // Theoretically we might need a more complex PID approach here if other
- // unknown forces are acting on the avatar and we need to adaptively respond
- // to such forces, but the following simple approach seems to works fine.
- Vector3 LocalVectorToTarget3D =
- (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
- * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
- // Ignore z component of vector
- Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
- LocalVectorToTarget2D.Normalize();
-
- //We're not nudging
- Nudging = false;
- agent_control_v3 += LocalVectorToTarget2D;
-
- // update avatar movement flags. the avatar coordinate system is as follows:
- //
- // +X (forward)
- //
- // ^
- // |
- // |
- // |
- // |
- // (left) +Y <--------o--------> -Y
- // avatar
- // |
- // |
- // |
- // |
- // v
- // -X
- //
-
- // based on the above avatar coordinate system, classify the movement into
- // one of left/right/back/forward.
- if (LocalVectorToTarget2D.Y > 0)//MoveLeft
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
- //AgentControlFlags
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
- update_movementflag = true;
- }
- else if (LocalVectorToTarget2D.Y < 0) //MoveRight
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
- update_movementflag = true;
- }
- if (LocalVectorToTarget2D.X < 0) //MoveBack
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
- update_movementflag = true;
- }
- else if (LocalVectorToTarget2D.X > 0) //Move Forward
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
- update_movementflag = true;
- }
- }
- catch (Exception e)
- {
- //Avoid system crash, can be slower but...
- m_log.DebugFormat("Crash! {0}", e.ToString());
- }
- }
- }
- }
-
- // Cause the avatar to stop flying if it's colliding
- // with something with the down arrow pressed.
-
- // Only do this if we're flying
- if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
- {
- // Landing detection code
-
- // Are the landing controls requirements filled?
- bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
- ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
-
- // Are the collision requirements fulfilled?
- bool colliding = (m_physicsActor.IsColliding == true);
-
- if (m_physicsActor.Flying && colliding && controlland)
- {
- // nesting this check because LengthSquared() is expensive and we don't
- // want to do it every step when flying.
- if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
- StopFlying();
- }
- }
-
- if (update_movementflag || (update_rotation && DCFlagKeyPressed))
- {
- // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
- // m_log.DebugFormat(
- // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
-
- AddNewMovement(agent_control_v3, q, Nudging);
-
-
- }
- }
-
- if (update_movementflag && !SitGround)
- Animator.UpdateMovementAnimations();
-
- m_scene.EventManager.TriggerOnClientMovement(this);
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client)
- {
- m_autopilotMoving = true;
- m_autoPilotTarget = Pos;
- m_sitAtAutoTarget = false;
- PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
- //proxy.PCode = (byte)PCode.ParticleSystem;
- proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
- proxyObjectGroup.AttachToScene(m_scene);
-
- // Commented out this code since it could never have executed, but might still be informative.
-// if (proxyObjectGroup != null)
-// {
- proxyObjectGroup.SendGroupFullUpdate();
- remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
- m_scene.DeleteSceneObject(proxyObjectGroup, false);
-// }
-// else
-// {
-// m_autopilotMoving = false;
-// m_autoPilotTarget = Vector3.Zero;
-// ControllingClient.SendAlertMessage("Autopilot cancelled");
-// }
- }
-
- public void DoMoveToPosition(Object sender, string method, List args)
- {
- try
- {
- float locx = 0f;
- float locy = 0f;
- float locz = 0f;
- uint regionX = 0;
- uint regionY = 0;
- try
- {
- Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
- locx = Convert.ToSingle(args[0]) - (float)regionX;
- locy = Convert.ToSingle(args[1]) - (float)regionY;
- locz = Convert.ToSingle(args[2]);
- }
- catch (InvalidCastException)
- {
- m_log.Error("[CLIENT]: Invalid autopilot request");
- return;
- }
- m_moveToPositionInProgress = true;
- m_moveToPositionTarget = new Vector3(locx, locy, locz);
- }
- catch (Exception ex)
- {
- //Why did I get this error?
- m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex);
- }
- }
-
- private void CheckAtSitTarget()
- {
- //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString());
- if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5)
- {
- if (m_sitAtAutoTarget)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID);
- if (part != null)
- {
- AbsolutePosition = part.AbsolutePosition;
- Velocity = Vector3.Zero;
- SendFullUpdateToAllClients();
-
- HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
- }
- //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
- m_requestedSitTargetUUID = UUID.Zero;
- }
- /*
- else
- {
- //ControllingClient.SendAlertMessage("Autopilot cancelled");
- //SendTerseUpdateToAllClients();
- //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
- //proxy.PCode = (byte)PCode.ParticleSystem;
- ////uint nextUUID = m_scene.NextLocalId;
-
- //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy);
- //if (proxyObjectGroup != null)
- //{
- //proxyObjectGroup.SendGroupFullUpdate();
- //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
- //m_scene.DeleteSceneObject(proxyObjectGroup);
- //}
- }
- */
- m_autoPilotTarget = Vector3.Zero;
- m_autopilotMoving = false;
- }
- }
- ///
- /// Perform the logic necessary to stand the avatar up. This method also executes
- /// the stand animation.
- ///
- public void StandUp()
- {
- SitGround = false;
-
- if (m_parentID != 0)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
- if (part != null)
- {
- part.TaskInventory.LockItemsForRead(true);
- TaskInventoryDictionary taskIDict = part.TaskInventory;
- if (taskIDict != null)
- {
- foreach (UUID taskID in taskIDict.Keys)
- {
- UnRegisterControlEventsToScript(LocalId, taskID);
- taskIDict[taskID].PermsMask &= ~(
- 2048 | //PERMISSION_CONTROL_CAMERA
- 4); // PERMISSION_TAKE_CONTROLS
- }
- }
- part.TaskInventory.LockItemsForRead(false);
- // Reset sit target.
- if (part.GetAvatarOnSitTarget() == UUID)
- part.SetAvatarOnSitTarget(UUID.Zero);
- m_parentPosition = part.GetWorldPosition();
- ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
- }
- // part.GetWorldRotation() is the rotation of the object being sat on
- // Rotation is the sittiing Av's rotation
-
- Quaternion partRot;
-// if (part.LinkNum == 1)
-// { // Root prim of linkset
-// partRot = part.ParentGroup.RootPart.RotationOffset;
-// }
-// else
-// { // single or child prim
-
-// }
- if (part == null) //CW: Part may be gone. llDie() for example.
- {
- partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- partRot = part.GetWorldRotation();
- }
-
- Quaternion partIRot = Quaternion.Inverse(partRot);
-
- Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
- Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
-
-
- if (m_physicsActor == null)
- {
- AddToPhysicalScene(false);
- }
- //CW: If the part isn't null then we can set the current position
- if (part != null)
- {
- Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
- AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
- part.IsOccupied = false;
- part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
- }
- else
- {
- //CW: Since the part doesn't exist, a coarse standup position isn't an issue
- AbsolutePosition = m_lastWorldPosition;
- }
-
- m_parentPosition = Vector3.Zero;
- m_parentID = 0;
- m_linkedPrim = UUID.Zero;
- m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- SendFullUpdateToAllClients();
- m_requestedSitTargetID = 0;
-
- if ((m_physicsActor != null) && (m_avHeight > 0))
- {
- SetHeight(m_avHeight);
- }
- }
- Animator.TrySetMovementAnimation("STAND");
- }
-
- private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
- {
- SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID);
- if (targetPart == null)
- return null;
-
- // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used.
- // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
-
- // Get our own copy of the part array, and sort into the order we want to test
- SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts();
- Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
- {
- // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
- int linkNum1 = p1==targetPart ? -1 : p1.LinkNum;
- int linkNum2 = p2==targetPart ? -1 : p2.LinkNum;
- return linkNum1 - linkNum2;
- }
- );
-
- //look for prims with explicit sit targets that are available
- foreach (SceneObjectPart part in partArray)
- {
- // Is a sit target available?
- Vector3 avSitOffSet = part.SitTargetPosition;
- Quaternion avSitOrientation = part.SitTargetOrientation;
- UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
- bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
- bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
- if (SitTargetisSet && !SitTargetOccupied)
- {
- //switch the target to this prim
- return part;
- }
- }
-
- // no explicit sit target found - use original target
- return targetPart;
- }
-
- private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
- {
- bool autopilot = true;
- Vector3 autopilotTarget = new Vector3();
- Quaternion sitOrientation = Quaternion.Identity;
- Vector3 pos = new Vector3();
- Vector3 cameraEyeOffset = Vector3.Zero;
- Vector3 cameraAtOffset = Vector3.Zero;
- bool forceMouselook = false;
-
- //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
- SceneObjectPart part = FindNextAvailableSitTarget(targetID);
- if (part == null) return;
-
- // TODO: determine position to sit at based on scene geometry; don't trust offset from client
- // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
-
- // part is the prim to sit on
- // offset is the world-ref vector distance from that prim center to the click-spot
- // UUID is the UUID of the Avatar doing the clicking
-
- m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
-
- // Is a sit target available?
- Vector3 avSitOffSet = part.SitTargetPosition;
- Quaternion avSitOrientation = part.SitTargetOrientation;
-
- bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
- // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
- Quaternion partRot;
-// if (part.LinkNum == 1)
-// { // Root prim of linkset
-// partRot = part.ParentGroup.RootPart.RotationOffset;
-// }
-// else
-// { // single or child prim
- partRot = part.GetWorldRotation();
-// }
- Quaternion partIRot = Quaternion.Inverse(partRot);
-//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
- // Sit analysis rewritten by KF 091125
- if (SitTargetisSet) // scipted sit
- {
- if (!part.IsOccupied)
- {
-//Console.WriteLine("Scripted, unoccupied");
- part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
- offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
-
- Quaternion nrot = avSitOrientation;
- if (!part.IsRoot)
- {
- nrot = part.RotationOffset * avSitOrientation;
- }
- sitOrientation = nrot; // Change rotatione to the scripted one
- OffsetRotation = nrot;
- autopilot = false; // Jump direct to scripted llSitPos()
- }
- else
- {
-//Console.WriteLine("Scripted, occupied");
- return;
- }
- }
- else // Not Scripted
- {
- if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
- {
- // large prim & offset, ignore if other Avs sitting
-// offset.Z -= 0.05f;
- m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
- autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
-
-//Console.WriteLine(" offset ={0}", offset);
-//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
-//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
-
- }
- else // small offset
- {
-//Console.WriteLine("Small offset");
- if (!part.IsOccupied)
- {
- m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
- autopilotTarget = part.AbsolutePosition;
-//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
- }
- else return; // occupied small
- } // end large/small
- } // end Scripted/not
- cameraAtOffset = part.GetCameraAtOffset();
- cameraEyeOffset = part.GetCameraEyeOffset();
- forceMouselook = part.GetForceMouselook();
- if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
- if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
-
- if (m_physicsActor != null)
- {
- // If we're not using the client autopilot, we're immediately warping the avatar to the location
- // We can remove the physicsActor until they stand up.
- m_sitAvatarHeight = m_physicsActor.Size.Z;
- if (autopilot)
- { // its not a scripted sit
-// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
- if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
- {
- autopilot = false; // close enough
- m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
- Not using the part's position because returning the AV to the last known standing
- position is likely to be more friendly, isn't it? */
- RemoveFromPhysicalScene();
- AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
- } // else the autopilot will get us close
- }
- else
- { // its a scripted sit
- m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
- I *am* using the part's position this time because we have no real idea how far away
- the avatar is from the sit target. */
- RemoveFromPhysicalScene();
- }
- }
- else return; // physactor is null!
-
- Vector3 offsetr; // = offset * partIRot;
- // KF: In a linkset, offsetr needs to be relative to the group root! 091208
- // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
- // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
- // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
- //offsetr = offset * partIRot;
-//
- // else
- // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
- // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
- // (offset * partRot);
- // }
-
-//Console.WriteLine(" ");
-//Console.WriteLine("link number ={0}", part.LinkNum);
-//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
-//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
-//Console.WriteLine("Click offst ={0}", offset);
-//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
-//Console.WriteLine("offsetr ={0}", offsetr);
-//Console.WriteLine("Camera At ={0}", cameraAtOffset);
-//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
-
- //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
- ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
-
- m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
- // This calls HandleAgentSit twice, once from here, and the client calls
- // HandleAgentSit itself after it gets to the location
- // It doesn't get to the location until we've moved them there though
- // which happens in HandleAgentSit :P
- m_autopilotMoving = autopilot;
- m_autoPilotTarget = autopilotTarget;
- m_sitAtAutoTarget = autopilot;
- m_initialSitTarget = autopilotTarget;
- if (!autopilot)
- HandleAgentSit(remoteClient, UUID);
- }
-
- public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
- {
- if (m_parentID != 0)
- {
- StandUp();
- }
- m_nextSitAnimation = "SIT";
-
- //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
- SceneObjectPart part = FindNextAvailableSitTarget(targetID);
-
- if (part != null)
- {
- if (!String.IsNullOrEmpty(part.SitAnimation))
- {
- m_nextSitAnimation = part.SitAnimation;
- }
- m_requestedSitTargetID = part.LocalId;
- //m_requestedSitOffset = offset;
- m_requestedSitTargetUUID = targetID;
-
- m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
-
- if (m_scene.PhysicsScene.SupportsRayCast())
- {
- //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback());
- //SitRayCastAvatarPosition(part);
- //return;
- }
- }
- else
- {
-
- m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
- }
-
-
-
- SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
- }
- /*
- public void SitRayCastAvatarPosition(SceneObjectPart part)
- {
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = AbsolutePosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse);
- }
-
- public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- }
- else
- {
- SitRayCastAvatarPositionCameraZ(part);
- }
- }
- else
- {
- SitRayCastAvatarPositionCameraZ(part);
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part)
- {
- // Next, try to raycast from the camera Z position
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse);
- }
-
- public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- }
- else
- {
- SitRayCastCameraPosition(part);
- }
- }
- else
- {
- SitRayCastCameraPosition(part);
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- public void SitRayCastCameraPosition(SceneObjectPart part)
- {
- // Next, try to raycast from the camera position
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = CameraPosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse);
- }
-
- public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- }
- else
- {
- SitRayHorizontal(part);
- }
- }
- else
- {
- SitRayHorizontal(part);
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- public void SitRayHorizontal(SceneObjectPart part)
- {
- // Next, try to raycast from the avatar position to fwd
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = CameraPosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse);
- }
-
- public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- // Next, try to raycast from the camera position
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = CameraPosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition);
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position not accessable.");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position not accessable.");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal)
- {
- int i = 0;
- //throw new NotImplementedException();
- //m_requestedSitTargetUUID = UUID.Zero;
- //m_requestedSitTargetID = 0;
- //m_requestedSitOffset = Vector3.Zero;
-
- SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity);
- }
- */
- public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation)
- {
- if (m_parentID != 0)
- {
- StandUp();
- }
- if (!String.IsNullOrEmpty(sitAnimation))
- {
- m_nextSitAnimation = sitAnimation;
- }
- else
- {
- m_nextSitAnimation = "SIT";
- }
-
- //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
- SceneObjectPart part = FindNextAvailableSitTarget(targetID);
- if (part != null)
- {
- m_requestedSitTargetID = part.LocalId;
- //m_requestedSitOffset = offset;
- m_requestedSitTargetUUID = targetID;
-
- m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
-
- if (m_scene.PhysicsScene.SupportsRayCast())
- {
- //SitRayCastAvatarPosition(part);
- //return;
- }
- }
- else
- {
- m_log.Warn("Sit requested on unknown object: " + targetID);
- }
-
- SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
- }
-
- public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
- {
- if (!String.IsNullOrEmpty(m_nextSitAnimation))
- {
- HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
- }
- else
- {
- HandleAgentSit(remoteClient, agentID, "SIT");
- }
- }
-
- public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
-
- if (m_sitAtAutoTarget || !m_autopilotMoving)
- {
- if (part != null)
- {
-//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
- if (part.GetAvatarOnSitTarget() == UUID)
- {
-//Console.WriteLine("Scripted Sit");
- // Scripted sit
- Vector3 sitTargetPos = part.SitTargetPosition;
- Quaternion sitTargetOrient = part.SitTargetOrientation;
- m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
- m_pos += SIT_TARGET_ADJUSTMENT;
- if (!part.IsRoot)
- {
- m_pos *= part.RotationOffset;
- }
- m_bodyRot = sitTargetOrient;
- m_parentPosition = part.AbsolutePosition;
- part.IsOccupied = true;
- part.ParentGroup.AddAvatar(agentID);
-Console.WriteLine("Scripted Sit ofset {0}", m_pos);
- }
- else
- {
- // if m_avUnscriptedSitPos is zero then Av sits above center
- // Else Av sits at m_avUnscriptedSitPos
-
- // Non-scripted sit by Kitto Flora 21Nov09
- // Calculate angle of line from prim to Av
- Quaternion partIRot;
-// if (part.LinkNum == 1)
-// { // Root prim of linkset
-// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
-// }
-// else
-// { // single or child prim
- partIRot = Quaternion.Inverse(part.GetWorldRotation());
-// }
- Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
- float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
- float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
- if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
- if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
- float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
- // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
- // Av sits at world euler <0,0, z>, translated by part rotation
- m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
-
- m_parentPosition = part.AbsolutePosition;
- part.IsOccupied = true;
- part.ParentGroup.AddAvatar(agentID);
- m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
- (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
- (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
- m_avUnscriptedSitPos; // adds click offset, if any
- //Set up raytrace to find top surface of prim
- Vector3 size = part.Scale;
- float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
- Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
- Vector3 down = new Vector3(0f, 0f, -1f);
-//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
- m_scene.PhysicsScene.RaycastWorld(
- start, // Vector3 position,
- down, // Vector3 direction,
- mag, // float length,
- SitAltitudeCallback); // retMethod
- } // end scripted/not
- }
- else // no Av
- {
- return;
- }
- }
-
- //We want our offsets to reference the root prim, not the child we may have sat on
- if (!part.IsRoot)
- {
- m_parentID = part.ParentGroup.RootPart.LocalId;
- m_pos += part.OffsetPosition;
- }
- else
- {
- m_parentID = m_requestedSitTargetID;
- }
-
- m_linkedPrim = part.UUID;
-
- Velocity = Vector3.Zero;
- RemoveFromPhysicalScene();
-
- Animator.TrySetMovementAnimation(sitAnimation);
- SendFullUpdateToAllClients();
- }
-
- public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
- {
- // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
- // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
- if(hitYN)
- {
- // m_pos = Av offset from prim center to make look like on center
- // m_parentPosition = Actual center pos of prim
- // collisionPoint = spot on prim where we want to sit
- // collisionPoint.Z = global sit surface height
- SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
- Quaternion partIRot;
-// if (part.LinkNum == 1)
-/// { // Root prim of linkset
-// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
-// }
-// else
-// { // single or child prim
- partIRot = Quaternion.Inverse(part.GetWorldRotation());
-// }
- if (m_initialSitTarget != null)
- {
- float offZ = collisionPoint.Z - m_initialSitTarget.Z;
- Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
- //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
- m_pos += offset;
- // ControllingClient.SendClearFollowCamProperties(part.UUID);
- }
-
- }
- } // End SitAltitudeCallback KF.
-
- ///
- /// Event handler for the 'Always run' setting on the client
- /// Tells the physics plugin to increase speed of movement.
- ///
- public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun)
- {
- m_setAlwaysRun = pSetAlwaysRun;
- if (PhysicsActor != null)
- {
- PhysicsActor.SetAlwaysRun = pSetAlwaysRun;
- }
- }
-
- public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
- {
- Animator.AddAnimation(animID, UUID.Zero);
- }
-
- public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
- {
- Animator.RemoveAnimation(animID);
- }
-
- ///
- /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
- ///
- /// The vector in which to move. This is relative to the rotation argument
- /// The direction in which this avatar should now face.
- public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
- {
- if (m_isChildAgent)
- {
- // WHAT???
- m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!");
-
- // we have to reset the user's child agent connections.
- // Likely, here they've lost the eventqueue for other regions so border
- // crossings will fail at this point unless we reset them.
-
- List regions = new List(KnownChildRegionHandles);
- regions.Remove(m_scene.RegionInfo.RegionHandle);
-
- MakeRootAgent(new Vector3(127f, 127f, 127f), true);
-
- // Async command
- if (m_scene.SceneGridService != null)
- {
- m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions);
-
- // Give the above command some time to try and close the connections.
- // this is really an emergency.. so sleep, or we'll get all discombobulated.
- System.Threading.Thread.Sleep(500);
- }
-
- if (m_scene.SceneGridService != null)
- {
- IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
- if (m_agentTransfer != null)
- m_agentTransfer.EnableChildAgents(this);
- }
-
- return;
- }
-
- m_perfMonMS = Util.EnvironmentTickCount();
-
- Rotation = rotation;
- Vector3 direc = vec * rotation;
- direc.Normalize();
- PhysicsActor actor = m_physicsActor;
- if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
-
- direc *= 0.03f * 128f * m_speedModifier;
-
- if (actor != null)
- {
- if (actor.Flying)
- {
- direc *= 4.0f;
- //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
- //bool colliding = (m_physicsActor.IsColliding==true);
- //if (controlland)
- // m_log.Info("[AGENT]: landCommand");
- //if (colliding)
- // m_log.Info("[AGENT]: colliding");
- //if (m_physicsActor.Flying && colliding && controlland)
- //{
- // StopFlying();
- // m_log.Info("[AGENT]: Stop FLying");
- //}
- }
- else if (!actor.Flying && actor.IsColliding)
- {
- if (direc.Z > 2.0f)
- {
- if(m_animator.m_animTickJump == -1)
- {
- direc.Z *= 3.0f; // jump
- }
- else
- {
- direc.Z *= 0.1f; // prejump
- }
- /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
- Animator.TrySetMovementAnimation("PREJUMP");
- Animator.TrySetMovementAnimation("JUMP");
- */
- }
- }
- }
-
- // TODO: Add the force instead of only setting it to support multiple forces per frame?
- m_forceToApply = direc;
- m_isNudging = Nudging;
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- #endregion
-
- #region Overridden Methods
-
- public override void Update()
- {
- const float ROTATION_TOLERANCE = 0.01f;
- const float VELOCITY_TOLERANCE = 0.001f;
- const float POSITION_TOLERANCE = 0.05f;
- //const int TIME_MS_TOLERANCE = 3000;
-
-
-
- if (m_isChildAgent == false)
- {
-// PhysicsActor actor = m_physicsActor;
-
- // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
- // grab the latest PhysicsActor velocity, whereas m_velocity is often
- // storing a requested force instead of an actual traveling velocity
-
- // Throw away duplicate or insignificant updates
- if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
- !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
- !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
- //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
- {
- SendTerseUpdateToAllClients();
-
- // Update the "last" values
- m_lastPosition = m_pos;
- m_lastRotation = m_bodyRot;
- m_lastVelocity = Velocity;
- //m_lastTerseSent = Environment.TickCount;
- }
-
- // followed suggestion from mic bowman. reversed the two lines below.
- if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something
- CheckForBorderCrossing();
- CheckForSignificantMovement(); // sends update to the modules.
- }
-
- //Sending prim updates AFTER the avatar terse updates are sent
- SendPrimUpdates();
- }
-
- #endregion
-
- #region Update Client(s)
-
- ///
- /// Sends a location update to the client connected to this scenePresence
- ///
- ///
- public void SendTerseUpdateToClient(IClientAPI remoteClient)
- {
- // If the client is inactive, it's getting its updates from another
- // server.
- if (remoteClient.IsActive)
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- PhysicsActor actor = m_physicsActor;
- Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero;
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
-
- remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- m_scene.StatsReporter.AddAgentUpdates(1);
- }
- }
-
- ///
- /// Send a location/velocity/accelleration update to all agents in scene
- ///
- public void SendTerseUpdateToAllClients()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- m_scene.ForEachClient(SendTerseUpdateToClient);
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- public void SendCoarseLocations(List coarseLocations, List avatarUUIDs)
- {
- SendCourseLocationsMethod d = m_sendCourseLocationsMethod;
- if (d != null)
- {
- d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
- }
- }
-
- public void SetSendCourseLocationMethod(SendCourseLocationsMethod d)
- {
- if (d != null)
- m_sendCourseLocationsMethod = d;
- }
-
- public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs)
- {
- m_perfMonMS = Util.EnvironmentTickCount();
- m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- ///
- /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar)
- ///
- ///
- public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar)
- {
- // 2 stage check is needed.
- if (remoteAvatar == null)
- return;
- IClientAPI cl=remoteAvatar.ControllingClient;
- if (cl == null)
- return;
- if (m_appearance.Texture == null)
- return;
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
- m_scene.StatsReporter.AddAgentUpdates(1);
- }
-
- ///
- /// Tell *ALL* agents about this agent
- ///
- public void SendInitialFullUpdateToAllClients()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
- int avUpdates = 0;
- m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
- {
- ++avUpdates;
- // only send if this is the root (children are only "listening posts" in a foreign region)
- if (!IsChildAgent)
- {
- SendFullUpdateToOtherClient(avatar);
- }
-
- if (avatar.LocalId != LocalId)
- {
- if (!avatar.IsChildAgent)
- {
- avatar.SendFullUpdateToOtherClient(this);
- avatar.SendAppearanceToOtherAgent(this);
- avatar.Animator.SendAnimPackToClient(ControllingClient);
- }
- }
- });
-
- m_scene.StatsReporter.AddAgentUpdates(avUpdates);
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
-
- //Animator.SendAnimPack();
- }
-
- public void SendFullUpdateToAllClients()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- // only send update from root agents to other clients; children are only "listening posts"
- int count = 0;
- m_scene.ForEachScenePresence(delegate(ScenePresence sp)
- {
- if (sp.IsChildAgent)
- return;
- SendFullUpdateToOtherClient(sp);
- ++count;
- });
- m_scene.StatsReporter.AddAgentUpdates(count);
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
-
- Animator.SendAnimPack();
- }
-
- ///
- /// Do everything required once a client completes its movement into a region
- ///
- public void SendInitialData()
- {
- // Moved this into CompleteMovement to ensure that m_appearance is initialized before
- // the inventory arrives
- // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- m_controllingClient.SendAvatarDataImmediate(this);
-
- SendInitialFullUpdateToAllClients();
- SendAppearanceToAllOtherAgents();
- }
-
- ///
- /// Tell the client for this scene presence what items it should be wearing now
- ///
- public void SendWearables()
- {
- m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name);
-
- ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
- }
-
- ///
- ///
- ///
- public void SendAppearanceToAllOtherAgents()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
- {
- if (scenePresence.UUID != UUID)
- {
- SendAppearanceToOtherAgent(scenePresence);
- }
- });
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- ///
- /// Send appearance data to an agent that isn't this one.
- ///
- ///
- public void SendAppearanceToOtherAgent(ScenePresence avatar)
- {
- avatar.ControllingClient.SendAppearance(
- m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
- }
-
- ///
- /// Set appearance data (textureentry and slider settings) received from the client
- ///
- ///
- ///
- public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
- {
- if (m_physicsActor != null)
- {
- if (!IsChildAgent)
- {
- // This may seem like it's redundant, remove the avatar from the physics scene
- // just to add it back again, but it saves us from having to update
- // 3 variables 10 times a second.
- bool flyingTemp = m_physicsActor.Flying;
- RemoveFromPhysicalScene();
- //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
-
- //PhysicsActor = null;
-
- AddToPhysicalScene(flyingTemp);
- }
- }
-
- #region Bake Cache Check
-
- if (textureEntry != null)
- {
- for (int i = 0; i < BAKE_INDICES.Length; i++)
- {
- int j = BAKE_INDICES[i];
- Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
-
- if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
- {
- if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
- {
- m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name);
- this.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
- }
- }
- }
-
- }
-
-
- #endregion Bake Cache Check
-
- m_appearance.SetAppearance(textureEntry, visualParams);
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
-
- // This is not needed, because only the transient data changed
- //AvatarData adata = new AvatarData(m_appearance);
- //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
-
- SendAppearanceToAllOtherAgents();
- if (!m_startAnimationSet)
- {
- Animator.UpdateMovementAnimations();
- m_startAnimationSet = true;
- }
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- m_controllingClient.SendAvatarDataImmediate(this);
- }
-
- public void SetWearable(int wearableId, AvatarWearable wearable)
- {
- m_appearance.SetWearable(wearableId, wearable);
- AvatarData adata = new AvatarData(m_appearance);
- m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
- m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
- }
-
- // Because appearance setting is in a module, we actually need
- // to give it access to our appearance directly, otherwise we
- // get a synchronization issue.
- public AvatarAppearance Appearance
- {
- get { return m_appearance; }
- set { m_appearance = value; }
- }
-
- #endregion
-
- #region Significant Movement Method
-
- ///
- /// This checks for a significant movement and sends a courselocationchange update
- ///
- protected void CheckForSignificantMovement()
- {
- // Movement updates for agents in neighboring regions are sent directly to clients.
- // This value only affects how often agent positions are sent to neighbor regions
- // for things such as distance-based update prioritization
- const float SIGNIFICANT_MOVEMENT = 2.0f;
-
- if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT)
- {
- posLastSignificantMove = AbsolutePosition;
- m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient);
- }
-
- // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
- if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance ||
- Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
- {
- m_lastChildAgentUpdatePosition = AbsolutePosition;
- m_lastChildAgentUpdateCamPosition = CameraPosition;
-
- ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
- cadu.ActiveGroupID = UUID.Zero.Guid;
- cadu.AgentID = UUID.Guid;
- cadu.alwaysrun = m_setAlwaysRun;
- cadu.AVHeight = m_avHeight;
- Vector3 tempCameraCenter = m_CameraCenter;
- cadu.cameraPosition = tempCameraCenter;
- cadu.drawdistance = m_DrawDistance;
- cadu.GroupAccess = 0;
- cadu.Position = AbsolutePosition;
- cadu.regionHandle = m_rootRegionHandle;
- float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / (float)innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
- multiplier = 0.25f;
- }
-
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
- cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
- cadu.Velocity = Velocity;
-
- AgentPosition agentpos = new AgentPosition();
- agentpos.CopyFrom(cadu);
-
- m_scene.SendOutChildAgentUpdates(agentpos, this);
- }
- }
-
- #endregion
-
- #region Border Crossing Methods
-
- ///
- /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion
- ///
- protected void CheckForBorderCrossing()
- {
- if (IsChildAgent)
- return;
-
- Vector3 pos2 = AbsolutePosition;
- Vector3 vel = Velocity;
- int neighbor = 0;
- int[] fix = new int[2];
-
- float timeStep = 0.1f;
- pos2.X = pos2.X + (vel.X*timeStep);
- pos2.Y = pos2.Y + (vel.Y*timeStep);
- pos2.Z = pos2.Z + (vel.Z*timeStep);
-
- if (!IsInTransit)
- {
- // Checks if where it's headed exists a region
-
- bool needsTransit = false;
- if (m_scene.TestBorderCross(pos2, Cardinals.W))
- {
- if (m_scene.TestBorderCross(pos2, Cardinals.S))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.SW, ref fix);
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.N))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.NW, ref fix);
- }
- else
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.W, ref fix);
- }
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.E))
- {
- if (m_scene.TestBorderCross(pos2, Cardinals.S))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.SE, ref fix);
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.N))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.NE, ref fix);
- }
- else
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.E, ref fix);
- }
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.S))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.S, ref fix);
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.N))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.N, ref fix);
- }
-
-
- // Makes sure avatar does not end up outside region
- if (neighbor <= 0)
- {
- if (!needsTransit)
- {
- if (m_requestedSitTargetUUID == UUID.Zero)
- {
- Vector3 pos = AbsolutePosition;
- if (AbsolutePosition.X < 0)
- pos.X += Velocity.X;
- else if (AbsolutePosition.X > Constants.RegionSize)
- pos.X -= Velocity.X;
- if (AbsolutePosition.Y < 0)
- pos.Y += Velocity.Y;
- else if (AbsolutePosition.Y > Constants.RegionSize)
- pos.Y -= Velocity.Y;
- AbsolutePosition = pos;
- }
- }
- }
- else if (neighbor > 0)
- CrossToNewRegion();
- }
- else
- {
- RemoveFromPhysicalScene();
- // This constant has been inferred from experimentation
- // I'm not sure what this value should be, so I tried a few values.
- timeStep = 0.04f;
- pos2 = AbsolutePosition;
- pos2.X = pos2.X + (vel.X * timeStep);
- pos2.Y = pos2.Y + (vel.Y * timeStep);
- pos2.Z = pos2.Z + (vel.Z * timeStep);
- m_pos = pos2;
- }
- }
-
- protected int HaveNeighbor(Cardinals car, ref int[] fix)
- {
- uint neighbourx = m_regionInfo.RegionLocX;
- uint neighboury = m_regionInfo.RegionLocY;
-
- int dir = (int)car;
-
- if (dir > 1 && dir < 5) //Heading East
- neighbourx++;
- else if (dir > 5) // Heading West
- neighbourx--;
-
- if (dir < 3 || dir == 8) // Heading North
- neighboury++;
- else if (dir > 3 && dir < 7) // Heading Sout
- neighboury--;
-
- int x = (int)(neighbourx * Constants.RegionSize);
- int y = (int)(neighboury * Constants.RegionSize);
- GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y);
-
- if (neighbourRegion == null)
- {
- fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx);
- fix[1] = (int)(m_regionInfo.RegionLocY - neighboury);
- return dir * (-1);
- }
- else
- return dir;
- }
-
- ///
- /// Moves the agent outside the region bounds
- /// Tells neighbor region that we're crossing to it
- /// If the neighbor accepts, remove the agent's viewable avatar from this scene
- /// set them to a child agent.
- ///
- protected void CrossToNewRegion()
- {
- InTransit();
- try
- {
- m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying);
- }
- catch
- {
- m_scene.CrossAgentToNewRegion(this, false);
- }
- }
-
- public void InTransit()
- {
- m_inTransit = true;
-
- if ((m_physicsActor != null) && m_physicsActor.Flying)
- m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY;
- else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
- m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY;
- }
-
- public void NotInTransit()
- {
- m_inTransit = false;
- }
-
- public void RestoreInCurrentScene()
- {
- AddToPhysicalScene(false); // not exactly false
- }
-
- public void Reset()
- {
- // Put the child agent back at the center
- AbsolutePosition
- = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
- Animator.ResetAnimations();
- }
-
- ///
- /// Computes which child agents to close when the scene presence moves to another region.
- /// Removes those regions from m_knownRegions.
- ///
- /// The new region's x on the map
- /// The new region's y on the map
- ///
- public void CloseChildAgents(uint newRegionX, uint newRegionY)
- {
- List byebyeRegions = new List();
- m_log.DebugFormat(
- "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
- m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName);
- //DumpKnownRegions();
-
- lock (m_knownChildRegions)
- {
- foreach (ulong handle in m_knownChildRegions.Keys)
- {
- // Don't close the agent on this region yet
- if (handle != Scene.RegionInfo.RegionHandle)
- {
- uint x, y;
- Utils.LongToUInts(handle, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
-
- //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
- //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
- if (Util.IsOutsideView(x, newRegionX, y, newRegionY))
- {
- byebyeRegions.Add(handle);
- }
- }
- }
- }
-
- if (byebyeRegions.Count > 0)
- {
- m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
- m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions);
- }
-
- foreach (ulong handle in byebyeRegions)
- {
- RemoveNeighbourRegion(handle);
- }
- }
-
- #endregion
-
- ///
- /// This allows the Sim owner the abiility to kick users from their sim currently.
- /// It tells the client that the agent has permission to do so.
- ///
- public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
- {
- if (godStatus)
- {
- // For now, assign god level 200 to anyone
- // who is granted god powers, but has no god level set.
- //
- UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
- if (account != null)
- {
- if (account.UserLevel > 0)
- m_godLevel = account.UserLevel;
- else
- m_godLevel = 200;
- }
- }
- else
- {
- m_godLevel = 0;
- }
-
- ControllingClient.SendAdminResponse(token, (uint)m_godLevel);
- }
-
- #region Child Agent Updates
-
- public void ChildAgentDataUpdate(AgentData cAgentData)
- {
- //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
- if (!IsChildAgent)
- return;
-
- CopyFrom(cAgentData);
- }
-
- ///
- /// This updates important decision making data about a child agent
- /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
- ///
- public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
- {
- if (!IsChildAgent)
- return;
-
- //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
- int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
- int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
-
- Vector3 offset = new Vector3(shiftx, shifty, 0f);
-
- m_DrawDistance = cAgentData.Far;
- if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!!
- m_pos = cAgentData.Position + offset;
-
- if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance)
- {
- posLastSignificantMove = AbsolutePosition;
- ReprioritizeUpdates();
- }
-
- m_CameraCenter = cAgentData.Center + offset;
-
- m_avHeight = cAgentData.Size.Z;
- //SetHeight(cAgentData.AVHeight);
-
- if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
- ControllingClient.SetChildAgentThrottle(cAgentData.Throttles);
-
- // Sends out the objects in the user's draw distance if m_sendTasksToChild is true.
- if (m_scene.m_seeIntoRegionFromNeighbor)
- m_sceneViewer.Reset();
-
- //cAgentData.AVHeight;
- m_rootRegionHandle = cAgentData.RegionHandle;
- //m_velocity = cAgentData.Velocity;
- }
-
- public void CopyTo(AgentData cAgent)
- {
- cAgent.AgentID = UUID;
- cAgent.RegionID = Scene.RegionInfo.RegionID;
-
- cAgent.Position = AbsolutePosition;
- cAgent.Velocity = m_velocity;
- cAgent.Center = m_CameraCenter;
- // Don't copy the size; it is inferred from apearance parameters
- //cAgent.Size = new Vector3(0, 0, m_avHeight);
- cAgent.AtAxis = m_CameraAtAxis;
- cAgent.LeftAxis = m_CameraLeftAxis;
- cAgent.UpAxis = m_CameraUpAxis;
-
- cAgent.Far = m_DrawDistance;
-
- // Throttles
- float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
- multiplier = 0.25f;
- }
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
- cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
-
- cAgent.HeadRotation = m_headrotation;
- cAgent.BodyRotation = m_bodyRot;
- cAgent.ControlFlags = (uint)m_AgentControlFlags;
-
- if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
- cAgent.GodLevel = (byte)m_godLevel;
- else
- cAgent.GodLevel = (byte) 0;
-
- cAgent.AlwaysRun = m_setAlwaysRun;
-
- try
- {
- // We might not pass the Wearables in all cases...
- // They're only needed so that persistent changes to the appearance
- // are preserved in the new region where the user is moving to.
- // But in Hypergrid we might not let this happen.
- int i = 0;
- UUID[] wears = new UUID[m_appearance.Wearables.Length * 2];
- foreach (AvatarWearable aw in m_appearance.Wearables)
- {
- if (aw != null)
- {
- wears[i++] = aw.ItemID;
- wears[i++] = aw.AssetID;
- }
- else
- {
- wears[i++] = UUID.Zero;
- wears[i++] = UUID.Zero;
- }
- }
- cAgent.Wearables = wears;
-
- cAgent.VisualParams = m_appearance.VisualParams;
-
- if (m_appearance.Texture != null)
- cAgent.AgentTextures = m_appearance.Texture.GetBytes();
- }
- catch (Exception e)
- {
- m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message);
- }
-
- //Attachments
- List attPoints = m_appearance.GetAttachedPoints();
- if (attPoints != null)
- {
- //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count);
- int i = 0;
- AttachmentData[] attachs = new AttachmentData[attPoints.Count];
- foreach (int point in attPoints)
- {
- attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point));
- }
- cAgent.Attachments = attachs;
- }
-
- lock (scriptedcontrols)
- {
- ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
- int i = 0;
-
- foreach (ScriptControllers c in scriptedcontrols.Values)
- {
- controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
- }
- cAgent.Controllers = controls;
- }
-
- // Animations
- try
- {
- cAgent.Anims = Animator.Animations.ToArray();
- }
- catch { }
-
- // cAgent.GroupID = ??
- // Groups???
-
- }
-
- public void CopyFrom(AgentData cAgent)
- {
- m_originRegionID = cAgent.RegionID;
-
- m_callbackURI = cAgent.CallbackURI;
-
- m_pos = cAgent.Position;
-
- m_velocity = cAgent.Velocity;
- m_CameraCenter = cAgent.Center;
- //m_avHeight = cAgent.Size.Z;
- m_CameraAtAxis = cAgent.AtAxis;
- m_CameraLeftAxis = cAgent.LeftAxis;
- m_CameraUpAxis = cAgent.UpAxis;
-
- m_DrawDistance = cAgent.Far;
-
- if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
- ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
-
- m_headrotation = cAgent.HeadRotation;
- m_bodyRot = cAgent.BodyRotation;
- m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags;
-
- if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
- m_godLevel = cAgent.GodLevel;
- m_setAlwaysRun = cAgent.AlwaysRun;
-
- uint i = 0;
- try
- {
- if (cAgent.Wearables == null)
- cAgent.Wearables = new UUID[0];
- AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2];
- for (uint n = 0; n < cAgent.Wearables.Length; n += 2)
- {
- UUID itemId = cAgent.Wearables[n];
- UUID assetId = cAgent.Wearables[n + 1];
- wears[i++] = new AvatarWearable(itemId, assetId);
- }
- m_appearance.Wearables = wears;
- Primitive.TextureEntry te;
- if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1)
- te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length);
- else
- te = AvatarAppearance.GetDefaultTexture();
- if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT))
- cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams();
- m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone());
- }
- catch (Exception e)
- {
- m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message);
- }
-
- // Attachments
- try
- {
- if (cAgent.Attachments != null)
- {
- m_appearance.ClearAttachments();
- foreach (AttachmentData att in cAgent.Attachments)
- {
- m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID);
- }
- }
- }
- catch { }
-
- try
- {
- lock (scriptedcontrols)
- {
- if (cAgent.Controllers != null)
- {
- scriptedcontrols.Clear();
-
- foreach (ControllerData c in cAgent.Controllers)
- {
- ScriptControllers sc = new ScriptControllers();
- sc.itemID = c.ItemID;
- sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
- sc.eventControls = (ScriptControlled)c.EventControls;
-
- scriptedcontrols[sc.itemID] = sc;
- }
- }
- }
- }
- catch { }
- // Animations
- try
- {
- Animator.ResetAnimations();
- Animator.Animations.FromArray(cAgent.Anims);
- }
- catch { }
-
- //cAgent.GroupID = ??
- //Groups???
- }
-
- public bool CopyAgent(out IAgentData agent)
- {
- agent = new CompleteAgentData();
- CopyTo((AgentData)agent);
- return true;
- }
-
- #endregion Child Agent Updates
-
- ///
- /// Handles part of the PID controller function for moving an avatar.
- ///
- public override void UpdateMovement()
- {
- if (m_forceToApply.HasValue)
- {
-
- Vector3 force = m_forceToApply.Value;
- m_updateflag = true;
- Velocity = force;
-
- m_forceToApply = null;
- }
- else
- {
- if (m_isNudging)
- {
- Vector3 force = Vector3.Zero;
-
- m_updateflag = true;
- Velocity = force;
- m_isNudging = false;
- m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
- }
- }
- }
-
- public override void SetText(string text, Vector3 color, double alpha)
- {
- throw new Exception("Can't set Text on avatar.");
- }
-
- ///
- /// Adds a physical representation of the avatar to the Physics plugin
- ///
- public void AddToPhysicalScene(bool isFlying)
- {
- PhysicsScene scene = m_scene.PhysicsScene;
-
- Vector3 pVec = AbsolutePosition;
-
- // Old bug where the height was in centimeters instead of meters
- if (m_avHeight == 127.0f)
- {
- m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f),
- isFlying);
- }
- else
- {
- m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
- new Vector3(0f, 0f, m_avHeight), isFlying);
- }
- scene.AddPhysicsActorTaint(m_physicsActor);
- //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
- m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
- m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
- m_physicsActor.SubscribeEvents(500);
- m_physicsActor.LocalID = LocalId;
- }
-
- private void OutOfBoundsCall(Vector3 pos)
- {
- //bool flying = m_physicsActor.Flying;
- //RemoveFromPhysicalScene();
-
- //AddToPhysicalScene(flying);
- if (ControllingClient != null)
- ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
- }
-
- // Event called by the physics plugin to tell the avatar about a collision.
- private void PhysicsCollisionUpdate(EventArgs e)
- {
- if (e == null)
- return;
-
- // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
- // as of this comment the interval is set in AddToPhysicalScene
- if (Animator!=null)
- {
- if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
- { // else its will lock out other animation changes, like ground sit.
- Animator.UpdateMovementAnimations();
- m_updateCount--;
- }
- }
-
- CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
- Dictionary coldata = collisionData.m_objCollisionList;
-
- CollisionPlane = Vector4.UnitW;
-
- if (m_lastColCount != coldata.Count)
- {
- m_updateCount = UPDATE_COUNT;
- m_lastColCount = coldata.Count;
- }
-
- if (coldata.Count != 0 && Animator != null)
- {
- switch (Animator.CurrentMovementAnimation)
- {
- case "STAND":
- case "WALK":
- case "RUN":
- case "CROUCH":
- case "CROUCHWALK":
- {
- ContactPoint lowest;
- lowest.SurfaceNormal = Vector3.Zero;
- lowest.Position = Vector3.Zero;
- lowest.Position.Z = Single.NaN;
-
- foreach (ContactPoint contact in coldata.Values)
- {
- if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z)
- {
- lowest = contact;
- }
- }
-
- CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
- }
- break;
- }
- }
-
- List thisHitColliders = new List();
- List endedColliders = new List();
- List startedColliders = new List();
-
- foreach (uint localid in coldata.Keys)
- {
- thisHitColliders.Add(localid);
- if (!m_lastColliders.Contains(localid))
- {
- startedColliders.Add(localid);
- }
- //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
- }
-
- // calculate things that ended colliding
- foreach (uint localID in m_lastColliders)
- {
- if (!thisHitColliders.Contains(localID))
- {
- endedColliders.Add(localID);
- }
- }
- //add the items that started colliding this time to the last colliders list.
- foreach (uint localID in startedColliders)
- {
- m_lastColliders.Add(localID);
- }
- // remove things that ended colliding from the last colliders list
- foreach (uint localID in endedColliders)
- {
- m_lastColliders.Remove(localID);
- }
-
- // do event notification
- if (startedColliders.Count > 0)
- {
- ColliderArgs StartCollidingMessage = new ColliderArgs();
- List colliding = new List();
- foreach (uint localId in startedColliders)
- {
- if (localId == 0)
- continue;
-
- SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
- string data = "";
- if (obj != null)
- {
- DetectedObject detobj = new DetectedObject();
- detobj.keyUUID = obj.UUID;
- detobj.nameStr = obj.Name;
- detobj.ownerUUID = obj.OwnerID;
- detobj.posVector = obj.AbsolutePosition;
- detobj.rotQuat = obj.GetWorldRotation();
- detobj.velVector = obj.Velocity;
- detobj.colliderType = 0;
- detobj.groupUUID = obj.GroupID;
- colliding.Add(detobj);
- }
- }
-
- if (colliding.Count > 0)
- {
- StartCollidingMessage.Colliders = colliding;
-
- foreach (SceneObjectGroup att in Attachments)
- Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
- }
- }
-
- if (endedColliders.Count > 0)
- {
- ColliderArgs EndCollidingMessage = new ColliderArgs();
- List colliding = new List();
- foreach (uint localId in endedColliders)
- {
- if (localId == 0)
- continue;
-
- SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
- string data = "";
- if (obj != null)
- {
- DetectedObject detobj = new DetectedObject();
- detobj.keyUUID = obj.UUID;
- detobj.nameStr = obj.Name;
- detobj.ownerUUID = obj.OwnerID;
- detobj.posVector = obj.AbsolutePosition;
- detobj.rotQuat = obj.GetWorldRotation();
- detobj.velVector = obj.Velocity;
- detobj.colliderType = 0;
- detobj.groupUUID = obj.GroupID;
- colliding.Add(detobj);
- }
- }
-
- if (colliding.Count > 0)
- {
- EndCollidingMessage.Colliders = colliding;
-
- foreach (SceneObjectGroup att in Attachments)
- Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
- }
- }
-
- if (thisHitColliders.Count > 0)
- {
- ColliderArgs CollidingMessage = new ColliderArgs();
- List colliding = new List();
- foreach (uint localId in thisHitColliders)
- {
- if (localId == 0)
- continue;
-
- SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
- string data = "";
- if (obj != null)
- {
- DetectedObject detobj = new DetectedObject();
- detobj.keyUUID = obj.UUID;
- detobj.nameStr = obj.Name;
- detobj.ownerUUID = obj.OwnerID;
- detobj.posVector = obj.AbsolutePosition;
- detobj.rotQuat = obj.GetWorldRotation();
- detobj.velVector = obj.Velocity;
- detobj.colliderType = 0;
- detobj.groupUUID = obj.GroupID;
- colliding.Add(detobj);
- }
- }
-
- if (colliding.Count > 0)
- {
- CollidingMessage.Colliders = colliding;
-
- lock (m_attachments)
- {
- foreach (SceneObjectGroup att in m_attachments)
- Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
- }
- }
- }
-
- if (m_invulnerable)
- return;
-
- float starthealth = Health;
- uint killerObj = 0;
- foreach (uint localid in coldata.Keys)
- {
- SceneObjectPart part = Scene.GetSceneObjectPart(localid);
-
- if (part != null && part.ParentGroup.Damage != -1.0f)
- Health -= part.ParentGroup.Damage;
- else
- {
- if (coldata[localid].PenetrationDepth >= 0.10f)
- Health -= coldata[localid].PenetrationDepth * 5.0f;
- }
-
- if (Health <= 0.0f)
- {
- if (localid != 0)
- killerObj = localid;
- }
- //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
- }
- //Health = 100;
- if (!m_invulnerable)
- {
- if (starthealth != Health)
- {
- ControllingClient.SendHealth(Health);
- }
- if (m_health <= 0)
- m_scene.EventManager.TriggerAvatarKill(killerObj, this);
- }
- }
-
- public void setHealthWithUpdate(float health)
- {
- Health = health;
- ControllingClient.SendHealth(Health);
- }
-
- public void Close()
- {
- lock (m_attachments)
- {
- // Delete attachments from scene
- // Don't try to save, as this thread won't live long
- // enough to complete the save. This would cause no copy
- // attachments to poof!
- //
- foreach (SceneObjectGroup grp in m_attachments)
- {
- m_scene.DeleteSceneObject(grp, false);
- }
- m_attachments.Clear();
- }
-
- lock (m_knownChildRegions)
- {
- m_knownChildRegions.Clear();
- }
-
- lock (m_reprioritization_timer)
- {
- m_reprioritization_timer.Enabled = false;
- m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
- }
-
- // I don't get it but mono crashes when you try to dispose of this timer,
- // unsetting the elapsed callback should be enough to allow for cleanup however.
- // m_reprioritizationTimer.Dispose();
-
- m_sceneViewer.Close();
-
- RemoveFromPhysicalScene();
- m_animator.Close();
- m_animator = null;
- }
-
- public void AddAttachment(SceneObjectGroup gobj)
- {
- lock (m_attachments)
- {
- m_attachments.Add(gobj);
- }
- }
-
- public bool HasAttachments()
- {
- return m_attachments.Count > 0;
- }
-
- public bool HasScriptedAttachments()
- {
- lock (m_attachments)
- {
- foreach (SceneObjectGroup gobj in m_attachments)
- {
- if (gobj != null)
- {
- if (gobj.RootPart.Inventory.ContainsScripts())
- return true;
- }
- }
- }
- return false;
- }
-
- public void RemoveAttachment(SceneObjectGroup gobj)
- {
- lock (m_attachments)
- {
- if (m_attachments.Contains(gobj))
- {
- m_attachments.Remove(gobj);
- }
- }
- }
-
- public bool ValidateAttachments()
- {
- lock (m_attachments)
- {
- // Validate
- foreach (SceneObjectGroup gobj in m_attachments)
- {
- if (gobj == null)
- return false;
-
- if (gobj.IsDeleted)
- return false;
- }
- }
- return true;
- }
-
- ///
- /// Send a script event to this scene presence's attachments
- ///
- /// The name of the event
- /// The arguments for the event
- public void SendScriptEventToAttachments(string eventName, Object[] args)
- {
- if (m_scriptEngines != null)
- {
- lock (m_attachments)
- {
- foreach (SceneObjectGroup grp in m_attachments)
- {
- // 16384 is CHANGED_ANIMATION
- //
- // Send this to all attachment root prims
- //
- foreach (IScriptModule m in m_scriptEngines)
- {
- if (m == null) // No script engine loaded
- continue;
-
- m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
- }
- }
- }
- }
- }
-
-
- public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
- {
- m_controllingClient = client;
- m_regionInfo = region;
- m_scene = scene;
-
- RegisterToEvents();
- if (m_controllingClient != null)
- {
- m_controllingClient.ProcessPendingPackets();
- }
- /*
- AbsolutePosition = client.StartPos;
-
- Animations = new AvatarAnimations();
- Animations.LoadAnims();
-
- m_animations = new List();
- m_animations.Add(Animations.AnimsUUID["STAND"]);
- m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
-
- SetDirectionVectors();
- */
- }
-
- internal void PushForce(Vector3 impulse)
- {
- if (PhysicsActor != null)
- {
- PhysicsActor.AddForce(impulse,true);
- }
- }
-
- public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
- {
- ScriptControllers obj = new ScriptControllers();
- obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
- obj.eventControls = ScriptControlled.CONTROL_ZERO;
-
- obj.itemID = Script_item_UUID;
- if (pass_on == 0 && accept == 0)
- {
- IgnoredControls |= (ScriptControlled)controls;
- obj.ignoreControls = (ScriptControlled)controls;
- }
-
- if (pass_on == 0 && accept == 1)
- {
- IgnoredControls |= (ScriptControlled)controls;
- obj.ignoreControls = (ScriptControlled)controls;
- obj.eventControls = (ScriptControlled)controls;
- }
- if (pass_on == 1 && accept == 1)
- {
- IgnoredControls = ScriptControlled.CONTROL_ZERO;
- obj.eventControls = (ScriptControlled)controls;
- obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
- }
-
- lock (scriptedcontrols)
- {
- if (pass_on == 1 && accept == 0)
- {
- IgnoredControls &= ~(ScriptControlled)controls;
- if (scriptedcontrols.ContainsKey(Script_item_UUID))
- scriptedcontrols.Remove(Script_item_UUID);
- }
- else
- {
- scriptedcontrols[Script_item_UUID] = obj;
- }
- }
- ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
- }
-
- public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
- {
- IgnoredControls = ScriptControlled.CONTROL_ZERO;
- lock (scriptedcontrols)
- {
- scriptedcontrols.Clear();
- }
- ControllingClient.SendTakeControls(int.MaxValue, false, false);
- }
-
- public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
- {
- ScriptControllers takecontrols;
-
- lock (scriptedcontrols)
- {
- if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols))
- {
- ScriptControlled sctc = takecontrols.eventControls;
-
- ControllingClient.SendTakeControls((int)sctc, false, false);
- ControllingClient.SendTakeControls((int)sctc, true, false);
-
- scriptedcontrols.Remove(Script_item_UUID);
- IgnoredControls = ScriptControlled.CONTROL_ZERO;
- foreach (ScriptControllers scData in scriptedcontrols.Values)
- {
- IgnoredControls |= scData.ignoreControls;
- }
- }
- }
- }
-
- internal void SendControlToScripts(uint flags)
- {
- ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
-
- if (MouseDown)
- {
- allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
- {
- allflags = ScriptControlled.CONTROL_ZERO;
- MouseDown = true;
- }
- }
-
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
- {
- allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
- MouseDown = true;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
- {
- allflags |= ScriptControlled.CONTROL_LBUTTON;
- MouseDown = true;
- }
-
- // find all activated controls, whether the scripts are interested in them or not
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_FWD;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_BACK;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_UP;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_DOWN;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_LEFT;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_RIGHT;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_ROT_LEFT;
- }
- // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
- if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
- {
- lock (scriptedcontrols)
- {
- foreach (KeyValuePair kvp in scriptedcontrols)
- {
- UUID scriptUUID = kvp.Key;
- ScriptControllers scriptControlData = kvp.Value;
-
- ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
- ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
- ScriptControlled localChange = localHeld ^ localLast; // the changed bits
- if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
- {
- // only send if still pressed or just changed
- m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange);
- }
- }
- }
- }
-
- LastCommands = allflags;
- }
-
- internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored)
- {
- if (ignored == ScriptControlled.CONTROL_ZERO)
- return flags;
-
- if ((ignored & ScriptControlled.CONTROL_BACK) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
- if ((ignored & ScriptControlled.CONTROL_FWD) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS);
- if ((ignored & ScriptControlled.CONTROL_DOWN) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG);
- if ((ignored & ScriptControlled.CONTROL_UP) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS);
- if ((ignored & ScriptControlled.CONTROL_LEFT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
- if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG);
- if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG);
- if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS);
- if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN);
- if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN);
-
- //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
- //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
- //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
- //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
- //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
- //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
- //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
-
- return flags;
- }
-
- ///
- /// RezAttachments. This should only be called upon login on the first region.
- /// Attachment rezzings on crossings and TPs are done in a different way.
- ///
- public void RezAttachments()
- {
- if (null == m_appearance)
- {
- m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
- return;
- }
-
- XmlDocument doc = new XmlDocument();
- string stateData = String.Empty;
-
- IAttachmentsService attServ = m_scene.RequestModuleInterface();
- if (attServ != null)
- {
- m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
- stateData = attServ.Get(ControllingClient.AgentId.ToString());
- if (stateData != String.Empty)
- {
- try
- {
- doc.LoadXml(stateData);
- }
- catch { }
- }
- }
-
- Dictionary itemData = new Dictionary();
-
- XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
- if (nodes.Count > 0)
- {
- foreach (XmlNode n in nodes)
- {
- XmlElement elem = (XmlElement)n;
- string itemID = elem.GetAttribute("ItemID");
- string xml = elem.InnerXml;
-
- itemData[new UUID(itemID)] = xml;
- }
- }
-
- List attPoints = m_appearance.GetAttachedPoints();
- foreach (int p in attPoints)
- {
- if (m_isDeleted)
- return;
-
- UUID itemID = m_appearance.GetAttachedItem(p);
- UUID assetID = m_appearance.GetAttachedAsset(p);
-
- // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
- // But they're not used anyway, the item is being looked up for now, so let's proceed.
- //if (UUID.Zero == assetID)
- //{
- // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID);
- // continue;
- //}
-
- try
- {
- string xmlData;
- XmlDocument d = new XmlDocument();
- UUID asset;
- if (itemData.TryGetValue(itemID, out xmlData))
- {
- d.LoadXml(xmlData);
- m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
-
- // Rez from inventory
- asset
- = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
-
- }
- else
- {
- // Rez from inventory (with a null doc to let
- // CHANGED_OWNER happen)
- asset
- = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
- }
-
- m_log.InfoFormat(
- "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
- p, itemID, assetID, asset);
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString());
- }
- }
- }
-
- private void ReprioritizeUpdates()
- {
- if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time)
- {
- lock (m_reprioritization_timer)
- {
- if (!m_reprioritizing)
- m_reprioritization_timer.Enabled = m_reprioritizing = true;
- else
- m_reprioritization_called = true;
- }
- }
- }
-
- private void Reprioritize(object sender, ElapsedEventArgs e)
- {
- m_controllingClient.ReprioritizeUpdates();
-
- lock (m_reprioritization_timer)
- {
- m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called;
- m_reprioritization_called = false;
- }
- }
-
- private Vector3 Quat2Euler(Quaternion rot){
- float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
- (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
- float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
- float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
- (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
- return(new Vector3(x,y,z));
- }
-
-
- }
-}
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Xml;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Timers;
+using OpenMetaverse;
+using log4net;
+using OpenSim.Framework;
+using OpenSim.Framework.Client;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes.Animation;
+using OpenSim.Region.Framework.Scenes.Types;
+using OpenSim.Region.Physics.Manager;
+using GridRegion = OpenSim.Services.Interfaces.GridRegion;
+using OpenSim.Services.Interfaces;
+
+namespace OpenSim.Region.Framework.Scenes
+{
+ enum ScriptControlled : uint
+ {
+ CONTROL_ZERO = 0,
+ CONTROL_FWD = 1,
+ CONTROL_BACK = 2,
+ CONTROL_LEFT = 4,
+ CONTROL_RIGHT = 8,
+ CONTROL_UP = 16,
+ CONTROL_DOWN = 32,
+ CONTROL_ROT_LEFT = 256,
+ CONTROL_ROT_RIGHT = 512,
+ CONTROL_LBUTTON = 268435456,
+ CONTROL_ML_LBUTTON = 1073741824
+ }
+
+ struct ScriptControllers
+ {
+ public UUID itemID;
+ public ScriptControlled ignoreControls;
+ public ScriptControlled eventControls;
+ }
+
+ public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs);
+
+ public class ScenePresence : EntityBase, ISceneEntity
+ {
+// ~ScenePresence()
+// {
+// m_log.Debug("[ScenePresence] Destructor called");
+// }
+
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
+// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
+ private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
+ private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
+
+ ///
+ /// Experimentally determined "fudge factor" to make sit-target positions
+ /// the same as in SecondLife. Fudge factor was tested for 36 different
+ /// test cases including prims of type box, sphere, cylinder, and torus,
+ /// with varying parameters for sit target location, prim size, prim
+ /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
+ /// issue #1716
+ ///
+// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
+ // Value revised by KF 091121 by comparison with SL.
+ private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
+
+ public UUID currentParcelUUID = UUID.Zero;
+
+ private ISceneViewer m_sceneViewer;
+
+ ///
+ /// The animator for this avatar
+ ///
+ public ScenePresenceAnimator Animator
+ {
+ get { return m_animator; }
+ }
+ protected ScenePresenceAnimator m_animator;
+
+ ///
+ /// The scene objects attached to this avatar. Do not change this list directly - use methods such as
+ /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it.
+ ///
+ public List Attachments
+ {
+ get { return m_attachments; }
+ }
+ protected List m_attachments = new List();
+
+ private Dictionary scriptedcontrols = new Dictionary();
+ private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
+ private bool MouseDown = false;
+ private SceneObjectGroup proxyObjectGroup;
+ //private SceneObjectPart proxyObjectPart = null;
+ public Vector3 lastKnownAllowedPosition;
+ public bool sentMessageAboutRestrictedParcelFlyingDown;
+ public Vector4 CollisionPlane = Vector4.UnitW;
+
+ private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
+ private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
+ private Vector3 m_lastPosition;
+ private Vector3 m_lastWorldPosition;
+ private Quaternion m_lastRotation;
+ private Vector3 m_lastVelocity;
+ //private int m_lastTerseSent;
+
+ private bool m_updateflag;
+ private byte m_movementflag;
+ private Vector3? m_forceToApply;
+ private uint m_requestedSitTargetID;
+ private UUID m_requestedSitTargetUUID;
+ public bool SitGround = false;
+
+ private SendCourseLocationsMethod m_sendCourseLocationsMethod;
+
+ private bool m_startAnimationSet;
+
+ //private Vector3 m_requestedSitOffset = new Vector3();
+
+ private Vector3 m_LastFinitePos;
+
+ private float m_sitAvatarHeight = 2.0f;
+
+ private int m_godLevel;
+ private int m_userLevel;
+
+ private bool m_invulnerable = true;
+
+ private Vector3 m_lastChildAgentUpdatePosition;
+ private Vector3 m_lastChildAgentUpdateCamPosition;
+
+ private int m_perfMonMS;
+
+ private bool m_setAlwaysRun;
+ private bool m_forceFly;
+ private bool m_flyDisabled;
+
+ private float m_speedModifier = 1.0f;
+
+ private Quaternion m_bodyRot= Quaternion.Identity;
+
+ private Quaternion m_bodyRotPrevious = Quaternion.Identity;
+
+ private const int LAND_VELOCITYMAG_MAX = 12;
+
+ public bool IsRestrictedToRegion;
+
+ public string JID = String.Empty;
+
+ private float m_health = 100f;
+
+ // Default AV Height
+ private float m_avHeight = 127.0f;
+
+ protected RegionInfo m_regionInfo;
+ protected ulong crossingFromRegion;
+
+ private readonly Vector3[] Dir_Vectors = new Vector3[11];
+ private bool m_isNudging = false;
+
+ // Position of agent's camera in world (region cordinates)
+ protected Vector3 m_CameraCenter;
+ protected Vector3 m_lastCameraCenter;
+
+ protected Timer m_reprioritization_timer;
+ protected bool m_reprioritizing;
+ protected bool m_reprioritization_called;
+
+ // Use these three vectors to figure out what the agent is looking at
+ // Convert it to a Matrix and/or Quaternion
+ protected Vector3 m_CameraAtAxis;
+ protected Vector3 m_CameraLeftAxis;
+ protected Vector3 m_CameraUpAxis;
+ private AgentManager.ControlFlags m_AgentControlFlags;
+ private Quaternion m_headrotation = Quaternion.Identity;
+ private byte m_state;
+
+ //Reuse the Vector3 instead of creating a new one on the UpdateMovement method
+// private Vector3 movementvector;
+
+ private bool m_autopilotMoving;
+ private Vector3 m_autoPilotTarget;
+ private bool m_sitAtAutoTarget;
+ private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
+
+ private string m_nextSitAnimation = String.Empty;
+
+ //PauPaw:Proper PID Controler for autopilot************
+ private bool m_moveToPositionInProgress;
+ private Vector3 m_moveToPositionTarget;
+ private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+
+ private bool m_followCamAuto;
+
+ private int m_movementUpdateCount;
+ private int m_lastColCount = -1; //KF: Look for Collision chnages
+ private int m_updateCount = 0; //KF: Update Anims for a while
+ private static readonly int UPDATE_COUNT = 10; // how many frames to update for
+ private const int NumMovementsBetweenRayCast = 5;
+ private List m_lastColliders = new List();
+
+ private bool CameraConstraintActive;
+ //private int m_moveToPositionStateStatus;
+ //*****************************************************
+
+ // Agent's Draw distance.
+ protected float m_DrawDistance;
+
+ protected AvatarAppearance m_appearance;
+
+ // neighbouring regions we have enabled a child agent in
+ // holds the seed cap for the child agent in that region
+ private Dictionary m_knownChildRegions = new Dictionary();
+
+ ///
+ /// Implemented Control Flags
+ ///
+ private enum Dir_ControlFlags
+ {
+ DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
+ DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
+ DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
+ DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
+ DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
+ DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
+ DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
+ DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
+ DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
+ DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
+ DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
+ }
+
+ ///
+ /// Position at which a significant movement was made
+ ///
+ private Vector3 posLastSignificantMove;
+
+ // For teleports and crossings callbacks
+ string m_callbackURI;
+ UUID m_originRegionID;
+
+ ulong m_rootRegionHandle;
+
+ ///
+ /// Script engines present in the scene
+ ///
+ private IScriptModule[] m_scriptEngines;
+
+ #region Properties
+
+ ///
+ /// Physical scene representation of this Avatar.
+ ///
+ public PhysicsActor PhysicsActor
+ {
+ set { m_physicsActor = value; }
+ get { return m_physicsActor; }
+ }
+
+ public byte MovementFlag
+ {
+ set { m_movementflag = value; }
+ get { return m_movementflag; }
+ }
+
+ public bool Updated
+ {
+ set { m_updateflag = value; }
+ get { return m_updateflag; }
+ }
+
+ public bool Invulnerable
+ {
+ set { m_invulnerable = value; }
+ get { return m_invulnerable; }
+ }
+
+ public int UserLevel
+ {
+ get { return m_userLevel; }
+ }
+
+ public int GodLevel
+ {
+ get { return m_godLevel; }
+ }
+
+ public ulong RegionHandle
+ {
+ get { return m_rootRegionHandle; }
+ }
+
+ public Vector3 CameraPosition
+ {
+ get { return m_CameraCenter; }
+ }
+
+ public Quaternion CameraRotation
+ {
+ get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); }
+ }
+
+ public Vector3 CameraAtAxis
+ {
+ get { return m_CameraAtAxis; }
+ }
+
+ public Vector3 CameraLeftAxis
+ {
+ get { return m_CameraLeftAxis; }
+ }
+
+ public Vector3 CameraUpAxis
+ {
+ get { return m_CameraUpAxis; }
+ }
+
+ public Vector3 Lookat
+ {
+ get
+ {
+ Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0);
+
+ if (a == Vector3.Zero)
+ return a;
+
+ return Util.GetNormalizedVector(a);
+ }
+ }
+
+ private readonly string m_firstname;
+
+ public string Firstname
+ {
+ get { return m_firstname; }
+ }
+
+ private readonly string m_lastname;
+
+ public string Lastname
+ {
+ get { return m_lastname; }
+ }
+
+ private string m_grouptitle;
+
+ public string Grouptitle
+ {
+ get { return m_grouptitle; }
+ set { m_grouptitle = value; }
+ }
+
+ public float DrawDistance
+ {
+ get { return m_DrawDistance; }
+ }
+
+ protected bool m_allowMovement = true;
+
+ public bool AllowMovement
+ {
+ get { return m_allowMovement; }
+ set { m_allowMovement = value; }
+ }
+
+ public bool SetAlwaysRun
+ {
+ get
+ {
+ if (PhysicsActor != null)
+ {
+ return PhysicsActor.SetAlwaysRun;
+ }
+ else
+ {
+ return m_setAlwaysRun;
+ }
+ }
+ set
+ {
+ m_setAlwaysRun = value;
+ if (PhysicsActor != null)
+ {
+ PhysicsActor.SetAlwaysRun = value;
+ }
+ }
+ }
+
+ public byte State
+ {
+ get { return m_state; }
+ set { m_state = value; }
+ }
+
+ public uint AgentControlFlags
+ {
+ get { return (uint)m_AgentControlFlags; }
+ set { m_AgentControlFlags = (AgentManager.ControlFlags)value; }
+ }
+
+ ///
+ /// This works out to be the ClientView object associated with this avatar, or it's client connection manager
+ ///
+ private IClientAPI m_controllingClient;
+
+ protected PhysicsActor m_physicsActor;
+
+ ///
+ /// The client controlling this presence
+ ///
+ public IClientAPI ControllingClient
+ {
+ get { return m_controllingClient; }
+ }
+
+ public IClientCore ClientView
+ {
+ get { return (IClientCore) m_controllingClient; }
+ }
+
+ protected Vector3 m_parentPosition;
+ public Vector3 ParentPosition
+ {
+ get { return m_parentPosition; }
+ set { m_parentPosition = value; }
+ }
+
+ ///
+ /// Position of this avatar relative to the region the avatar is in
+ ///
+ public override Vector3 AbsolutePosition
+ {
+ get
+ {
+ PhysicsActor actor = m_physicsActor;
+// if (actor != null)
+ if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
+ m_pos = actor.Position;
+
+ // If we're sitting, we need to update our position
+ if (m_parentID != 0)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
+ if (part != null)
+ m_parentPosition = part.AbsolutePosition;
+ }
+
+ return m_parentPosition + m_pos;
+ }
+ set
+ {
+ PhysicsActor actor = m_physicsActor;
+ if (actor != null)
+ {
+ try
+ {
+ lock (m_scene.SyncRoot)
+ m_physicsActor.Position = value;
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
+ }
+ }
+
+ if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
+ m_pos = value;
+ m_parentPosition = Vector3.Zero;
+ }
+ }
+
+ public Vector3 OffsetPosition
+ {
+ get { return m_pos; }
+ set { m_pos = value; }
+ }
+
+ ///
+ /// Current velocity of the avatar.
+ ///
+ public override Vector3 Velocity
+ {
+ get
+ {
+ PhysicsActor actor = m_physicsActor;
+ if (actor != null)
+ m_velocity = actor.Velocity;
+
+ return m_velocity;
+ }
+ set
+ {
+ PhysicsActor actor = m_physicsActor;
+ if (actor != null)
+ {
+ try
+ {
+ lock (m_scene.SyncRoot)
+ actor.Velocity = value;
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message);
+ }
+ }
+
+ m_velocity = value;
+ }
+ }
+
+ public Quaternion OffsetRotation
+ {
+ get { return m_offsetRotation; }
+ set { m_offsetRotation = value; }
+ }
+
+ public Quaternion Rotation
+ {
+ get {
+ if (m_parentID != 0)
+ {
+ if (m_offsetRotation != null)
+ {
+ return m_offsetRotation;
+ }
+ else
+ {
+ return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ }
+ else
+ {
+ return m_bodyRot;
+ }
+ }
+ set {
+ m_bodyRot = value;
+ if (m_parentID != 0)
+ {
+ m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ }
+ }
+
+ public Quaternion PreviousRotation
+ {
+ get { return m_bodyRotPrevious; }
+ set { m_bodyRotPrevious = value; }
+ }
+
+ ///
+ /// If this is true, agent doesn't have a representation in this scene.
+ /// this is an agent 'looking into' this scene from a nearby scene(region)
+ ///
+ /// if False, this agent has a representation in this scene
+ ///
+ private bool m_isChildAgent = true;
+
+ public bool IsChildAgent
+ {
+ get { return m_isChildAgent; }
+ set { m_isChildAgent = value; }
+ }
+
+ private uint m_parentID;
+
+
+ private UUID m_linkedPrim;
+
+ public uint ParentID
+ {
+ get { return m_parentID; }
+ set { m_parentID = value; }
+ }
+
+ public UUID LinkedPrim
+ {
+ get { return m_linkedPrim; }
+ set { m_linkedPrim = value; }
+ }
+
+ public float Health
+ {
+ get { return m_health; }
+ set { m_health = value; }
+ }
+
+ ///
+ /// These are the region handles known by the avatar.
+ ///
+ public List KnownChildRegionHandles
+ {
+ get
+ {
+ if (m_knownChildRegions.Count == 0)
+ return new List();
+ else
+ return new List(m_knownChildRegions.Keys);
+ }
+ }
+
+ public Dictionary KnownRegions
+ {
+ get { return m_knownChildRegions; }
+ set
+ {
+ m_knownChildRegions = value;
+ }
+ }
+
+ public ISceneViewer SceneViewer
+ {
+ get { return m_sceneViewer; }
+ }
+
+ public void AdjustKnownSeeds()
+ {
+ Dictionary seeds;
+
+ if (Scene.CapsModule != null)
+ seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
+ else
+ seeds = new Dictionary();
+
+ List old = new List();
+ foreach (ulong handle in seeds.Keys)
+ {
+ uint x, y;
+ Utils.LongToUInts(handle, out x, out y);
+ x = x / Constants.RegionSize;
+ y = y / Constants.RegionSize;
+ if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
+ {
+ old.Add(handle);
+ }
+ }
+ DropOldNeighbours(old);
+
+ if (Scene.CapsModule != null)
+ Scene.CapsModule.SetChildrenSeed(UUID, seeds);
+
+ KnownRegions = seeds;
+ //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
+ //DumpKnownRegions();
+ }
+
+ public void DumpKnownRegions()
+ {
+ m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================");
+ foreach (KeyValuePair kvp in KnownRegions)
+ {
+ uint x, y;
+ Utils.LongToUInts(kvp.Key, out x, out y);
+ x = x / Constants.RegionSize;
+ y = y / Constants.RegionSize;
+ m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
+ }
+ }
+
+ private bool m_inTransit;
+ private bool m_mouseLook;
+ private bool m_leftButtonDown;
+
+ public bool IsInTransit
+ {
+ get { return m_inTransit; }
+ set { m_inTransit = value; }
+ }
+
+ public float SpeedModifier
+ {
+ get { return m_speedModifier; }
+ set { m_speedModifier = value; }
+ }
+
+ public bool ForceFly
+ {
+ get { return m_forceFly; }
+ set { m_forceFly = value; }
+ }
+
+ public bool FlyDisabled
+ {
+ get { return m_flyDisabled; }
+ set { m_flyDisabled = value; }
+ }
+
+ public string Viewer
+ {
+ get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; }
+ }
+
+ #endregion
+
+ #region Constructor(s)
+
+ public ScenePresence()
+ {
+ m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
+ CreateSceneViewer();
+ m_animator = new ScenePresenceAnimator(this);
+ }
+
+ private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
+ {
+ m_rootRegionHandle = reginfo.RegionHandle;
+ m_controllingClient = client;
+ m_firstname = m_controllingClient.FirstName;
+ m_lastname = m_controllingClient.LastName;
+ m_name = String.Format("{0} {1}", m_firstname, m_lastname);
+ m_scene = world;
+ m_uuid = client.AgentId;
+ m_regionInfo = reginfo;
+ m_localId = m_scene.AllocateLocalId();
+
+ UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
+
+ if (account != null)
+ m_userLevel = account.UserLevel;
+
+ IGroupsModule gm = m_scene.RequestModuleInterface();
+ if (gm != null)
+ m_grouptitle = gm.GetGroupTitle(m_uuid);
+
+ m_scriptEngines = m_scene.RequestModuleInterfaces();
+
+ AbsolutePosition = posLastSignificantMove = m_CameraCenter =
+ m_lastCameraCenter = m_controllingClient.StartPos;
+
+ m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
+ m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
+ m_reprioritization_timer.AutoReset = false;
+
+ AdjustKnownSeeds();
+ Animator.TrySetMovementAnimation("STAND");
+ // we created a new ScenePresence (a new child agent) in a fresh region.
+ // Request info about all the (root) agents in this region
+ // Note: This won't send data *to* other clients in that region (children don't send)
+ SendInitialFullUpdateToAllClients();
+ RegisterToEvents();
+ if (m_controllingClient != null)
+ {
+ m_controllingClient.ProcessPendingPackets();
+ }
+ SetDirectionVectors();
+ }
+
+ public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
+ AvatarWearable[] wearables)
+ : this(client, world, reginfo)
+ {
+ m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
+ }
+
+ public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
+ : this(client, world, reginfo)
+ {
+ m_appearance = appearance;
+ }
+
+ private void CreateSceneViewer()
+ {
+ m_sceneViewer = new SceneViewer(this);
+ }
+
+ public void RegisterToEvents()
+ {
+ m_controllingClient.OnRequestWearables += SendWearables;
+ m_controllingClient.OnSetAppearance += SetAppearance;
+ m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
+ //m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
+ m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
+ m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
+ m_controllingClient.OnAgentSit += HandleAgentSit;
+ m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
+ m_controllingClient.OnStartAnim += HandleStartAnim;
+ m_controllingClient.OnStopAnim += HandleStopAnim;
+ m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
+ m_controllingClient.OnAutoPilotGo += DoAutoPilot;
+ m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
+
+ // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
+ // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
+ }
+
+ private void SetDirectionVectors()
+ {
+ Dir_Vectors[0] = Vector3.UnitX; //FORWARD
+ Dir_Vectors[1] = -Vector3.UnitX; //BACK
+ Dir_Vectors[2] = Vector3.UnitY; //LEFT
+ Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
+ Dir_Vectors[4] = Vector3.UnitZ; //UP
+ Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
+ Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
+ Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
+ Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
+ Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
+ Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
+ }
+
+ private Vector3[] GetWalkDirectionVectors()
+ {
+ Vector3[] vector = new Vector3[11];
+ vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
+ vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
+ vector[2] = Vector3.UnitY; //LEFT
+ vector[3] = -Vector3.UnitY; //RIGHT
+ vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
+ vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
+ vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
+ vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
+ vector[8] = Vector3.UnitY; //LEFT_NUDGE
+ vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
+ vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
+ return vector;
+ }
+
+ private bool[] GetDirectionIsNudge()
+ {
+ bool[] isNudge = new bool[11];
+ isNudge[0] = false; //FORWARD
+ isNudge[1] = false; //BACK
+ isNudge[2] = false; //LEFT
+ isNudge[3] = false; //RIGHT
+ isNudge[4] = false; //UP
+ isNudge[5] = false; //DOWN
+ isNudge[6] = true; //FORWARD_NUDGE
+ isNudge[7] = true; //BACK_NUDGE
+ isNudge[8] = true; //LEFT_NUDGE
+ isNudge[9] = true; //RIGHT_NUDGE
+ isNudge[10] = true; //DOWN_Nudge
+ return isNudge;
+ }
+
+
+ #endregion
+
+ public uint GenerateClientFlags(UUID ObjectID)
+ {
+ return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
+ }
+
+ ///
+ /// Send updates to the client about prims which have been placed on the update queue. We don't
+ /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
+ /// timestamp has already been sent.
+ ///
+ public void SendPrimUpdates()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ m_sceneViewer.SendPrimUpdates();
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ #region Status Methods
+
+ ///
+ /// This turns a child agent, into a root agent
+ /// This is called when an agent teleports into a region, or if an
+ /// agent crosses into this region from a neighbor over the border
+ ///
+ public void MakeRootAgent(Vector3 pos, bool isFlying)
+ {
+ m_log.DebugFormat(
+ "[SCENE]: Upgrading child to root agent for {0} in {1}",
+ Name, m_scene.RegionInfo.RegionName);
+
+ //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
+
+ IGroupsModule gm = m_scene.RequestModuleInterface();
+ if (gm != null)
+ m_grouptitle = gm.GetGroupTitle(m_uuid);
+
+ m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
+ m_scene.SetRootAgentScene(m_uuid);
+
+ // Moved this from SendInitialData to ensure that m_appearance is initialized
+ // before the inventory is processed in MakeRootAgent. This fixes a race condition
+ // related to the handling of attachments
+ //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
+ if (m_scene.TestBorderCross(pos, Cardinals.E))
+ {
+ Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
+ pos.X = crossedBorder.BorderLine.Z - 1;
+ }
+
+ if (m_scene.TestBorderCross(pos, Cardinals.N))
+ {
+ Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
+ pos.Y = crossedBorder.BorderLine.Z - 1;
+ }
+
+ //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
+ //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
+ //they'll bypass the landing point. But I can't think of any decent way of fixing this.
+ if (KnownChildRegionHandles.Count == 0)
+ {
+ ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
+ if (land != null)
+ {
+ //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ {
+ pos = land.LandData.UserLocation;
+ }
+ }
+ }
+
+ if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
+ {
+ Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
+
+ if (pos.X < 0)
+ {
+ emergencyPos.X = (int)Constants.RegionSize + pos.X;
+ if (!(pos.Y < 0))
+ emergencyPos.Y = pos.Y;
+ if (!(pos.Z < 0))
+ emergencyPos.Z = pos.Z;
+ }
+ if (pos.Y < 0)
+ {
+ emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
+ if (!(pos.X < 0))
+ emergencyPos.X = pos.X;
+ if (!(pos.Z < 0))
+ emergencyPos.Z = pos.Z;
+ }
+ if (pos.Z < 0)
+ {
+ emergencyPos.Z = 128;
+ if (!(pos.Y < 0))
+ emergencyPos.Y = pos.Y;
+ if (!(pos.X < 0))
+ emergencyPos.X = pos.X;
+ }
+ }
+
+ if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
+ {
+ m_log.WarnFormat(
+ "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
+ pos, Name, UUID);
+
+ if (pos.X < 0f) pos.X = 0f;
+ if (pos.Y < 0f) pos.Y = 0f;
+ if (pos.Z < 0f) pos.Z = 0f;
+ }
+
+ float localAVHeight = 1.56f;
+ if (m_avHeight != 127.0f)
+ {
+ localAVHeight = m_avHeight;
+ }
+
+ float posZLimit = 0;
+
+ if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
+ posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
+
+ float newPosZ = posZLimit + localAVHeight / 2;
+ if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
+ {
+ pos.Z = newPosZ;
+ }
+ AbsolutePosition = pos;
+
+ AddToPhysicalScene(isFlying);
+
+ if (m_forceFly)
+ {
+ m_physicsActor.Flying = true;
+ }
+ else if (m_flyDisabled)
+ {
+ m_physicsActor.Flying = false;
+ }
+
+ if (m_appearance != null)
+ {
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+ }
+ else
+ {
+ m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName);
+ // emergency; this really shouldn't happen
+ m_appearance = new AvatarAppearance(UUID);
+ }
+
+ // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
+ // avatar to return to the standing position in mid-air. On login it looks like this is being sent
+ // elsewhere anyway
+ // Animator.SendAnimPack();
+
+ m_scene.SwapRootAgentCount(false);
+
+ //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
+ //if (userInfo != null)
+ // userInfo.FetchInventory();
+ //else
+ // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid);
+
+ // On the next prim update, all objects will be sent
+ //
+ m_sceneViewer.Reset();
+
+ m_isChildAgent = false;
+
+ // send the animations of the other presences to me
+ m_scene.ForEachScenePresence(delegate(ScenePresence presence)
+ {
+ if (presence != this)
+ presence.Animator.SendAnimPackToClient(ControllingClient);
+ });
+
+ m_scene.EventManager.TriggerOnMakeRootAgent(this);
+ }
+
+ ///
+ /// This turns a root agent into a child agent
+ /// when an agent departs this region for a neighbor, this gets called.
+ ///
+ /// It doesn't get called for a teleport. Reason being, an agent that
+ /// teleports out may not end up anywhere near this region
+ ///
+ public void MakeChildAgent()
+ {
+ // It looks like m_animator is set to null somewhere, and MakeChild
+ // is called after that. Probably in aborted teleports.
+ if (m_animator == null)
+ m_animator = new ScenePresenceAnimator(this);
+ else
+ Animator.ResetAnimations();
+
+// m_log.DebugFormat(
+// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
+// Name, UUID, m_scene.RegionInfo.RegionName);
+
+ // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
+ // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
+ //Velocity = new Vector3(0, 0, 0);
+
+ m_isChildAgent = true;
+ m_scene.SwapRootAgentCount(true);
+ RemoveFromPhysicalScene();
+
+ // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into
+
+ m_scene.EventManager.TriggerOnMakeChildAgent(this);
+ }
+
+ ///
+ /// Removes physics plugin scene representation of this agent if it exists.
+ ///
+ private void RemoveFromPhysicalScene()
+ {
+ if (PhysicsActor != null)
+ {
+ m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
+ m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
+ m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
+ m_physicsActor.UnSubscribeEvents();
+ m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
+ PhysicsActor = null;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void Teleport(Vector3 pos)
+ {
+ bool isFlying = false;
+
+ if (m_physicsActor != null)
+ isFlying = m_physicsActor.Flying;
+
+ RemoveFromPhysicalScene();
+ Velocity = Vector3.Zero;
+ AbsolutePosition = pos;
+ AddToPhysicalScene(isFlying);
+ if (m_appearance != null)
+ {
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+ }
+
+ SendTerseUpdateToAllClients();
+
+ }
+
+ public void TeleportWithMomentum(Vector3 pos)
+ {
+ bool isFlying = false;
+ if (m_physicsActor != null)
+ isFlying = m_physicsActor.Flying;
+
+ RemoveFromPhysicalScene();
+ AbsolutePosition = pos;
+ AddToPhysicalScene(isFlying);
+ if (m_appearance != null)
+ {
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+ }
+
+ SendTerseUpdateToAllClients();
+ }
+
+ ///
+ ///
+ ///
+ public void StopMovement()
+ {
+ }
+
+ public void StopFlying()
+ {
+ ControllingClient.StopFlying(this);
+ }
+
+ public void AddNeighbourRegion(ulong regionHandle, string cap)
+ {
+ lock (m_knownChildRegions)
+ {
+ if (!m_knownChildRegions.ContainsKey(regionHandle))
+ {
+ uint x, y;
+ Utils.LongToUInts(regionHandle, out x, out y);
+ m_knownChildRegions.Add(regionHandle, cap);
+ }
+ }
+ }
+
+ public void RemoveNeighbourRegion(ulong regionHandle)
+ {
+ lock (m_knownChildRegions)
+ {
+ if (m_knownChildRegions.ContainsKey(regionHandle))
+ {
+ m_knownChildRegions.Remove(regionHandle);
+ //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
+ }
+ }
+ }
+
+ public void DropOldNeighbours(List oldRegions)
+ {
+ foreach (ulong handle in oldRegions)
+ {
+ RemoveNeighbourRegion(handle);
+ Scene.CapsModule.DropChildSeed(UUID, handle);
+ }
+ }
+
+ public List GetKnownRegionList()
+ {
+ return new List(m_knownChildRegions.Keys);
+ }
+
+ #endregion
+
+ #region Event Handlers
+
+ ///
+ /// Sets avatar height in the phyiscs plugin
+ ///
+ internal void SetHeight(float height)
+ {
+ m_avHeight = height;
+ if (PhysicsActor != null && !IsChildAgent)
+ {
+ Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight);
+ PhysicsActor.Size = SetSize;
+ }
+ }
+
+ ///
+ /// Complete Avatar's movement into the region.
+ /// This is called upon a very important packet sent from the client,
+ /// so it's client-controlled. Never call this method directly.
+ ///
+ public void CompleteMovement(IClientAPI client)
+ {
+ //m_log.Debug("[SCENE PRESENCE]: CompleteMovement");
+
+ Vector3 look = Velocity;
+ if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
+ {
+ look = new Vector3(0.99f, 0.042f, 0);
+ }
+
+ // Prevent teleporting to an underground location
+ // (may crash client otherwise)
+ //
+ Vector3 pos = AbsolutePosition;
+ float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
+ if (pos.Z < ground + 1.5f)
+ {
+ pos.Z = ground + 1.5f;
+ AbsolutePosition = pos;
+ }
+ m_isChildAgent = false;
+ bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
+ MakeRootAgent(AbsolutePosition, m_flying);
+
+ if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
+ {
+ m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI);
+ Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
+ m_callbackURI = null;
+ }
+
+ //m_log.DebugFormat("Completed movement");
+
+ m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
+ SendInitialData();
+
+ // Create child agents in neighbouring regions
+ if (!m_isChildAgent)
+ {
+ IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
+ if (m_agentTransfer != null)
+ m_agentTransfer.EnableChildAgents(this);
+ else
+ m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active");
+
+ IFriendsModule friendsModule = m_scene.RequestModuleInterface();
+ if (friendsModule != null)
+ friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
+ }
+
+ }
+
+ ///
+ /// Callback for the Camera view block check. Gets called with the results of the camera view block test
+ /// hitYN is true when there's something in the way.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
+ {
+ const float POSITION_TOLERANCE = 0.02f;
+ const float VELOCITY_TOLERANCE = 0.02f;
+ const float ROTATION_TOLERANCE = 0.02f;
+
+ if (m_followCamAuto)
+ {
+ if (hitYN)
+ {
+ CameraConstraintActive = true;
+ //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance);
+
+ Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint);
+ ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint)));
+ }
+ else
+ {
+ if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
+ !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
+ !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
+ {
+ if (CameraConstraintActive)
+ {
+ ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f));
+ CameraConstraintActive = false;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// This is the event handler for client movement. If a client is moving, this event is triggering.
+ ///
+ public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
+ {
+ //if (m_isChildAgent)
+ //{
+ // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
+ // return;
+ //}
+
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ ++m_movementUpdateCount;
+ if (m_movementUpdateCount < 1)
+ m_movementUpdateCount = 1;
+
+ #region Sanity Checking
+
+ // This is irritating. Really.
+ if (!AbsolutePosition.IsFinite())
+ {
+ RemoveFromPhysicalScene();
+ m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
+
+ m_pos = m_LastFinitePos;
+
+ if (!m_pos.IsFinite())
+ {
+ m_pos.X = 127f;
+ m_pos.Y = 127f;
+ m_pos.Z = 127f;
+ m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
+ }
+
+ AddToPhysicalScene(false);
+ }
+ else
+ {
+ m_LastFinitePos = m_pos;
+ }
+
+ #endregion Sanity Checking
+
+ #region Inputs
+
+ AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
+ Quaternion bodyRotation = agentData.BodyRotation;
+
+ // Camera location in world. We'll need to raytrace
+ // from this location from time to time.
+ m_CameraCenter = agentData.CameraCenter;
+ if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance)
+ {
+ ReprioritizeUpdates();
+ m_lastCameraCenter = m_CameraCenter;
+ }
+
+ // Use these three vectors to figure out what the agent is looking at
+ // Convert it to a Matrix and/or Quaternion
+ m_CameraAtAxis = agentData.CameraAtAxis;
+ m_CameraLeftAxis = agentData.CameraLeftAxis;
+ m_CameraUpAxis = agentData.CameraUpAxis;
+
+ // The Agent's Draw distance setting
+ m_DrawDistance = agentData.Far;
+
+ // Check if Client has camera in 'follow cam' or 'build' mode.
+ Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation);
+
+ m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f)
+ && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
+
+ m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
+ m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
+
+ #endregion Inputs
+
+ if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
+ {
+ StandUp();
+ }
+
+ //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
+ // Raycast from the avatar's head to the camera to see if there's anything blocking the view
+ if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
+ {
+ if (m_followCamAuto)
+ {
+ Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
+ m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
+ }
+ }
+ lock (scriptedcontrols)
+ {
+ if (scriptedcontrols.Count > 0)
+ {
+ SendControlToScripts((uint)flags);
+ flags = RemoveIgnoredControls(flags, IgnoredControls);
+ }
+ }
+
+ if (m_autopilotMoving)
+ CheckAtSitTarget();
+
+ if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
+ {
+ m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
+ Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
+
+ // TODO: This doesn't prevent the user from walking yet.
+ // Setting parent ID would fix this, if we knew what value
+ // to use. Or we could add a m_isSitting variable.
+ //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
+ SitGround = true;
+ }
+
+ // In the future, these values might need to go global.
+ // Here's where you get them.
+ m_AgentControlFlags = flags;
+ m_headrotation = agentData.HeadRotation;
+ m_state = agentData.State;
+
+ PhysicsActor actor = PhysicsActor;
+ if (actor == null)
+ {
+ return;
+ }
+
+ bool update_movementflag = false;
+
+ if (m_allowMovement && !SitGround)
+ {
+ if (agentData.UseClientAgentPosition)
+ {
+ m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
+ m_moveToPositionTarget = agentData.ClientAgentPosition;
+ }
+
+ int i = 0;
+
+ bool update_rotation = false;
+ bool DCFlagKeyPressed = false;
+ Vector3 agent_control_v3 = Vector3.Zero;
+ Quaternion q = bodyRotation;
+
+ bool oldflying = PhysicsActor.Flying;
+
+ if (m_forceFly)
+ actor.Flying = true;
+ else if (m_flyDisabled)
+ actor.Flying = false;
+ else
+ actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
+
+ if (actor.Flying != oldflying)
+ update_movementflag = true;
+
+ if (q != m_bodyRot)
+ {
+ m_bodyRot = q;
+ update_rotation = true;
+ }
+
+ //guilty until proven innocent..
+ bool Nudging = true;
+ //Basically, if there is at least one non-nudge control then we don't need
+ //to worry about stopping the avatar
+
+ if (m_parentID == 0)
+ {
+ bool bAllowUpdateMoveToPosition = false;
+ bool bResetMoveToPosition = false;
+
+ Vector3[] dirVectors;
+
+ // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
+ // this prevents 'jumping' in inappropriate situations.
+ if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying))
+ dirVectors = GetWalkDirectionVectors();
+ else
+ dirVectors = Dir_Vectors;
+
+ bool[] isNudge = GetDirectionIsNudge();
+
+
+
+
+
+ foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
+ {
+ if (((uint)flags & (uint)DCF) != 0)
+ {
+ bResetMoveToPosition = true;
+ DCFlagKeyPressed = true;
+ try
+ {
+ agent_control_v3 += dirVectors[i];
+ if (isNudge[i] == false)
+ {
+ Nudging = false;
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ // Why did I get this?
+ }
+
+ if ((m_movementflag & (uint)DCF) == 0)
+ {
+ m_movementflag += (byte)(uint)DCF;
+ update_movementflag = true;
+ }
+ }
+ else
+ {
+ if ((m_movementflag & (uint)DCF) != 0)
+ {
+ m_movementflag -= (byte)(uint)DCF;
+ update_movementflag = true;
+ }
+ else
+ {
+ bAllowUpdateMoveToPosition = true;
+ }
+ }
+ i++;
+ }
+ //Paupaw:Do Proper PID for Autopilot here
+ if (bResetMoveToPosition)
+ {
+ m_moveToPositionTarget = Vector3.Zero;
+ m_moveToPositionInProgress = false;
+ update_movementflag = true;
+ bAllowUpdateMoveToPosition = false;
+ }
+
+ if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
+ {
+ //Check the error term of the current position in relation to the target position
+ if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
+ {
+ // we are close enough to the target
+ m_moveToPositionTarget = Vector3.Zero;
+ m_moveToPositionInProgress = false;
+ update_movementflag = true;
+ }
+ else
+ {
+ try
+ {
+ // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
+ // This movement vector gets added to the velocity through AddNewMovement().
+ // Theoretically we might need a more complex PID approach here if other
+ // unknown forces are acting on the avatar and we need to adaptively respond
+ // to such forces, but the following simple approach seems to works fine.
+ Vector3 LocalVectorToTarget3D =
+ (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
+ * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
+ // Ignore z component of vector
+ Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
+ LocalVectorToTarget2D.Normalize();
+
+ //We're not nudging
+ Nudging = false;
+ agent_control_v3 += LocalVectorToTarget2D;
+
+ // update avatar movement flags. the avatar coordinate system is as follows:
+ //
+ // +X (forward)
+ //
+ // ^
+ // |
+ // |
+ // |
+ // |
+ // (left) +Y <--------o--------> -Y
+ // avatar
+ // |
+ // |
+ // |
+ // |
+ // v
+ // -X
+ //
+
+ // based on the above avatar coordinate system, classify the movement into
+ // one of left/right/back/forward.
+ if (LocalVectorToTarget2D.Y > 0)//MoveLeft
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
+ //AgentControlFlags
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
+ update_movementflag = true;
+ }
+ else if (LocalVectorToTarget2D.Y < 0) //MoveRight
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
+ update_movementflag = true;
+ }
+ if (LocalVectorToTarget2D.X < 0) //MoveBack
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
+ update_movementflag = true;
+ }
+ else if (LocalVectorToTarget2D.X > 0) //Move Forward
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
+ update_movementflag = true;
+ }
+ }
+ catch (Exception e)
+ {
+ //Avoid system crash, can be slower but...
+ m_log.DebugFormat("Crash! {0}", e.ToString());
+ }
+ }
+ }
+ }
+
+ // Cause the avatar to stop flying if it's colliding
+ // with something with the down arrow pressed.
+
+ // Only do this if we're flying
+ if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
+ {
+ // Landing detection code
+
+ // Are the landing controls requirements filled?
+ bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
+ ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
+
+ // Are the collision requirements fulfilled?
+ bool colliding = (m_physicsActor.IsColliding == true);
+
+ if (m_physicsActor.Flying && colliding && controlland)
+ {
+ // nesting this check because LengthSquared() is expensive and we don't
+ // want to do it every step when flying.
+ if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
+ StopFlying();
+ }
+ }
+
+ if (update_movementflag || (update_rotation && DCFlagKeyPressed))
+ {
+ // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
+ // m_log.DebugFormat(
+ // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
+
+ AddNewMovement(agent_control_v3, q, Nudging);
+
+
+ }
+ }
+
+ if (update_movementflag && !SitGround)
+ Animator.UpdateMovementAnimations();
+
+ m_scene.EventManager.TriggerOnClientMovement(this);
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client)
+ {
+ m_autopilotMoving = true;
+ m_autoPilotTarget = Pos;
+ m_sitAtAutoTarget = false;
+ PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
+ //proxy.PCode = (byte)PCode.ParticleSystem;
+ proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
+ proxyObjectGroup.AttachToScene(m_scene);
+
+ // Commented out this code since it could never have executed, but might still be informative.
+// if (proxyObjectGroup != null)
+// {
+ proxyObjectGroup.SendGroupFullUpdate();
+ remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
+ m_scene.DeleteSceneObject(proxyObjectGroup, false);
+// }
+// else
+// {
+// m_autopilotMoving = false;
+// m_autoPilotTarget = Vector3.Zero;
+// ControllingClient.SendAlertMessage("Autopilot cancelled");
+// }
+ }
+
+ public void DoMoveToPosition(Object sender, string method, List args)
+ {
+ try
+ {
+ float locx = 0f;
+ float locy = 0f;
+ float locz = 0f;
+ uint regionX = 0;
+ uint regionY = 0;
+ try
+ {
+ Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
+ locx = Convert.ToSingle(args[0]) - (float)regionX;
+ locy = Convert.ToSingle(args[1]) - (float)regionY;
+ locz = Convert.ToSingle(args[2]);
+ }
+ catch (InvalidCastException)
+ {
+ m_log.Error("[CLIENT]: Invalid autopilot request");
+ return;
+ }
+ m_moveToPositionInProgress = true;
+ m_moveToPositionTarget = new Vector3(locx, locy, locz);
+ }
+ catch (Exception ex)
+ {
+ //Why did I get this error?
+ m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex);
+ }
+ }
+
+ private void CheckAtSitTarget()
+ {
+ //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString());
+ if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5)
+ {
+ if (m_sitAtAutoTarget)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ AbsolutePosition = part.AbsolutePosition;
+ Velocity = Vector3.Zero;
+ SendFullUpdateToAllClients();
+
+ HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
+ }
+ //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
+ m_requestedSitTargetUUID = UUID.Zero;
+ }
+ /*
+ else
+ {
+ //ControllingClient.SendAlertMessage("Autopilot cancelled");
+ //SendTerseUpdateToAllClients();
+ //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
+ //proxy.PCode = (byte)PCode.ParticleSystem;
+ ////uint nextUUID = m_scene.NextLocalId;
+
+ //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy);
+ //if (proxyObjectGroup != null)
+ //{
+ //proxyObjectGroup.SendGroupFullUpdate();
+ //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
+ //m_scene.DeleteSceneObject(proxyObjectGroup);
+ //}
+ }
+ */
+ m_autoPilotTarget = Vector3.Zero;
+ m_autopilotMoving = false;
+ }
+ }
+ ///
+ /// Perform the logic necessary to stand the avatar up. This method also executes
+ /// the stand animation.
+ ///
+ public void StandUp()
+ {
+ SitGround = false;
+
+ if (m_parentID != 0)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
+ if (part != null)
+ {
+ part.TaskInventory.LockItemsForRead(true);
+ TaskInventoryDictionary taskIDict = part.TaskInventory;
+ if (taskIDict != null)
+ {
+ foreach (UUID taskID in taskIDict.Keys)
+ {
+ UnRegisterControlEventsToScript(LocalId, taskID);
+ taskIDict[taskID].PermsMask &= ~(
+ 2048 | //PERMISSION_CONTROL_CAMERA
+ 4); // PERMISSION_TAKE_CONTROLS
+ }
+ }
+ part.TaskInventory.LockItemsForRead(false);
+ // Reset sit target.
+ if (part.GetAvatarOnSitTarget() == UUID)
+ part.SetAvatarOnSitTarget(UUID.Zero);
+ m_parentPosition = part.GetWorldPosition();
+ ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
+ }
+ // part.GetWorldRotation() is the rotation of the object being sat on
+ // Rotation is the sittiing Av's rotation
+
+ Quaternion partRot;
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partRot = part.ParentGroup.RootPart.RotationOffset;
+// }
+// else
+// { // single or child prim
+
+// }
+ if (part == null) //CW: Part may be gone. llDie() for example.
+ {
+ partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ partRot = part.GetWorldRotation();
+ }
+
+ Quaternion partIRot = Quaternion.Inverse(partRot);
+
+ Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
+ Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
+
+
+ if (m_physicsActor == null)
+ {
+ AddToPhysicalScene(false);
+ }
+ //CW: If the part isn't null then we can set the current position
+ if (part != null)
+ {
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
+ AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
+ part.IsOccupied = false;
+ part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
+ }
+ else
+ {
+ //CW: Since the part doesn't exist, a coarse standup position isn't an issue
+ AbsolutePosition = m_lastWorldPosition;
+ }
+
+ m_parentPosition = Vector3.Zero;
+ m_parentID = 0;
+ m_linkedPrim = UUID.Zero;
+ m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ SendFullUpdateToAllClients();
+ m_requestedSitTargetID = 0;
+
+ if ((m_physicsActor != null) && (m_avHeight > 0))
+ {
+ SetHeight(m_avHeight);
+ }
+ }
+ Animator.TrySetMovementAnimation("STAND");
+ }
+
+ private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
+ {
+ SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID);
+ if (targetPart == null)
+ return null;
+
+ // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used.
+ // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
+
+ // Get our own copy of the part array, and sort into the order we want to test
+ SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts();
+ Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
+ {
+ // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
+ int linkNum1 = p1==targetPart ? -1 : p1.LinkNum;
+ int linkNum2 = p2==targetPart ? -1 : p2.LinkNum;
+ return linkNum1 - linkNum2;
+ }
+ );
+
+ //look for prims with explicit sit targets that are available
+ foreach (SceneObjectPart part in partArray)
+ {
+ // Is a sit target available?
+ Vector3 avSitOffSet = part.SitTargetPosition;
+ Quaternion avSitOrientation = part.SitTargetOrientation;
+ UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
+ bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
+ bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
+ if (SitTargetisSet && !SitTargetOccupied)
+ {
+ //switch the target to this prim
+ return part;
+ }
+ }
+
+ // no explicit sit target found - use original target
+ return targetPart;
+ }
+
+ private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
+ {
+ bool autopilot = true;
+ Vector3 autopilotTarget = new Vector3();
+ Quaternion sitOrientation = Quaternion.Identity;
+ Vector3 pos = new Vector3();
+ Vector3 cameraEyeOffset = Vector3.Zero;
+ Vector3 cameraAtOffset = Vector3.Zero;
+ bool forceMouselook = false;
+
+ //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
+ SceneObjectPart part = FindNextAvailableSitTarget(targetID);
+ if (part == null) return;
+
+ // TODO: determine position to sit at based on scene geometry; don't trust offset from client
+ // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
+
+ // part is the prim to sit on
+ // offset is the world-ref vector distance from that prim center to the click-spot
+ // UUID is the UUID of the Avatar doing the clicking
+
+ m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
+
+ // Is a sit target available?
+ Vector3 avSitOffSet = part.SitTargetPosition;
+ Quaternion avSitOrientation = part.SitTargetOrientation;
+
+ bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
+ // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ Quaternion partRot;
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partRot = part.ParentGroup.RootPart.RotationOffset;
+// }
+// else
+// { // single or child prim
+ partRot = part.GetWorldRotation();
+// }
+ Quaternion partIRot = Quaternion.Inverse(partRot);
+//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
+ // Sit analysis rewritten by KF 091125
+ if (SitTargetisSet) // scipted sit
+ {
+ if (!part.IsOccupied)
+ {
+//Console.WriteLine("Scripted, unoccupied");
+ part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
+ offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
+
+ Quaternion nrot = avSitOrientation;
+ if (!part.IsRoot)
+ {
+ nrot = part.RotationOffset * avSitOrientation;
+ }
+ sitOrientation = nrot; // Change rotatione to the scripted one
+ OffsetRotation = nrot;
+ autopilot = false; // Jump direct to scripted llSitPos()
+ }
+ else
+ {
+//Console.WriteLine("Scripted, occupied");
+ return;
+ }
+ }
+ else // Not Scripted
+ {
+ if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
+ {
+ // large prim & offset, ignore if other Avs sitting
+// offset.Z -= 0.05f;
+ m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
+ autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
+
+//Console.WriteLine(" offset ={0}", offset);
+//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
+//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
+
+ }
+ else // small offset
+ {
+//Console.WriteLine("Small offset");
+ if (!part.IsOccupied)
+ {
+ m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
+ autopilotTarget = part.AbsolutePosition;
+//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
+ }
+ else return; // occupied small
+ } // end large/small
+ } // end Scripted/not
+ cameraAtOffset = part.GetCameraAtOffset();
+ cameraEyeOffset = part.GetCameraEyeOffset();
+ forceMouselook = part.GetForceMouselook();
+ if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
+ if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
+
+ if (m_physicsActor != null)
+ {
+ // If we're not using the client autopilot, we're immediately warping the avatar to the location
+ // We can remove the physicsActor until they stand up.
+ m_sitAvatarHeight = m_physicsActor.Size.Z;
+ if (autopilot)
+ { // its not a scripted sit
+// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
+ if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
+ {
+ autopilot = false; // close enough
+ m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
+ Not using the part's position because returning the AV to the last known standing
+ position is likely to be more friendly, isn't it? */
+ RemoveFromPhysicalScene();
+ AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
+ } // else the autopilot will get us close
+ }
+ else
+ { // its a scripted sit
+ m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
+ I *am* using the part's position this time because we have no real idea how far away
+ the avatar is from the sit target. */
+ RemoveFromPhysicalScene();
+ }
+ }
+ else return; // physactor is null!
+
+ Vector3 offsetr; // = offset * partIRot;
+ // KF: In a linkset, offsetr needs to be relative to the group root! 091208
+ // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
+ // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
+ // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
+ //offsetr = offset * partIRot;
+//
+ // else
+ // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
+ // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
+ // (offset * partRot);
+ // }
+
+//Console.WriteLine(" ");
+//Console.WriteLine("link number ={0}", part.LinkNum);
+//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
+//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
+//Console.WriteLine("Click offst ={0}", offset);
+//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
+//Console.WriteLine("offsetr ={0}", offsetr);
+//Console.WriteLine("Camera At ={0}", cameraAtOffset);
+//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
+
+ //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
+ ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+
+ m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
+ // This calls HandleAgentSit twice, once from here, and the client calls
+ // HandleAgentSit itself after it gets to the location
+ // It doesn't get to the location until we've moved them there though
+ // which happens in HandleAgentSit :P
+ m_autopilotMoving = autopilot;
+ m_autoPilotTarget = autopilotTarget;
+ m_sitAtAutoTarget = autopilot;
+ m_initialSitTarget = autopilotTarget;
+ if (!autopilot)
+ HandleAgentSit(remoteClient, UUID);
+ }
+
+ public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
+ {
+ if (m_parentID != 0)
+ {
+ StandUp();
+ }
+ m_nextSitAnimation = "SIT";
+
+ //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
+ SceneObjectPart part = FindNextAvailableSitTarget(targetID);
+
+ if (part != null)
+ {
+ if (!String.IsNullOrEmpty(part.SitAnimation))
+ {
+ m_nextSitAnimation = part.SitAnimation;
+ }
+ m_requestedSitTargetID = part.LocalId;
+ //m_requestedSitOffset = offset;
+ m_requestedSitTargetUUID = targetID;
+
+ m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
+
+ if (m_scene.PhysicsScene.SupportsRayCast())
+ {
+ //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback());
+ //SitRayCastAvatarPosition(part);
+ //return;
+ }
+ }
+ else
+ {
+
+ m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
+ }
+
+
+
+ SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
+ }
+ /*
+ public void SitRayCastAvatarPosition(SceneObjectPart part)
+ {
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = AbsolutePosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse);
+ }
+
+ public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ }
+ else
+ {
+ SitRayCastAvatarPositionCameraZ(part);
+ }
+ }
+ else
+ {
+ SitRayCastAvatarPositionCameraZ(part);
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part)
+ {
+ // Next, try to raycast from the camera Z position
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse);
+ }
+
+ public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ }
+ else
+ {
+ SitRayCastCameraPosition(part);
+ }
+ }
+ else
+ {
+ SitRayCastCameraPosition(part);
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ public void SitRayCastCameraPosition(SceneObjectPart part)
+ {
+ // Next, try to raycast from the camera position
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = CameraPosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse);
+ }
+
+ public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ }
+ else
+ {
+ SitRayHorizontal(part);
+ }
+ }
+ else
+ {
+ SitRayHorizontal(part);
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ public void SitRayHorizontal(SceneObjectPart part)
+ {
+ // Next, try to raycast from the avatar position to fwd
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = CameraPosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse);
+ }
+
+ public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ // Next, try to raycast from the camera position
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = CameraPosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition);
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position not accessable.");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position not accessable.");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal)
+ {
+ int i = 0;
+ //throw new NotImplementedException();
+ //m_requestedSitTargetUUID = UUID.Zero;
+ //m_requestedSitTargetID = 0;
+ //m_requestedSitOffset = Vector3.Zero;
+
+ SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity);
+ }
+ */
+ public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation)
+ {
+ if (m_parentID != 0)
+ {
+ StandUp();
+ }
+ if (!String.IsNullOrEmpty(sitAnimation))
+ {
+ m_nextSitAnimation = sitAnimation;
+ }
+ else
+ {
+ m_nextSitAnimation = "SIT";
+ }
+
+ //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
+ SceneObjectPart part = FindNextAvailableSitTarget(targetID);
+ if (part != null)
+ {
+ m_requestedSitTargetID = part.LocalId;
+ //m_requestedSitOffset = offset;
+ m_requestedSitTargetUUID = targetID;
+
+ m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
+
+ if (m_scene.PhysicsScene.SupportsRayCast())
+ {
+ //SitRayCastAvatarPosition(part);
+ //return;
+ }
+ }
+ else
+ {
+ m_log.Warn("Sit requested on unknown object: " + targetID);
+ }
+
+ SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
+ }
+
+ public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
+ {
+ if (!String.IsNullOrEmpty(m_nextSitAnimation))
+ {
+ HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
+ }
+ else
+ {
+ HandleAgentSit(remoteClient, agentID, "SIT");
+ }
+ }
+
+ public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
+
+ if (m_sitAtAutoTarget || !m_autopilotMoving)
+ {
+ if (part != null)
+ {
+//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
+ if (part.GetAvatarOnSitTarget() == UUID)
+ {
+//Console.WriteLine("Scripted Sit");
+ // Scripted sit
+ Vector3 sitTargetPos = part.SitTargetPosition;
+ Quaternion sitTargetOrient = part.SitTargetOrientation;
+ m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
+ m_pos += SIT_TARGET_ADJUSTMENT;
+ if (!part.IsRoot)
+ {
+ m_pos *= part.RotationOffset;
+ }
+ m_bodyRot = sitTargetOrient;
+ m_parentPosition = part.AbsolutePosition;
+ part.IsOccupied = true;
+ part.ParentGroup.AddAvatar(agentID);
+Console.WriteLine("Scripted Sit ofset {0}", m_pos);
+ }
+ else
+ {
+ // if m_avUnscriptedSitPos is zero then Av sits above center
+ // Else Av sits at m_avUnscriptedSitPos
+
+ // Non-scripted sit by Kitto Flora 21Nov09
+ // Calculate angle of line from prim to Av
+ Quaternion partIRot;
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+// }
+// else
+// { // single or child prim
+ partIRot = Quaternion.Inverse(part.GetWorldRotation());
+// }
+ Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
+ float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
+ float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
+ if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
+ if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
+ float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
+ // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
+ // Av sits at world euler <0,0, z>, translated by part rotation
+ m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
+
+ m_parentPosition = part.AbsolutePosition;
+ part.IsOccupied = true;
+ part.ParentGroup.AddAvatar(agentID);
+ m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
+ (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
+ (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
+ m_avUnscriptedSitPos; // adds click offset, if any
+ //Set up raytrace to find top surface of prim
+ Vector3 size = part.Scale;
+ float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
+ Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
+ Vector3 down = new Vector3(0f, 0f, -1f);
+//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
+ m_scene.PhysicsScene.RaycastWorld(
+ start, // Vector3 position,
+ down, // Vector3 direction,
+ mag, // float length,
+ SitAltitudeCallback); // retMethod
+ } // end scripted/not
+ }
+ else // no Av
+ {
+ return;
+ }
+ }
+
+ //We want our offsets to reference the root prim, not the child we may have sat on
+ if (!part.IsRoot)
+ {
+ m_parentID = part.ParentGroup.RootPart.LocalId;
+ m_pos += part.OffsetPosition;
+ }
+ else
+ {
+ m_parentID = m_requestedSitTargetID;
+ }
+
+ m_linkedPrim = part.UUID;
+
+ Velocity = Vector3.Zero;
+ RemoveFromPhysicalScene();
+ Animator.TrySetMovementAnimation(sitAnimation);
+ SendFullUpdateToAllClients();
+ SendTerseUpdateToAllClients();
+ }
+
+ public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
+ {
+ // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
+ // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
+ if(hitYN)
+ {
+ // m_pos = Av offset from prim center to make look like on center
+ // m_parentPosition = Actual center pos of prim
+ // collisionPoint = spot on prim where we want to sit
+ // collisionPoint.Z = global sit surface height
+ SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
+ Quaternion partIRot;
+// if (part.LinkNum == 1)
+/// { // Root prim of linkset
+// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+// }
+// else
+// { // single or child prim
+ partIRot = Quaternion.Inverse(part.GetWorldRotation());
+// }
+ if (m_initialSitTarget != null)
+ {
+ float offZ = collisionPoint.Z - m_initialSitTarget.Z;
+ Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
+ //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
+ m_pos += offset;
+ // ControllingClient.SendClearFollowCamProperties(part.UUID);
+ }
+
+ }
+ } // End SitAltitudeCallback KF.
+
+ ///
+ /// Event handler for the 'Always run' setting on the client
+ /// Tells the physics plugin to increase speed of movement.
+ ///
+ public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun)
+ {
+ m_setAlwaysRun = pSetAlwaysRun;
+ if (PhysicsActor != null)
+ {
+ PhysicsActor.SetAlwaysRun = pSetAlwaysRun;
+ }
+ }
+
+ public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
+ {
+ Animator.AddAnimation(animID, UUID.Zero);
+ }
+
+ public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
+ {
+ Animator.RemoveAnimation(animID);
+ }
+
+ ///
+ /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
+ ///
+ /// The vector in which to move. This is relative to the rotation argument
+ /// The direction in which this avatar should now face.
+ public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
+ {
+ if (m_isChildAgent)
+ {
+ // WHAT???
+ m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!");
+
+ // we have to reset the user's child agent connections.
+ // Likely, here they've lost the eventqueue for other regions so border
+ // crossings will fail at this point unless we reset them.
+
+ List regions = new List(KnownChildRegionHandles);
+ regions.Remove(m_scene.RegionInfo.RegionHandle);
+
+ MakeRootAgent(new Vector3(127f, 127f, 127f), true);
+
+ // Async command
+ if (m_scene.SceneGridService != null)
+ {
+ m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions);
+
+ // Give the above command some time to try and close the connections.
+ // this is really an emergency.. so sleep, or we'll get all discombobulated.
+ System.Threading.Thread.Sleep(500);
+ }
+
+ if (m_scene.SceneGridService != null)
+ {
+ IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
+ if (m_agentTransfer != null)
+ m_agentTransfer.EnableChildAgents(this);
+ }
+
+ return;
+ }
+
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ Rotation = rotation;
+ Vector3 direc = vec * rotation;
+ direc.Normalize();
+ PhysicsActor actor = m_physicsActor;
+ if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
+
+ direc *= 0.03f * 128f * m_speedModifier;
+
+ if (actor != null)
+ {
+ if (actor.Flying)
+ {
+ direc *= 4.0f;
+ //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
+ //bool colliding = (m_physicsActor.IsColliding==true);
+ //if (controlland)
+ // m_log.Info("[AGENT]: landCommand");
+ //if (colliding)
+ // m_log.Info("[AGENT]: colliding");
+ //if (m_physicsActor.Flying && colliding && controlland)
+ //{
+ // StopFlying();
+ // m_log.Info("[AGENT]: Stop FLying");
+ //}
+ }
+ else if (!actor.Flying && actor.IsColliding)
+ {
+ if (direc.Z > 2.0f)
+ {
+ if(m_animator.m_animTickJump == -1)
+ {
+ direc.Z *= 3.0f; // jump
+ }
+ else
+ {
+ direc.Z *= 0.1f; // prejump
+ }
+ /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
+ Animator.TrySetMovementAnimation("PREJUMP");
+ Animator.TrySetMovementAnimation("JUMP");
+ */
+ }
+ }
+ }
+
+ // TODO: Add the force instead of only setting it to support multiple forces per frame?
+ m_forceToApply = direc;
+ m_isNudging = Nudging;
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ #endregion
+
+ #region Overridden Methods
+
+ public override void Update()
+ {
+ const float ROTATION_TOLERANCE = 0.01f;
+ const float VELOCITY_TOLERANCE = 0.001f;
+ const float POSITION_TOLERANCE = 0.05f;
+ //const int TIME_MS_TOLERANCE = 3000;
+
+
+
+ if (m_isChildAgent == false)
+ {
+// PhysicsActor actor = m_physicsActor;
+
+ // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
+ // grab the latest PhysicsActor velocity, whereas m_velocity is often
+ // storing a requested force instead of an actual traveling velocity
+
+ // Throw away duplicate or insignificant updates
+ if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
+ !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
+ !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
+ //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
+ {
+ SendTerseUpdateToAllClients();
+
+ // Update the "last" values
+ m_lastPosition = m_pos;
+ m_lastRotation = m_bodyRot;
+ m_lastVelocity = Velocity;
+ //m_lastTerseSent = Environment.TickCount;
+ }
+
+ // followed suggestion from mic bowman. reversed the two lines below.
+ if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something
+ CheckForBorderCrossing();
+ CheckForSignificantMovement(); // sends update to the modules.
+ }
+
+ //Sending prim updates AFTER the avatar terse updates are sent
+ SendPrimUpdates();
+ }
+
+ #endregion
+
+ #region Update Client(s)
+
+ ///
+ /// Sends a location update to the client connected to this scenePresence
+ ///
+ ///
+ public void SendTerseUpdateToClient(IClientAPI remoteClient)
+ {
+ // If the client is inactive, it's getting its updates from another
+ // server.
+ if (remoteClient.IsActive)
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ PhysicsActor actor = m_physicsActor;
+ Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero;
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
+
+ remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ m_scene.StatsReporter.AddAgentUpdates(1);
+ }
+ }
+
+ ///
+ /// Send a location/velocity/accelleration update to all agents in scene
+ ///
+ public void SendTerseUpdateToAllClients()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ m_scene.ForEachClient(SendTerseUpdateToClient);
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ public void SendCoarseLocations(List coarseLocations, List avatarUUIDs)
+ {
+ SendCourseLocationsMethod d = m_sendCourseLocationsMethod;
+ if (d != null)
+ {
+ d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
+ }
+ }
+
+ public void SetSendCourseLocationMethod(SendCourseLocationsMethod d)
+ {
+ if (d != null)
+ m_sendCourseLocationsMethod = d;
+ }
+
+ public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs)
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+ m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ ///
+ /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar)
+ ///
+ ///
+ public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar)
+ {
+ // 2 stage check is needed.
+ if (remoteAvatar == null)
+ return;
+ IClientAPI cl=remoteAvatar.ControllingClient;
+ if (cl == null)
+ return;
+ if (m_appearance.Texture == null)
+ return;
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
+ m_scene.StatsReporter.AddAgentUpdates(1);
+ }
+
+ ///
+ /// Tell *ALL* agents about this agent
+ ///
+ public void SendInitialFullUpdateToAllClients()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+ int avUpdates = 0;
+ m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
+ {
+ ++avUpdates;
+ // only send if this is the root (children are only "listening posts" in a foreign region)
+ if (!IsChildAgent)
+ {
+ SendFullUpdateToOtherClient(avatar);
+ }
+
+ if (avatar.LocalId != LocalId)
+ {
+ if (!avatar.IsChildAgent)
+ {
+ avatar.SendFullUpdateToOtherClient(this);
+ avatar.SendAppearanceToOtherAgent(this);
+ avatar.Animator.SendAnimPackToClient(ControllingClient);
+ }
+ }
+ });
+
+ m_scene.StatsReporter.AddAgentUpdates(avUpdates);
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+
+ //Animator.SendAnimPack();
+ }
+
+ public void SendFullUpdateToAllClients()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ // only send update from root agents to other clients; children are only "listening posts"
+ int count = 0;
+ m_scene.ForEachScenePresence(delegate(ScenePresence sp)
+ {
+ if (sp.IsChildAgent)
+ return;
+ SendFullUpdateToOtherClient(sp);
+ ++count;
+ });
+ m_scene.StatsReporter.AddAgentUpdates(count);
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+
+ Animator.SendAnimPack();
+ }
+
+ ///
+ /// Do everything required once a client completes its movement into a region
+ ///
+ public void SendInitialData()
+ {
+ // Moved this into CompleteMovement to ensure that m_appearance is initialized before
+ // the inventory arrives
+ // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ m_controllingClient.SendAvatarDataImmediate(this);
+
+ SendInitialFullUpdateToAllClients();
+ SendAppearanceToAllOtherAgents();
+ }
+
+ ///
+ /// Tell the client for this scene presence what items it should be wearing now
+ ///
+ public void SendWearables()
+ {
+ m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name);
+
+ ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
+ }
+
+ ///
+ ///
+ ///
+ public void SendAppearanceToAllOtherAgents()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
+ {
+ if (scenePresence.UUID != UUID)
+ {
+ SendAppearanceToOtherAgent(scenePresence);
+ }
+ });
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ ///
+ /// Send appearance data to an agent that isn't this one.
+ ///
+ ///
+ public void SendAppearanceToOtherAgent(ScenePresence avatar)
+ {
+ avatar.ControllingClient.SendAppearance(
+ m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
+ }
+
+ ///
+ /// Set appearance data (textureentry and slider settings) received from the client
+ ///
+ ///
+ ///
+ public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
+ {
+ if (m_physicsActor != null)
+ {
+ if (!IsChildAgent)
+ {
+ // This may seem like it's redundant, remove the avatar from the physics scene
+ // just to add it back again, but it saves us from having to update
+ // 3 variables 10 times a second.
+ bool flyingTemp = m_physicsActor.Flying;
+ RemoveFromPhysicalScene();
+ //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
+
+ //PhysicsActor = null;
+
+ AddToPhysicalScene(flyingTemp);
+ }
+ }
+
+ #region Bake Cache Check
+
+ if (textureEntry != null)
+ {
+ for (int i = 0; i < BAKE_INDICES.Length; i++)
+ {
+ int j = BAKE_INDICES[i];
+ Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
+
+ if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
+ {
+ if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
+ {
+ m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name);
+ this.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
+ }
+ }
+ }
+
+ }
+
+
+ #endregion Bake Cache Check
+
+ m_appearance.SetAppearance(textureEntry, visualParams);
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+
+ // This is not needed, because only the transient data changed
+ //AvatarData adata = new AvatarData(m_appearance);
+ //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
+
+ SendAppearanceToAllOtherAgents();
+ if (!m_startAnimationSet)
+ {
+ Animator.UpdateMovementAnimations();
+ m_startAnimationSet = true;
+ }
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ m_controllingClient.SendAvatarDataImmediate(this);
+ }
+
+ public void SetWearable(int wearableId, AvatarWearable wearable)
+ {
+ m_appearance.SetWearable(wearableId, wearable);
+ AvatarData adata = new AvatarData(m_appearance);
+ m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
+ m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
+ }
+
+ // Because appearance setting is in a module, we actually need
+ // to give it access to our appearance directly, otherwise we
+ // get a synchronization issue.
+ public AvatarAppearance Appearance
+ {
+ get { return m_appearance; }
+ set { m_appearance = value; }
+ }
+
+ #endregion
+
+ #region Significant Movement Method
+
+ ///
+ /// This checks for a significant movement and sends a courselocationchange update
+ ///
+ protected void CheckForSignificantMovement()
+ {
+ // Movement updates for agents in neighboring regions are sent directly to clients.
+ // This value only affects how often agent positions are sent to neighbor regions
+ // for things such as distance-based update prioritization
+ const float SIGNIFICANT_MOVEMENT = 2.0f;
+
+ if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT)
+ {
+ posLastSignificantMove = AbsolutePosition;
+ m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient);
+ }
+
+ // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
+ if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance ||
+ Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
+ {
+ m_lastChildAgentUpdatePosition = AbsolutePosition;
+ m_lastChildAgentUpdateCamPosition = CameraPosition;
+
+ ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
+ cadu.ActiveGroupID = UUID.Zero.Guid;
+ cadu.AgentID = UUID.Guid;
+ cadu.alwaysrun = m_setAlwaysRun;
+ cadu.AVHeight = m_avHeight;
+ Vector3 tempCameraCenter = m_CameraCenter;
+ cadu.cameraPosition = tempCameraCenter;
+ cadu.drawdistance = m_DrawDistance;
+ cadu.GroupAccess = 0;
+ cadu.Position = AbsolutePosition;
+ cadu.regionHandle = m_rootRegionHandle;
+ float multiplier = 1;
+ int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
+ if (innacurateNeighbors != 0)
+ {
+ multiplier = 1f / (float)innacurateNeighbors;
+ }
+ if (multiplier <= 0f)
+ {
+ multiplier = 0.25f;
+ }
+
+ //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
+ cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
+ cadu.Velocity = Velocity;
+
+ AgentPosition agentpos = new AgentPosition();
+ agentpos.CopyFrom(cadu);
+
+ m_scene.SendOutChildAgentUpdates(agentpos, this);
+ }
+ }
+
+ #endregion
+
+ #region Border Crossing Methods
+
+ ///
+ /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion
+ ///
+ protected void CheckForBorderCrossing()
+ {
+ if (IsChildAgent)
+ return;
+
+ Vector3 pos2 = AbsolutePosition;
+ Vector3 vel = Velocity;
+ int neighbor = 0;
+ int[] fix = new int[2];
+
+ float timeStep = 0.1f;
+ pos2.X = pos2.X + (vel.X*timeStep);
+ pos2.Y = pos2.Y + (vel.Y*timeStep);
+ pos2.Z = pos2.Z + (vel.Z*timeStep);
+
+ if (!IsInTransit)
+ {
+ // Checks if where it's headed exists a region
+
+ bool needsTransit = false;
+ if (m_scene.TestBorderCross(pos2, Cardinals.W))
+ {
+ if (m_scene.TestBorderCross(pos2, Cardinals.S))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.SW, ref fix);
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.N))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.NW, ref fix);
+ }
+ else
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.W, ref fix);
+ }
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.E))
+ {
+ if (m_scene.TestBorderCross(pos2, Cardinals.S))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.SE, ref fix);
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.N))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.NE, ref fix);
+ }
+ else
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.E, ref fix);
+ }
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.S))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.S, ref fix);
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.N))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.N, ref fix);
+ }
+
+
+ // Makes sure avatar does not end up outside region
+ if (neighbor <= 0)
+ {
+ if (!needsTransit)
+ {
+ if (m_requestedSitTargetUUID == UUID.Zero)
+ {
+ Vector3 pos = AbsolutePosition;
+ if (AbsolutePosition.X < 0)
+ pos.X += Velocity.X;
+ else if (AbsolutePosition.X > Constants.RegionSize)
+ pos.X -= Velocity.X;
+ if (AbsolutePosition.Y < 0)
+ pos.Y += Velocity.Y;
+ else if (AbsolutePosition.Y > Constants.RegionSize)
+ pos.Y -= Velocity.Y;
+ AbsolutePosition = pos;
+ }
+ }
+ }
+ else if (neighbor > 0)
+ CrossToNewRegion();
+ }
+ else
+ {
+ RemoveFromPhysicalScene();
+ // This constant has been inferred from experimentation
+ // I'm not sure what this value should be, so I tried a few values.
+ timeStep = 0.04f;
+ pos2 = AbsolutePosition;
+ pos2.X = pos2.X + (vel.X * timeStep);
+ pos2.Y = pos2.Y + (vel.Y * timeStep);
+ pos2.Z = pos2.Z + (vel.Z * timeStep);
+ m_pos = pos2;
+ }
+ }
+
+ protected int HaveNeighbor(Cardinals car, ref int[] fix)
+ {
+ uint neighbourx = m_regionInfo.RegionLocX;
+ uint neighboury = m_regionInfo.RegionLocY;
+
+ int dir = (int)car;
+
+ if (dir > 1 && dir < 5) //Heading East
+ neighbourx++;
+ else if (dir > 5) // Heading West
+ neighbourx--;
+
+ if (dir < 3 || dir == 8) // Heading North
+ neighboury++;
+ else if (dir > 3 && dir < 7) // Heading Sout
+ neighboury--;
+
+ int x = (int)(neighbourx * Constants.RegionSize);
+ int y = (int)(neighboury * Constants.RegionSize);
+ GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y);
+
+ if (neighbourRegion == null)
+ {
+ fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx);
+ fix[1] = (int)(m_regionInfo.RegionLocY - neighboury);
+ return dir * (-1);
+ }
+ else
+ return dir;
+ }
+
+ ///
+ /// Moves the agent outside the region bounds
+ /// Tells neighbor region that we're crossing to it
+ /// If the neighbor accepts, remove the agent's viewable avatar from this scene
+ /// set them to a child agent.
+ ///
+ protected void CrossToNewRegion()
+ {
+ InTransit();
+ try
+ {
+ m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying);
+ }
+ catch
+ {
+ m_scene.CrossAgentToNewRegion(this, false);
+ }
+ }
+
+ public void InTransit()
+ {
+ m_inTransit = true;
+
+ if ((m_physicsActor != null) && m_physicsActor.Flying)
+ m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY;
+ else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
+ m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY;
+ }
+
+ public void NotInTransit()
+ {
+ m_inTransit = false;
+ }
+
+ public void RestoreInCurrentScene()
+ {
+ AddToPhysicalScene(false); // not exactly false
+ }
+
+ public void Reset()
+ {
+ // Put the child agent back at the center
+ AbsolutePosition
+ = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
+ Animator.ResetAnimations();
+ }
+
+ ///
+ /// Computes which child agents to close when the scene presence moves to another region.
+ /// Removes those regions from m_knownRegions.
+ ///
+ /// The new region's x on the map
+ /// The new region's y on the map
+ ///
+ public void CloseChildAgents(uint newRegionX, uint newRegionY)
+ {
+ List byebyeRegions = new List();
+ m_log.DebugFormat(
+ "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
+ m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName);
+ //DumpKnownRegions();
+
+ lock (m_knownChildRegions)
+ {
+ foreach (ulong handle in m_knownChildRegions.Keys)
+ {
+ // Don't close the agent on this region yet
+ if (handle != Scene.RegionInfo.RegionHandle)
+ {
+ uint x, y;
+ Utils.LongToUInts(handle, out x, out y);
+ x = x / Constants.RegionSize;
+ y = y / Constants.RegionSize;
+
+ //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
+ //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
+ if (Util.IsOutsideView(x, newRegionX, y, newRegionY))
+ {
+ byebyeRegions.Add(handle);
+ }
+ }
+ }
+ }
+
+ if (byebyeRegions.Count > 0)
+ {
+ m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
+ m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions);
+ }
+
+ foreach (ulong handle in byebyeRegions)
+ {
+ RemoveNeighbourRegion(handle);
+ }
+ }
+
+ #endregion
+
+ ///
+ /// This allows the Sim owner the abiility to kick users from their sim currently.
+ /// It tells the client that the agent has permission to do so.
+ ///
+ public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
+ {
+ if (godStatus)
+ {
+ // For now, assign god level 200 to anyone
+ // who is granted god powers, but has no god level set.
+ //
+ UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
+ if (account != null)
+ {
+ if (account.UserLevel > 0)
+ m_godLevel = account.UserLevel;
+ else
+ m_godLevel = 200;
+ }
+ }
+ else
+ {
+ m_godLevel = 0;
+ }
+
+ ControllingClient.SendAdminResponse(token, (uint)m_godLevel);
+ }
+
+ #region Child Agent Updates
+
+ public void ChildAgentDataUpdate(AgentData cAgentData)
+ {
+ //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
+ if (!IsChildAgent)
+ return;
+
+ CopyFrom(cAgentData);
+ }
+
+ ///
+ /// This updates important decision making data about a child agent
+ /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
+ ///
+ public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
+ {
+ if (!IsChildAgent)
+ return;
+
+ //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
+ int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
+ int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
+
+ Vector3 offset = new Vector3(shiftx, shifty, 0f);
+
+ m_DrawDistance = cAgentData.Far;
+ if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!!
+ m_pos = cAgentData.Position + offset;
+
+ if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance)
+ {
+ posLastSignificantMove = AbsolutePosition;
+ ReprioritizeUpdates();
+ }
+
+ m_CameraCenter = cAgentData.Center + offset;
+
+ m_avHeight = cAgentData.Size.Z;
+ //SetHeight(cAgentData.AVHeight);
+
+ if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
+ ControllingClient.SetChildAgentThrottle(cAgentData.Throttles);
+
+ // Sends out the objects in the user's draw distance if m_sendTasksToChild is true.
+ if (m_scene.m_seeIntoRegionFromNeighbor)
+ m_sceneViewer.Reset();
+
+ //cAgentData.AVHeight;
+ m_rootRegionHandle = cAgentData.RegionHandle;
+ //m_velocity = cAgentData.Velocity;
+ }
+
+ public void CopyTo(AgentData cAgent)
+ {
+ cAgent.AgentID = UUID;
+ cAgent.RegionID = Scene.RegionInfo.RegionID;
+
+ cAgent.Position = AbsolutePosition;
+ cAgent.Velocity = m_velocity;
+ cAgent.Center = m_CameraCenter;
+ // Don't copy the size; it is inferred from apearance parameters
+ //cAgent.Size = new Vector3(0, 0, m_avHeight);
+ cAgent.AtAxis = m_CameraAtAxis;
+ cAgent.LeftAxis = m_CameraLeftAxis;
+ cAgent.UpAxis = m_CameraUpAxis;
+
+ cAgent.Far = m_DrawDistance;
+
+ // Throttles
+ float multiplier = 1;
+ int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
+ if (innacurateNeighbors != 0)
+ {
+ multiplier = 1f / innacurateNeighbors;
+ }
+ if (multiplier <= 0f)
+ {
+ multiplier = 0.25f;
+ }
+ //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
+ cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
+
+ cAgent.HeadRotation = m_headrotation;
+ cAgent.BodyRotation = m_bodyRot;
+ cAgent.ControlFlags = (uint)m_AgentControlFlags;
+
+ if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
+ cAgent.GodLevel = (byte)m_godLevel;
+ else
+ cAgent.GodLevel = (byte) 0;
+
+ cAgent.AlwaysRun = m_setAlwaysRun;
+
+ try
+ {
+ // We might not pass the Wearables in all cases...
+ // They're only needed so that persistent changes to the appearance
+ // are preserved in the new region where the user is moving to.
+ // But in Hypergrid we might not let this happen.
+ int i = 0;
+ UUID[] wears = new UUID[m_appearance.Wearables.Length * 2];
+ foreach (AvatarWearable aw in m_appearance.Wearables)
+ {
+ if (aw != null)
+ {
+ wears[i++] = aw.ItemID;
+ wears[i++] = aw.AssetID;
+ }
+ else
+ {
+ wears[i++] = UUID.Zero;
+ wears[i++] = UUID.Zero;
+ }
+ }
+ cAgent.Wearables = wears;
+
+ cAgent.VisualParams = m_appearance.VisualParams;
+
+ if (m_appearance.Texture != null)
+ cAgent.AgentTextures = m_appearance.Texture.GetBytes();
+ }
+ catch (Exception e)
+ {
+ m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message);
+ }
+
+ //Attachments
+ List attPoints = m_appearance.GetAttachedPoints();
+ if (attPoints != null)
+ {
+ //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count);
+ int i = 0;
+ AttachmentData[] attachs = new AttachmentData[attPoints.Count];
+ foreach (int point in attPoints)
+ {
+ attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point));
+ }
+ cAgent.Attachments = attachs;
+ }
+
+ lock (scriptedcontrols)
+ {
+ ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
+ int i = 0;
+
+ foreach (ScriptControllers c in scriptedcontrols.Values)
+ {
+ controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
+ }
+ cAgent.Controllers = controls;
+ }
+
+ // Animations
+ try
+ {
+ cAgent.Anims = Animator.Animations.ToArray();
+ }
+ catch { }
+
+ // cAgent.GroupID = ??
+ // Groups???
+
+ }
+
+ public void CopyFrom(AgentData cAgent)
+ {
+ m_originRegionID = cAgent.RegionID;
+
+ m_callbackURI = cAgent.CallbackURI;
+
+ m_pos = cAgent.Position;
+
+ m_velocity = cAgent.Velocity;
+ m_CameraCenter = cAgent.Center;
+ //m_avHeight = cAgent.Size.Z;
+ m_CameraAtAxis = cAgent.AtAxis;
+ m_CameraLeftAxis = cAgent.LeftAxis;
+ m_CameraUpAxis = cAgent.UpAxis;
+
+ m_DrawDistance = cAgent.Far;
+
+ if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
+ ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
+
+ m_headrotation = cAgent.HeadRotation;
+ m_bodyRot = cAgent.BodyRotation;
+ m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags;
+
+ if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
+ m_godLevel = cAgent.GodLevel;
+ m_setAlwaysRun = cAgent.AlwaysRun;
+
+ uint i = 0;
+ try
+ {
+ if (cAgent.Wearables == null)
+ cAgent.Wearables = new UUID[0];
+ AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2];
+ for (uint n = 0; n < cAgent.Wearables.Length; n += 2)
+ {
+ UUID itemId = cAgent.Wearables[n];
+ UUID assetId = cAgent.Wearables[n + 1];
+ wears[i++] = new AvatarWearable(itemId, assetId);
+ }
+ m_appearance.Wearables = wears;
+ Primitive.TextureEntry te;
+ if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1)
+ te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length);
+ else
+ te = AvatarAppearance.GetDefaultTexture();
+ if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT))
+ cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams();
+ m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone());
+ }
+ catch (Exception e)
+ {
+ m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message);
+ }
+
+ // Attachments
+ try
+ {
+ if (cAgent.Attachments != null)
+ {
+ m_appearance.ClearAttachments();
+ foreach (AttachmentData att in cAgent.Attachments)
+ {
+ m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID);
+ }
+ }
+ }
+ catch { }
+
+ try
+ {
+ lock (scriptedcontrols)
+ {
+ if (cAgent.Controllers != null)
+ {
+ scriptedcontrols.Clear();
+
+ foreach (ControllerData c in cAgent.Controllers)
+ {
+ ScriptControllers sc = new ScriptControllers();
+ sc.itemID = c.ItemID;
+ sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
+ sc.eventControls = (ScriptControlled)c.EventControls;
+
+ scriptedcontrols[sc.itemID] = sc;
+ }
+ }
+ }
+ }
+ catch { }
+ // Animations
+ try
+ {
+ Animator.ResetAnimations();
+ Animator.Animations.FromArray(cAgent.Anims);
+ }
+ catch { }
+
+ //cAgent.GroupID = ??
+ //Groups???
+ }
+
+ public bool CopyAgent(out IAgentData agent)
+ {
+ agent = new CompleteAgentData();
+ CopyTo((AgentData)agent);
+ return true;
+ }
+
+ #endregion Child Agent Updates
+
+ ///
+ /// Handles part of the PID controller function for moving an avatar.
+ ///
+ public override void UpdateMovement()
+ {
+ if (m_forceToApply.HasValue)
+ {
+
+ Vector3 force = m_forceToApply.Value;
+ m_updateflag = true;
+ Velocity = force;
+
+ m_forceToApply = null;
+ }
+ else
+ {
+ if (m_isNudging)
+ {
+ Vector3 force = Vector3.Zero;
+
+ m_updateflag = true;
+ Velocity = force;
+ m_isNudging = false;
+ m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
+ }
+ }
+ }
+
+ public override void SetText(string text, Vector3 color, double alpha)
+ {
+ throw new Exception("Can't set Text on avatar.");
+ }
+
+ ///
+ /// Adds a physical representation of the avatar to the Physics plugin
+ ///
+ public void AddToPhysicalScene(bool isFlying)
+ {
+ PhysicsScene scene = m_scene.PhysicsScene;
+
+ Vector3 pVec = AbsolutePosition;
+
+ // Old bug where the height was in centimeters instead of meters
+ if (m_avHeight == 127.0f)
+ {
+ m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f),
+ isFlying);
+ }
+ else
+ {
+ m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
+ new Vector3(0f, 0f, m_avHeight), isFlying);
+ }
+ scene.AddPhysicsActorTaint(m_physicsActor);
+ //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
+ m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
+ m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
+ m_physicsActor.SubscribeEvents(500);
+ m_physicsActor.LocalID = LocalId;
+ }
+
+ private void OutOfBoundsCall(Vector3 pos)
+ {
+ //bool flying = m_physicsActor.Flying;
+ //RemoveFromPhysicalScene();
+
+ //AddToPhysicalScene(flying);
+ if (ControllingClient != null)
+ ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
+ }
+
+ // Event called by the physics plugin to tell the avatar about a collision.
+ private void PhysicsCollisionUpdate(EventArgs e)
+ {
+ if (e == null)
+ return;
+
+ // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
+ // as of this comment the interval is set in AddToPhysicalScene
+ if (Animator!=null)
+ {
+ if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
+ { // else its will lock out other animation changes, like ground sit.
+ Animator.UpdateMovementAnimations();
+ m_updateCount--;
+ }
+ }
+
+ CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
+ Dictionary coldata = collisionData.m_objCollisionList;
+
+ CollisionPlane = Vector4.UnitW;
+
+ if (m_lastColCount != coldata.Count)
+ {
+ m_updateCount = UPDATE_COUNT;
+ m_lastColCount = coldata.Count;
+ }
+
+ if (coldata.Count != 0 && Animator != null)
+ {
+ switch (Animator.CurrentMovementAnimation)
+ {
+ case "STAND":
+ case "WALK":
+ case "RUN":
+ case "CROUCH":
+ case "CROUCHWALK":
+ {
+ ContactPoint lowest;
+ lowest.SurfaceNormal = Vector3.Zero;
+ lowest.Position = Vector3.Zero;
+ lowest.Position.Z = Single.NaN;
+
+ foreach (ContactPoint contact in coldata.Values)
+ {
+ if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z)
+ {
+ lowest = contact;
+ }
+ }
+
+ CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
+ }
+ break;
+ }
+ }
+
+ List thisHitColliders = new List();
+ List endedColliders = new List();
+ List startedColliders = new List();
+
+ foreach (uint localid in coldata.Keys)
+ {
+ thisHitColliders.Add(localid);
+ if (!m_lastColliders.Contains(localid))
+ {
+ startedColliders.Add(localid);
+ }
+ //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
+ }
+
+ // calculate things that ended colliding
+ foreach (uint localID in m_lastColliders)
+ {
+ if (!thisHitColliders.Contains(localID))
+ {
+ endedColliders.Add(localID);
+ }
+ }
+ //add the items that started colliding this time to the last colliders list.
+ foreach (uint localID in startedColliders)
+ {
+ m_lastColliders.Add(localID);
+ }
+ // remove things that ended colliding from the last colliders list
+ foreach (uint localID in endedColliders)
+ {
+ m_lastColliders.Remove(localID);
+ }
+
+ // do event notification
+ if (startedColliders.Count > 0)
+ {
+ ColliderArgs StartCollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in startedColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ StartCollidingMessage.Colliders = colliding;
+
+ foreach (SceneObjectGroup att in Attachments)
+ Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
+ }
+ }
+
+ if (endedColliders.Count > 0)
+ {
+ ColliderArgs EndCollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in endedColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ EndCollidingMessage.Colliders = colliding;
+
+ foreach (SceneObjectGroup att in Attachments)
+ Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
+ }
+ }
+
+ if (thisHitColliders.Count > 0)
+ {
+ ColliderArgs CollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in thisHitColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ CollidingMessage.Colliders = colliding;
+
+ lock (m_attachments)
+ {
+ foreach (SceneObjectGroup att in m_attachments)
+ Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
+ }
+ }
+ }
+
+ if (m_invulnerable)
+ return;
+
+ float starthealth = Health;
+ uint killerObj = 0;
+ foreach (uint localid in coldata.Keys)
+ {
+ SceneObjectPart part = Scene.GetSceneObjectPart(localid);
+
+ if (part != null && part.ParentGroup.Damage != -1.0f)
+ Health -= part.ParentGroup.Damage;
+ else
+ {
+ if (coldata[localid].PenetrationDepth >= 0.10f)
+ Health -= coldata[localid].PenetrationDepth * 5.0f;
+ }
+
+ if (Health <= 0.0f)
+ {
+ if (localid != 0)
+ killerObj = localid;
+ }
+ //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
+ }
+ //Health = 100;
+ if (!m_invulnerable)
+ {
+ if (starthealth != Health)
+ {
+ ControllingClient.SendHealth(Health);
+ }
+ if (m_health <= 0)
+ m_scene.EventManager.TriggerAvatarKill(killerObj, this);
+ }
+ }
+
+ public void setHealthWithUpdate(float health)
+ {
+ Health = health;
+ ControllingClient.SendHealth(Health);
+ }
+
+ public void Close()
+ {
+ lock (m_attachments)
+ {
+ // Delete attachments from scene
+ // Don't try to save, as this thread won't live long
+ // enough to complete the save. This would cause no copy
+ // attachments to poof!
+ //
+ foreach (SceneObjectGroup grp in m_attachments)
+ {
+ m_scene.DeleteSceneObject(grp, false);
+ }
+ m_attachments.Clear();
+ }
+
+ lock (m_knownChildRegions)
+ {
+ m_knownChildRegions.Clear();
+ }
+
+ lock (m_reprioritization_timer)
+ {
+ m_reprioritization_timer.Enabled = false;
+ m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
+ }
+
+ // I don't get it but mono crashes when you try to dispose of this timer,
+ // unsetting the elapsed callback should be enough to allow for cleanup however.
+ // m_reprioritizationTimer.Dispose();
+
+ m_sceneViewer.Close();
+
+ RemoveFromPhysicalScene();
+ m_animator.Close();
+ m_animator = null;
+ }
+
+ public void AddAttachment(SceneObjectGroup gobj)
+ {
+ lock (m_attachments)
+ {
+ m_attachments.Add(gobj);
+ }
+ }
+
+ public bool HasAttachments()
+ {
+ return m_attachments.Count > 0;
+ }
+
+ public bool HasScriptedAttachments()
+ {
+ lock (m_attachments)
+ {
+ foreach (SceneObjectGroup gobj in m_attachments)
+ {
+ if (gobj != null)
+ {
+ if (gobj.RootPart.Inventory.ContainsScripts())
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void RemoveAttachment(SceneObjectGroup gobj)
+ {
+ lock (m_attachments)
+ {
+ if (m_attachments.Contains(gobj))
+ {
+ m_attachments.Remove(gobj);
+ }
+ }
+ }
+
+ public bool ValidateAttachments()
+ {
+ lock (m_attachments)
+ {
+ // Validate
+ foreach (SceneObjectGroup gobj in m_attachments)
+ {
+ if (gobj == null)
+ return false;
+
+ if (gobj.IsDeleted)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Send a script event to this scene presence's attachments
+ ///
+ /// The name of the event
+ /// The arguments for the event
+ public void SendScriptEventToAttachments(string eventName, Object[] args)
+ {
+ if (m_scriptEngines != null)
+ {
+ lock (m_attachments)
+ {
+ foreach (SceneObjectGroup grp in m_attachments)
+ {
+ // 16384 is CHANGED_ANIMATION
+ //
+ // Send this to all attachment root prims
+ //
+ foreach (IScriptModule m in m_scriptEngines)
+ {
+ if (m == null) // No script engine loaded
+ continue;
+
+ m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
+ }
+ }
+ }
+ }
+ }
+
+
+ public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
+ {
+ m_controllingClient = client;
+ m_regionInfo = region;
+ m_scene = scene;
+
+ RegisterToEvents();
+ if (m_controllingClient != null)
+ {
+ m_controllingClient.ProcessPendingPackets();
+ }
+ /*
+ AbsolutePosition = client.StartPos;
+
+ Animations = new AvatarAnimations();
+ Animations.LoadAnims();
+
+ m_animations = new List();
+ m_animations.Add(Animations.AnimsUUID["STAND"]);
+ m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
+
+ SetDirectionVectors();
+ */
+ }
+
+ internal void PushForce(Vector3 impulse)
+ {
+ if (PhysicsActor != null)
+ {
+ PhysicsActor.AddForce(impulse,true);
+ }
+ }
+
+ public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
+ {
+ ScriptControllers obj = new ScriptControllers();
+ obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
+ obj.eventControls = ScriptControlled.CONTROL_ZERO;
+
+ obj.itemID = Script_item_UUID;
+ if (pass_on == 0 && accept == 0)
+ {
+ IgnoredControls |= (ScriptControlled)controls;
+ obj.ignoreControls = (ScriptControlled)controls;
+ }
+
+ if (pass_on == 0 && accept == 1)
+ {
+ IgnoredControls |= (ScriptControlled)controls;
+ obj.ignoreControls = (ScriptControlled)controls;
+ obj.eventControls = (ScriptControlled)controls;
+ }
+ if (pass_on == 1 && accept == 1)
+ {
+ IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ obj.eventControls = (ScriptControlled)controls;
+ obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
+ }
+
+ lock (scriptedcontrols)
+ {
+ if (pass_on == 1 && accept == 0)
+ {
+ IgnoredControls &= ~(ScriptControlled)controls;
+ if (scriptedcontrols.ContainsKey(Script_item_UUID))
+ scriptedcontrols.Remove(Script_item_UUID);
+ }
+ else
+ {
+ scriptedcontrols[Script_item_UUID] = obj;
+ }
+ }
+ ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
+ }
+
+ public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
+ {
+ IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ lock (scriptedcontrols)
+ {
+ scriptedcontrols.Clear();
+ }
+ ControllingClient.SendTakeControls(int.MaxValue, false, false);
+ }
+
+ public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
+ {
+ ScriptControllers takecontrols;
+
+ lock (scriptedcontrols)
+ {
+ if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols))
+ {
+ ScriptControlled sctc = takecontrols.eventControls;
+
+ ControllingClient.SendTakeControls((int)sctc, false, false);
+ ControllingClient.SendTakeControls((int)sctc, true, false);
+
+ scriptedcontrols.Remove(Script_item_UUID);
+ IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ foreach (ScriptControllers scData in scriptedcontrols.Values)
+ {
+ IgnoredControls |= scData.ignoreControls;
+ }
+ }
+ }
+ }
+
+ internal void SendControlToScripts(uint flags)
+ {
+ ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
+
+ if (MouseDown)
+ {
+ allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
+ {
+ allflags = ScriptControlled.CONTROL_ZERO;
+ MouseDown = true;
+ }
+ }
+
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
+ MouseDown = true;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_LBUTTON;
+ MouseDown = true;
+ }
+
+ // find all activated controls, whether the scripts are interested in them or not
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_FWD;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_BACK;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_UP;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_DOWN;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_LEFT;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_RIGHT;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_ROT_LEFT;
+ }
+ // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
+ if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
+ {
+ lock (scriptedcontrols)
+ {
+ foreach (KeyValuePair kvp in scriptedcontrols)
+ {
+ UUID scriptUUID = kvp.Key;
+ ScriptControllers scriptControlData = kvp.Value;
+
+ ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
+ ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
+ ScriptControlled localChange = localHeld ^ localLast; // the changed bits
+ if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
+ {
+ // only send if still pressed or just changed
+ m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange);
+ }
+ }
+ }
+ }
+
+ LastCommands = allflags;
+ }
+
+ internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored)
+ {
+ if (ignored == ScriptControlled.CONTROL_ZERO)
+ return flags;
+
+ if ((ignored & ScriptControlled.CONTROL_BACK) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
+ if ((ignored & ScriptControlled.CONTROL_FWD) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS);
+ if ((ignored & ScriptControlled.CONTROL_DOWN) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG);
+ if ((ignored & ScriptControlled.CONTROL_UP) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS);
+ if ((ignored & ScriptControlled.CONTROL_LEFT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
+ if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG);
+ if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG);
+ if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS);
+ if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN);
+ if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN);
+
+ //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
+ //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
+ //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
+ //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
+ //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
+ //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
+ //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
+
+ return flags;
+ }
+
+ ///
+ /// RezAttachments. This should only be called upon login on the first region.
+ /// Attachment rezzings on crossings and TPs are done in a different way.
+ ///
+ public void RezAttachments()
+ {
+ if (null == m_appearance)
+ {
+ m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
+ return;
+ }
+
+ XmlDocument doc = new XmlDocument();
+ string stateData = String.Empty;
+
+ IAttachmentsService attServ = m_scene.RequestModuleInterface();
+ if (attServ != null)
+ {
+ m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
+ stateData = attServ.Get(ControllingClient.AgentId.ToString());
+ if (stateData != String.Empty)
+ {
+ try
+ {
+ doc.LoadXml(stateData);
+ }
+ catch { }
+ }
+ }
+
+ Dictionary itemData = new Dictionary();
+
+ XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
+ if (nodes.Count > 0)
+ {
+ foreach (XmlNode n in nodes)
+ {
+ XmlElement elem = (XmlElement)n;
+ string itemID = elem.GetAttribute("ItemID");
+ string xml = elem.InnerXml;
+
+ itemData[new UUID(itemID)] = xml;
+ }
+ }
+
+ List attPoints = m_appearance.GetAttachedPoints();
+ foreach (int p in attPoints)
+ {
+ if (m_isDeleted)
+ return;
+
+ UUID itemID = m_appearance.GetAttachedItem(p);
+ UUID assetID = m_appearance.GetAttachedAsset(p);
+
+ // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
+ // But they're not used anyway, the item is being looked up for now, so let's proceed.
+ //if (UUID.Zero == assetID)
+ //{
+ // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID);
+ // continue;
+ //}
+
+ try
+ {
+ string xmlData;
+ XmlDocument d = new XmlDocument();
+ UUID asset;
+ if (itemData.TryGetValue(itemID, out xmlData))
+ {
+ d.LoadXml(xmlData);
+ m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
+
+ // Rez from inventory
+ asset
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
+
+ }
+ else
+ {
+ // Rez from inventory (with a null doc to let
+ // CHANGED_OWNER happen)
+ asset
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
+ }
+
+ m_log.InfoFormat(
+ "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
+ p, itemID, assetID, asset);
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString());
+ }
+ }
+ }
+
+ private void ReprioritizeUpdates()
+ {
+ if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time)
+ {
+ lock (m_reprioritization_timer)
+ {
+ if (!m_reprioritizing)
+ m_reprioritization_timer.Enabled = m_reprioritizing = true;
+ else
+ m_reprioritization_called = true;
+ }
+ }
+ }
+
+ private void Reprioritize(object sender, ElapsedEventArgs e)
+ {
+ m_controllingClient.ReprioritizeUpdates();
+
+ lock (m_reprioritization_timer)
+ {
+ m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called;
+ m_reprioritization_called = false;
+ }
+ }
+
+ private Vector3 Quat2Euler(Quaternion rot){
+ float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
+ (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
+ float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
+ float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
+ (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
+ return(new Vector3(x,y,z));
+ }
+
+
+ }
+}
--
cgit v1.1
From cabbd187e7945329c2f0700180f400b11096d33c Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 11:13:05 -0700
Subject: Fix the distance from which autopilot is negated when sitting on an
unscripted prim - and also add some more Velocity code to ensure it gets set
to zero in all cases
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 882f4a7..56e7e93 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2007,13 +2007,14 @@ namespace OpenSim.Region.Framework.Scenes
if (autopilot)
{ // its not a scripted sit
// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
- if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 2.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 2.0f) )
+ if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 10.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 10.0f) )
{
autopilot = false; // close enough
m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
Not using the part's position because returning the AV to the last known standing
position is likely to be more friendly, isn't it? */
RemoveFromPhysicalScene();
+ Velocity = Vector3.Zero;
AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
} // else the autopilot will get us close
}
@@ -2023,6 +2024,7 @@ namespace OpenSim.Region.Framework.Scenes
I *am* using the part's position this time because we have no real idea how far away
the avatar is from the sit target. */
RemoveFromPhysicalScene();
+ Velocity = Vector3.Zero;
}
}
else return; // physactor is null!
--
cgit v1.1
From acb1590cf063769802f35c99dd5fb6398172296f Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 17:32:36 -0700
Subject: Fix the unscripted sit rotation being incorrect (relative to the
prim). Note that unscripted sit offset is still really poor but this is not
something i'm prepared to spend time on fixing.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 56e7e93..5191236 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2053,9 +2053,13 @@ namespace OpenSim.Region.Framework.Scenes
//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
//NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
- ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ Quaternion roffset = Quaternion.Identity;
+ if (SitTargetisSet)
+ {
+ roffset = part.RotationOffset;
+ }
+ ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * roffset) + part.OffsetPosition), sitOrientation / part.RotationOffset, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
- m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
// This calls HandleAgentSit twice, once from here, and the client calls
// HandleAgentSit itself after it gets to the location
// It doesn't get to the location until we've moved them there though
@@ -2441,7 +2445,7 @@ Console.WriteLine("Scripted Sit ofset {0}", m_pos);
}
m_linkedPrim = part.UUID;
-
+ m_offsetRotation = m_offsetRotation / part.RotationOffset;
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
Animator.TrySetMovementAnimation(sitAnimation);
--
cgit v1.1
From b771965f287af0cb5d46e4f652e9912dfaa40682 Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 17:33:27 -0700
Subject: Get rid of some debug chatter that someone who can't spell left
behind. ;)
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 5191236..6f92a41 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2378,8 +2378,7 @@ namespace OpenSim.Region.Framework.Scenes
m_bodyRot = sitTargetOrient;
m_parentPosition = part.AbsolutePosition;
part.IsOccupied = true;
- part.ParentGroup.AddAvatar(agentID);
-Console.WriteLine("Scripted Sit ofset {0}", m_pos);
+ part.ParentGroup.AddAvatar(agentID);
}
else
{
--
cgit v1.1
From aa54e8d95eb920869da5c885fc536cfb1ffca90b Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 17:35:16 -0700
Subject: Increase sit distance to 256 meters, but leave the initial autopilot
process in the picture so sit position can still be raycast by the existing
code.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 6f92a41..cca296e 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2007,7 +2007,7 @@ namespace OpenSim.Region.Framework.Scenes
if (autopilot)
{ // its not a scripted sit
// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
- if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 10.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 10.0f) )
+ if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
{
autopilot = false; // close enough
m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
--
cgit v1.1
From f9b5f23383675abe0ae1c2ed83dd5ccce738d940 Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 22:19:26 -0700
Subject: Reverted: * Fix the unscripted sit rotation being incorrect .. will
commit a proper fix now.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 10 +++-------
1 file changed, 3 insertions(+), 7 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cca296e..87cf135 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2053,13 +2053,9 @@ namespace OpenSim.Region.Framework.Scenes
//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
//NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
- Quaternion roffset = Quaternion.Identity;
- if (SitTargetisSet)
- {
- roffset = part.RotationOffset;
- }
- ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * roffset) + part.OffsetPosition), sitOrientation / part.RotationOffset, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+ m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
// This calls HandleAgentSit twice, once from here, and the client calls
// HandleAgentSit itself after it gets to the location
// It doesn't get to the location until we've moved them there though
@@ -2444,7 +2440,7 @@ namespace OpenSim.Region.Framework.Scenes
}
m_linkedPrim = part.UUID;
- m_offsetRotation = m_offsetRotation / part.RotationOffset;
+
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
Animator.TrySetMovementAnimation(sitAnimation);
--
cgit v1.1
From a1f2be5e69ef04a8520229e161bdd0527badb844 Mon Sep 17 00:00:00 2001
From: meta7
Date: Sat, 7 Aug 2010 22:25:37 -0700
Subject: The real fix for unscripted sit positions. This one doesn't fuck
everything else up. Promise.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 87cf135..fc8e0d7 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2440,7 +2440,10 @@ namespace OpenSim.Region.Framework.Scenes
}
m_linkedPrim = part.UUID;
-
+ if (part.GetAvatarOnSitTarget() != UUID)
+ {
+ m_offsetRotation = m_offsetRotation / part.RotationOffset;
+ }
Velocity = Vector3.Zero;
RemoveFromPhysicalScene();
Animator.TrySetMovementAnimation(sitAnimation);
--
cgit v1.1
From 383ee0d647df245dcb933e71f2b4bcdfbc026a15 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Tue, 10 Aug 2010 19:48:45 +0100
Subject: Remove 4000+ DOS line endings. Grrr!
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8664 +++++++++++-----------
1 file changed, 4332 insertions(+), 4332 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index fc8e0d7..9d95324 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1,4332 +1,4332 @@
-/*
- * Copyright (c) Contributors, http://opensimulator.org/
- * See CONTRIBUTORS.TXT for a full list of copyright holders.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions are met:
- * * Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * * Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * * Neither the name of the OpenSimulator Project nor the
- * names of its contributors may be used to endorse or promote products
- * derived from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
- * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
- * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
- * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
- * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
- * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
- * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
- * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-using System;
-using System.Xml;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Timers;
-using OpenMetaverse;
-using log4net;
-using OpenSim.Framework;
-using OpenSim.Framework.Client;
-using OpenSim.Region.Framework.Interfaces;
-using OpenSim.Region.Framework.Scenes.Animation;
-using OpenSim.Region.Framework.Scenes.Types;
-using OpenSim.Region.Physics.Manager;
-using GridRegion = OpenSim.Services.Interfaces.GridRegion;
-using OpenSim.Services.Interfaces;
-
-namespace OpenSim.Region.Framework.Scenes
-{
- enum ScriptControlled : uint
- {
- CONTROL_ZERO = 0,
- CONTROL_FWD = 1,
- CONTROL_BACK = 2,
- CONTROL_LEFT = 4,
- CONTROL_RIGHT = 8,
- CONTROL_UP = 16,
- CONTROL_DOWN = 32,
- CONTROL_ROT_LEFT = 256,
- CONTROL_ROT_RIGHT = 512,
- CONTROL_LBUTTON = 268435456,
- CONTROL_ML_LBUTTON = 1073741824
- }
-
- struct ScriptControllers
- {
- public UUID itemID;
- public ScriptControlled ignoreControls;
- public ScriptControlled eventControls;
- }
-
- public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs);
-
- public class ScenePresence : EntityBase, ISceneEntity
- {
-// ~ScenePresence()
-// {
-// m_log.Debug("[ScenePresence] Destructor called");
-// }
-
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
-
- private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
-// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
- private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
- private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
-
- ///
- /// Experimentally determined "fudge factor" to make sit-target positions
- /// the same as in SecondLife. Fudge factor was tested for 36 different
- /// test cases including prims of type box, sphere, cylinder, and torus,
- /// with varying parameters for sit target location, prim size, prim
- /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
- /// issue #1716
- ///
-// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
- // Value revised by KF 091121 by comparison with SL.
- private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
-
- public UUID currentParcelUUID = UUID.Zero;
-
- private ISceneViewer m_sceneViewer;
-
- ///
- /// The animator for this avatar
- ///
- public ScenePresenceAnimator Animator
- {
- get { return m_animator; }
- }
- protected ScenePresenceAnimator m_animator;
-
- ///
- /// The scene objects attached to this avatar. Do not change this list directly - use methods such as
- /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it.
- ///
- public List Attachments
- {
- get { return m_attachments; }
- }
- protected List m_attachments = new List();
-
- private Dictionary scriptedcontrols = new Dictionary();
- private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
- private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
- private bool MouseDown = false;
- private SceneObjectGroup proxyObjectGroup;
- //private SceneObjectPart proxyObjectPart = null;
- public Vector3 lastKnownAllowedPosition;
- public bool sentMessageAboutRestrictedParcelFlyingDown;
- public Vector4 CollisionPlane = Vector4.UnitW;
-
- private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
- private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
- private Vector3 m_lastPosition;
- private Vector3 m_lastWorldPosition;
- private Quaternion m_lastRotation;
- private Vector3 m_lastVelocity;
- //private int m_lastTerseSent;
-
- private bool m_updateflag;
- private byte m_movementflag;
- private Vector3? m_forceToApply;
- private uint m_requestedSitTargetID;
- private UUID m_requestedSitTargetUUID;
- public bool SitGround = false;
-
- private SendCourseLocationsMethod m_sendCourseLocationsMethod;
-
- private bool m_startAnimationSet;
-
- //private Vector3 m_requestedSitOffset = new Vector3();
-
- private Vector3 m_LastFinitePos;
-
- private float m_sitAvatarHeight = 2.0f;
-
- private int m_godLevel;
- private int m_userLevel;
-
- private bool m_invulnerable = true;
-
- private Vector3 m_lastChildAgentUpdatePosition;
- private Vector3 m_lastChildAgentUpdateCamPosition;
-
- private int m_perfMonMS;
-
- private bool m_setAlwaysRun;
- private bool m_forceFly;
- private bool m_flyDisabled;
-
- private float m_speedModifier = 1.0f;
-
- private Quaternion m_bodyRot= Quaternion.Identity;
-
- private Quaternion m_bodyRotPrevious = Quaternion.Identity;
-
- private const int LAND_VELOCITYMAG_MAX = 12;
-
- public bool IsRestrictedToRegion;
-
- public string JID = String.Empty;
-
- private float m_health = 100f;
-
- // Default AV Height
- private float m_avHeight = 127.0f;
-
- protected RegionInfo m_regionInfo;
- protected ulong crossingFromRegion;
-
- private readonly Vector3[] Dir_Vectors = new Vector3[11];
- private bool m_isNudging = false;
-
- // Position of agent's camera in world (region cordinates)
- protected Vector3 m_CameraCenter;
- protected Vector3 m_lastCameraCenter;
-
- protected Timer m_reprioritization_timer;
- protected bool m_reprioritizing;
- protected bool m_reprioritization_called;
-
- // Use these three vectors to figure out what the agent is looking at
- // Convert it to a Matrix and/or Quaternion
- protected Vector3 m_CameraAtAxis;
- protected Vector3 m_CameraLeftAxis;
- protected Vector3 m_CameraUpAxis;
- private AgentManager.ControlFlags m_AgentControlFlags;
- private Quaternion m_headrotation = Quaternion.Identity;
- private byte m_state;
-
- //Reuse the Vector3 instead of creating a new one on the UpdateMovement method
-// private Vector3 movementvector;
-
- private bool m_autopilotMoving;
- private Vector3 m_autoPilotTarget;
- private bool m_sitAtAutoTarget;
- private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
-
- private string m_nextSitAnimation = String.Empty;
-
- //PauPaw:Proper PID Controler for autopilot************
- private bool m_moveToPositionInProgress;
- private Vector3 m_moveToPositionTarget;
- private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
-
- private bool m_followCamAuto;
-
- private int m_movementUpdateCount;
- private int m_lastColCount = -1; //KF: Look for Collision chnages
- private int m_updateCount = 0; //KF: Update Anims for a while
- private static readonly int UPDATE_COUNT = 10; // how many frames to update for
- private const int NumMovementsBetweenRayCast = 5;
- private List m_lastColliders = new List();
-
- private bool CameraConstraintActive;
- //private int m_moveToPositionStateStatus;
- //*****************************************************
-
- // Agent's Draw distance.
- protected float m_DrawDistance;
-
- protected AvatarAppearance m_appearance;
-
- // neighbouring regions we have enabled a child agent in
- // holds the seed cap for the child agent in that region
- private Dictionary m_knownChildRegions = new Dictionary();
-
- ///
- /// Implemented Control Flags
- ///
- private enum Dir_ControlFlags
- {
- DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
- DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
- DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
- DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
- DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
- DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
- DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
- DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
- DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
- DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
- DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
- }
-
- ///
- /// Position at which a significant movement was made
- ///
- private Vector3 posLastSignificantMove;
-
- // For teleports and crossings callbacks
- string m_callbackURI;
- UUID m_originRegionID;
-
- ulong m_rootRegionHandle;
-
- ///
- /// Script engines present in the scene
- ///
- private IScriptModule[] m_scriptEngines;
-
- #region Properties
-
- ///
- /// Physical scene representation of this Avatar.
- ///
- public PhysicsActor PhysicsActor
- {
- set { m_physicsActor = value; }
- get { return m_physicsActor; }
- }
-
- public byte MovementFlag
- {
- set { m_movementflag = value; }
- get { return m_movementflag; }
- }
-
- public bool Updated
- {
- set { m_updateflag = value; }
- get { return m_updateflag; }
- }
-
- public bool Invulnerable
- {
- set { m_invulnerable = value; }
- get { return m_invulnerable; }
- }
-
- public int UserLevel
- {
- get { return m_userLevel; }
- }
-
- public int GodLevel
- {
- get { return m_godLevel; }
- }
-
- public ulong RegionHandle
- {
- get { return m_rootRegionHandle; }
- }
-
- public Vector3 CameraPosition
- {
- get { return m_CameraCenter; }
- }
-
- public Quaternion CameraRotation
- {
- get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); }
- }
-
- public Vector3 CameraAtAxis
- {
- get { return m_CameraAtAxis; }
- }
-
- public Vector3 CameraLeftAxis
- {
- get { return m_CameraLeftAxis; }
- }
-
- public Vector3 CameraUpAxis
- {
- get { return m_CameraUpAxis; }
- }
-
- public Vector3 Lookat
- {
- get
- {
- Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0);
-
- if (a == Vector3.Zero)
- return a;
-
- return Util.GetNormalizedVector(a);
- }
- }
-
- private readonly string m_firstname;
-
- public string Firstname
- {
- get { return m_firstname; }
- }
-
- private readonly string m_lastname;
-
- public string Lastname
- {
- get { return m_lastname; }
- }
-
- private string m_grouptitle;
-
- public string Grouptitle
- {
- get { return m_grouptitle; }
- set { m_grouptitle = value; }
- }
-
- public float DrawDistance
- {
- get { return m_DrawDistance; }
- }
-
- protected bool m_allowMovement = true;
-
- public bool AllowMovement
- {
- get { return m_allowMovement; }
- set { m_allowMovement = value; }
- }
-
- public bool SetAlwaysRun
- {
- get
- {
- if (PhysicsActor != null)
- {
- return PhysicsActor.SetAlwaysRun;
- }
- else
- {
- return m_setAlwaysRun;
- }
- }
- set
- {
- m_setAlwaysRun = value;
- if (PhysicsActor != null)
- {
- PhysicsActor.SetAlwaysRun = value;
- }
- }
- }
-
- public byte State
- {
- get { return m_state; }
- set { m_state = value; }
- }
-
- public uint AgentControlFlags
- {
- get { return (uint)m_AgentControlFlags; }
- set { m_AgentControlFlags = (AgentManager.ControlFlags)value; }
- }
-
- ///
- /// This works out to be the ClientView object associated with this avatar, or it's client connection manager
- ///
- private IClientAPI m_controllingClient;
-
- protected PhysicsActor m_physicsActor;
-
- ///
- /// The client controlling this presence
- ///
- public IClientAPI ControllingClient
- {
- get { return m_controllingClient; }
- }
-
- public IClientCore ClientView
- {
- get { return (IClientCore) m_controllingClient; }
- }
-
- protected Vector3 m_parentPosition;
- public Vector3 ParentPosition
- {
- get { return m_parentPosition; }
- set { m_parentPosition = value; }
- }
-
- ///
- /// Position of this avatar relative to the region the avatar is in
- ///
- public override Vector3 AbsolutePosition
- {
- get
- {
- PhysicsActor actor = m_physicsActor;
-// if (actor != null)
- if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
- m_pos = actor.Position;
-
- // If we're sitting, we need to update our position
- if (m_parentID != 0)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
- if (part != null)
- m_parentPosition = part.AbsolutePosition;
- }
-
- return m_parentPosition + m_pos;
- }
- set
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- {
- try
- {
- lock (m_scene.SyncRoot)
- m_physicsActor.Position = value;
- }
- catch (Exception e)
- {
- m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
- }
- }
-
- if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
- m_pos = value;
- m_parentPosition = Vector3.Zero;
- }
- }
-
- public Vector3 OffsetPosition
- {
- get { return m_pos; }
- set { m_pos = value; }
- }
-
- ///
- /// Current velocity of the avatar.
- ///
- public override Vector3 Velocity
- {
- get
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- m_velocity = actor.Velocity;
-
- return m_velocity;
- }
- set
- {
- PhysicsActor actor = m_physicsActor;
- if (actor != null)
- {
- try
- {
- lock (m_scene.SyncRoot)
- actor.Velocity = value;
- }
- catch (Exception e)
- {
- m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message);
- }
- }
-
- m_velocity = value;
- }
- }
-
- public Quaternion OffsetRotation
- {
- get { return m_offsetRotation; }
- set { m_offsetRotation = value; }
- }
-
- public Quaternion Rotation
- {
- get {
- if (m_parentID != 0)
- {
- if (m_offsetRotation != null)
- {
- return m_offsetRotation;
- }
- else
- {
- return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
-
- }
- else
- {
- return m_bodyRot;
- }
- }
- set {
- m_bodyRot = value;
- if (m_parentID != 0)
- {
- m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- }
- }
-
- public Quaternion PreviousRotation
- {
- get { return m_bodyRotPrevious; }
- set { m_bodyRotPrevious = value; }
- }
-
- ///
- /// If this is true, agent doesn't have a representation in this scene.
- /// this is an agent 'looking into' this scene from a nearby scene(region)
- ///
- /// if False, this agent has a representation in this scene
- ///
- private bool m_isChildAgent = true;
-
- public bool IsChildAgent
- {
- get { return m_isChildAgent; }
- set { m_isChildAgent = value; }
- }
-
- private uint m_parentID;
-
-
- private UUID m_linkedPrim;
-
- public uint ParentID
- {
- get { return m_parentID; }
- set { m_parentID = value; }
- }
-
- public UUID LinkedPrim
- {
- get { return m_linkedPrim; }
- set { m_linkedPrim = value; }
- }
-
- public float Health
- {
- get { return m_health; }
- set { m_health = value; }
- }
-
- ///
- /// These are the region handles known by the avatar.
- ///
- public List KnownChildRegionHandles
- {
- get
- {
- if (m_knownChildRegions.Count == 0)
- return new List();
- else
- return new List(m_knownChildRegions.Keys);
- }
- }
-
- public Dictionary KnownRegions
- {
- get { return m_knownChildRegions; }
- set
- {
- m_knownChildRegions = value;
- }
- }
-
- public ISceneViewer SceneViewer
- {
- get { return m_sceneViewer; }
- }
-
- public void AdjustKnownSeeds()
- {
- Dictionary seeds;
-
- if (Scene.CapsModule != null)
- seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
- else
- seeds = new Dictionary();
-
- List old = new List();
- foreach (ulong handle in seeds.Keys)
- {
- uint x, y;
- Utils.LongToUInts(handle, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
- if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
- {
- old.Add(handle);
- }
- }
- DropOldNeighbours(old);
-
- if (Scene.CapsModule != null)
- Scene.CapsModule.SetChildrenSeed(UUID, seeds);
-
- KnownRegions = seeds;
- //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
- //DumpKnownRegions();
- }
-
- public void DumpKnownRegions()
- {
- m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================");
- foreach (KeyValuePair kvp in KnownRegions)
- {
- uint x, y;
- Utils.LongToUInts(kvp.Key, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
- m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
- }
- }
-
- private bool m_inTransit;
- private bool m_mouseLook;
- private bool m_leftButtonDown;
-
- public bool IsInTransit
- {
- get { return m_inTransit; }
- set { m_inTransit = value; }
- }
-
- public float SpeedModifier
- {
- get { return m_speedModifier; }
- set { m_speedModifier = value; }
- }
-
- public bool ForceFly
- {
- get { return m_forceFly; }
- set { m_forceFly = value; }
- }
-
- public bool FlyDisabled
- {
- get { return m_flyDisabled; }
- set { m_flyDisabled = value; }
- }
-
- public string Viewer
- {
- get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; }
- }
-
- #endregion
-
- #region Constructor(s)
-
- public ScenePresence()
- {
- m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
- CreateSceneViewer();
- m_animator = new ScenePresenceAnimator(this);
- }
-
- private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
- {
- m_rootRegionHandle = reginfo.RegionHandle;
- m_controllingClient = client;
- m_firstname = m_controllingClient.FirstName;
- m_lastname = m_controllingClient.LastName;
- m_name = String.Format("{0} {1}", m_firstname, m_lastname);
- m_scene = world;
- m_uuid = client.AgentId;
- m_regionInfo = reginfo;
- m_localId = m_scene.AllocateLocalId();
-
- UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
-
- if (account != null)
- m_userLevel = account.UserLevel;
-
- IGroupsModule gm = m_scene.RequestModuleInterface();
- if (gm != null)
- m_grouptitle = gm.GetGroupTitle(m_uuid);
-
- m_scriptEngines = m_scene.RequestModuleInterfaces();
-
- AbsolutePosition = posLastSignificantMove = m_CameraCenter =
- m_lastCameraCenter = m_controllingClient.StartPos;
-
- m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
- m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
- m_reprioritization_timer.AutoReset = false;
-
- AdjustKnownSeeds();
- Animator.TrySetMovementAnimation("STAND");
- // we created a new ScenePresence (a new child agent) in a fresh region.
- // Request info about all the (root) agents in this region
- // Note: This won't send data *to* other clients in that region (children don't send)
- SendInitialFullUpdateToAllClients();
- RegisterToEvents();
- if (m_controllingClient != null)
- {
- m_controllingClient.ProcessPendingPackets();
- }
- SetDirectionVectors();
- }
-
- public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
- AvatarWearable[] wearables)
- : this(client, world, reginfo)
- {
- m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
- }
-
- public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
- : this(client, world, reginfo)
- {
- m_appearance = appearance;
- }
-
- private void CreateSceneViewer()
- {
- m_sceneViewer = new SceneViewer(this);
- }
-
- public void RegisterToEvents()
- {
- m_controllingClient.OnRequestWearables += SendWearables;
- m_controllingClient.OnSetAppearance += SetAppearance;
- m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
- //m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
- m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
- m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
- m_controllingClient.OnAgentSit += HandleAgentSit;
- m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
- m_controllingClient.OnStartAnim += HandleStartAnim;
- m_controllingClient.OnStopAnim += HandleStopAnim;
- m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
- m_controllingClient.OnAutoPilotGo += DoAutoPilot;
- m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
-
- // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
- // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
- }
-
- private void SetDirectionVectors()
- {
- Dir_Vectors[0] = Vector3.UnitX; //FORWARD
- Dir_Vectors[1] = -Vector3.UnitX; //BACK
- Dir_Vectors[2] = Vector3.UnitY; //LEFT
- Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
- Dir_Vectors[4] = Vector3.UnitZ; //UP
- Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
- Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
- Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
- Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
- Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
- Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
- }
-
- private Vector3[] GetWalkDirectionVectors()
- {
- Vector3[] vector = new Vector3[11];
- vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
- vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
- vector[2] = Vector3.UnitY; //LEFT
- vector[3] = -Vector3.UnitY; //RIGHT
- vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
- vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
- vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
- vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
- vector[8] = Vector3.UnitY; //LEFT_NUDGE
- vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
- vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
- return vector;
- }
-
- private bool[] GetDirectionIsNudge()
- {
- bool[] isNudge = new bool[11];
- isNudge[0] = false; //FORWARD
- isNudge[1] = false; //BACK
- isNudge[2] = false; //LEFT
- isNudge[3] = false; //RIGHT
- isNudge[4] = false; //UP
- isNudge[5] = false; //DOWN
- isNudge[6] = true; //FORWARD_NUDGE
- isNudge[7] = true; //BACK_NUDGE
- isNudge[8] = true; //LEFT_NUDGE
- isNudge[9] = true; //RIGHT_NUDGE
- isNudge[10] = true; //DOWN_Nudge
- return isNudge;
- }
-
-
- #endregion
-
- public uint GenerateClientFlags(UUID ObjectID)
- {
- return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
- }
-
- ///
- /// Send updates to the client about prims which have been placed on the update queue. We don't
- /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
- /// timestamp has already been sent.
- ///
- public void SendPrimUpdates()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- m_sceneViewer.SendPrimUpdates();
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- #region Status Methods
-
- ///
- /// This turns a child agent, into a root agent
- /// This is called when an agent teleports into a region, or if an
- /// agent crosses into this region from a neighbor over the border
- ///
- public void MakeRootAgent(Vector3 pos, bool isFlying)
- {
- m_log.DebugFormat(
- "[SCENE]: Upgrading child to root agent for {0} in {1}",
- Name, m_scene.RegionInfo.RegionName);
-
- //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
-
- IGroupsModule gm = m_scene.RequestModuleInterface();
- if (gm != null)
- m_grouptitle = gm.GetGroupTitle(m_uuid);
-
- m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
- m_scene.SetRootAgentScene(m_uuid);
-
- // Moved this from SendInitialData to ensure that m_appearance is initialized
- // before the inventory is processed in MakeRootAgent. This fixes a race condition
- // related to the handling of attachments
- //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
- if (m_scene.TestBorderCross(pos, Cardinals.E))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
- pos.X = crossedBorder.BorderLine.Z - 1;
- }
-
- if (m_scene.TestBorderCross(pos, Cardinals.N))
- {
- Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
- pos.Y = crossedBorder.BorderLine.Z - 1;
- }
-
- //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
- //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
- //they'll bypass the landing point. But I can't think of any decent way of fixing this.
- if (KnownChildRegionHandles.Count == 0)
- {
- ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
- if (land != null)
- {
- //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
- if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
- {
- pos = land.LandData.UserLocation;
- }
- }
- }
-
- if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
- {
- Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
-
- if (pos.X < 0)
- {
- emergencyPos.X = (int)Constants.RegionSize + pos.X;
- if (!(pos.Y < 0))
- emergencyPos.Y = pos.Y;
- if (!(pos.Z < 0))
- emergencyPos.Z = pos.Z;
- }
- if (pos.Y < 0)
- {
- emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
- if (!(pos.X < 0))
- emergencyPos.X = pos.X;
- if (!(pos.Z < 0))
- emergencyPos.Z = pos.Z;
- }
- if (pos.Z < 0)
- {
- emergencyPos.Z = 128;
- if (!(pos.Y < 0))
- emergencyPos.Y = pos.Y;
- if (!(pos.X < 0))
- emergencyPos.X = pos.X;
- }
- }
-
- if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
- {
- m_log.WarnFormat(
- "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
- pos, Name, UUID);
-
- if (pos.X < 0f) pos.X = 0f;
- if (pos.Y < 0f) pos.Y = 0f;
- if (pos.Z < 0f) pos.Z = 0f;
- }
-
- float localAVHeight = 1.56f;
- if (m_avHeight != 127.0f)
- {
- localAVHeight = m_avHeight;
- }
-
- float posZLimit = 0;
-
- if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
- posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
-
- float newPosZ = posZLimit + localAVHeight / 2;
- if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
- {
- pos.Z = newPosZ;
- }
- AbsolutePosition = pos;
-
- AddToPhysicalScene(isFlying);
-
- if (m_forceFly)
- {
- m_physicsActor.Flying = true;
- }
- else if (m_flyDisabled)
- {
- m_physicsActor.Flying = false;
- }
-
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
- else
- {
- m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName);
- // emergency; this really shouldn't happen
- m_appearance = new AvatarAppearance(UUID);
- }
-
- // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
- // avatar to return to the standing position in mid-air. On login it looks like this is being sent
- // elsewhere anyway
- // Animator.SendAnimPack();
-
- m_scene.SwapRootAgentCount(false);
-
- //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
- //if (userInfo != null)
- // userInfo.FetchInventory();
- //else
- // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid);
-
- // On the next prim update, all objects will be sent
- //
- m_sceneViewer.Reset();
-
- m_isChildAgent = false;
-
- // send the animations of the other presences to me
- m_scene.ForEachScenePresence(delegate(ScenePresence presence)
- {
- if (presence != this)
- presence.Animator.SendAnimPackToClient(ControllingClient);
- });
-
- m_scene.EventManager.TriggerOnMakeRootAgent(this);
- }
-
- ///
- /// This turns a root agent into a child agent
- /// when an agent departs this region for a neighbor, this gets called.
- ///
- /// It doesn't get called for a teleport. Reason being, an agent that
- /// teleports out may not end up anywhere near this region
- ///
- public void MakeChildAgent()
- {
- // It looks like m_animator is set to null somewhere, and MakeChild
- // is called after that. Probably in aborted teleports.
- if (m_animator == null)
- m_animator = new ScenePresenceAnimator(this);
- else
- Animator.ResetAnimations();
-
-// m_log.DebugFormat(
-// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
-// Name, UUID, m_scene.RegionInfo.RegionName);
-
- // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
- // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
- //Velocity = new Vector3(0, 0, 0);
-
- m_isChildAgent = true;
- m_scene.SwapRootAgentCount(true);
- RemoveFromPhysicalScene();
-
- // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into
-
- m_scene.EventManager.TriggerOnMakeChildAgent(this);
- }
-
- ///
- /// Removes physics plugin scene representation of this agent if it exists.
- ///
- private void RemoveFromPhysicalScene()
- {
- if (PhysicsActor != null)
- {
- m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
- m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
- m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
- m_physicsActor.UnSubscribeEvents();
- m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
- PhysicsActor = null;
- }
- }
-
- ///
- ///
- ///
- ///
- public void Teleport(Vector3 pos)
- {
- bool isFlying = false;
-
- if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
- RemoveFromPhysicalScene();
- Velocity = Vector3.Zero;
- AbsolutePosition = pos;
- AddToPhysicalScene(isFlying);
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
-
- SendTerseUpdateToAllClients();
-
- }
-
- public void TeleportWithMomentum(Vector3 pos)
- {
- bool isFlying = false;
- if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
- RemoveFromPhysicalScene();
- AbsolutePosition = pos;
- AddToPhysicalScene(isFlying);
- if (m_appearance != null)
- {
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
- }
-
- SendTerseUpdateToAllClients();
- }
-
- ///
- ///
- ///
- public void StopMovement()
- {
- }
-
- public void StopFlying()
- {
- ControllingClient.StopFlying(this);
- }
-
- public void AddNeighbourRegion(ulong regionHandle, string cap)
- {
- lock (m_knownChildRegions)
- {
- if (!m_knownChildRegions.ContainsKey(regionHandle))
- {
- uint x, y;
- Utils.LongToUInts(regionHandle, out x, out y);
- m_knownChildRegions.Add(regionHandle, cap);
- }
- }
- }
-
- public void RemoveNeighbourRegion(ulong regionHandle)
- {
- lock (m_knownChildRegions)
- {
- if (m_knownChildRegions.ContainsKey(regionHandle))
- {
- m_knownChildRegions.Remove(regionHandle);
- //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
- }
- }
- }
-
- public void DropOldNeighbours(List oldRegions)
- {
- foreach (ulong handle in oldRegions)
- {
- RemoveNeighbourRegion(handle);
- Scene.CapsModule.DropChildSeed(UUID, handle);
- }
- }
-
- public List GetKnownRegionList()
- {
- return new List(m_knownChildRegions.Keys);
- }
-
- #endregion
-
- #region Event Handlers
-
- ///
- /// Sets avatar height in the phyiscs plugin
- ///
- internal void SetHeight(float height)
- {
- m_avHeight = height;
- if (PhysicsActor != null && !IsChildAgent)
- {
- Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight);
- PhysicsActor.Size = SetSize;
- }
- }
-
- ///
- /// Complete Avatar's movement into the region.
- /// This is called upon a very important packet sent from the client,
- /// so it's client-controlled. Never call this method directly.
- ///
- public void CompleteMovement(IClientAPI client)
- {
- //m_log.Debug("[SCENE PRESENCE]: CompleteMovement");
-
- Vector3 look = Velocity;
- if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
- {
- look = new Vector3(0.99f, 0.042f, 0);
- }
-
- // Prevent teleporting to an underground location
- // (may crash client otherwise)
- //
- Vector3 pos = AbsolutePosition;
- float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
- if (pos.Z < ground + 1.5f)
- {
- pos.Z = ground + 1.5f;
- AbsolutePosition = pos;
- }
- m_isChildAgent = false;
- bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
- MakeRootAgent(AbsolutePosition, m_flying);
-
- if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
- {
- m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI);
- Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
- m_callbackURI = null;
- }
-
- //m_log.DebugFormat("Completed movement");
-
- m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
- SendInitialData();
-
- // Create child agents in neighbouring regions
- if (!m_isChildAgent)
- {
- IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
- if (m_agentTransfer != null)
- m_agentTransfer.EnableChildAgents(this);
- else
- m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active");
-
- IFriendsModule friendsModule = m_scene.RequestModuleInterface();
- if (friendsModule != null)
- friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
- }
-
- }
-
- ///
- /// Callback for the Camera view block check. Gets called with the results of the camera view block test
- /// hitYN is true when there's something in the way.
- ///
- ///
- ///
- ///
- ///
- public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
- {
- const float POSITION_TOLERANCE = 0.02f;
- const float VELOCITY_TOLERANCE = 0.02f;
- const float ROTATION_TOLERANCE = 0.02f;
-
- if (m_followCamAuto)
- {
- if (hitYN)
- {
- CameraConstraintActive = true;
- //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance);
-
- Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint);
- ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint)));
- }
- else
- {
- if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
- !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
- !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
- {
- if (CameraConstraintActive)
- {
- ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f));
- CameraConstraintActive = false;
- }
- }
- }
- }
- }
-
- ///
- /// This is the event handler for client movement. If a client is moving, this event is triggering.
- ///
- public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
- {
- //if (m_isChildAgent)
- //{
- // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
- // return;
- //}
-
- m_perfMonMS = Util.EnvironmentTickCount();
-
- ++m_movementUpdateCount;
- if (m_movementUpdateCount < 1)
- m_movementUpdateCount = 1;
-
- #region Sanity Checking
-
- // This is irritating. Really.
- if (!AbsolutePosition.IsFinite())
- {
- RemoveFromPhysicalScene();
- m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
-
- m_pos = m_LastFinitePos;
-
- if (!m_pos.IsFinite())
- {
- m_pos.X = 127f;
- m_pos.Y = 127f;
- m_pos.Z = 127f;
- m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
- }
-
- AddToPhysicalScene(false);
- }
- else
- {
- m_LastFinitePos = m_pos;
- }
-
- #endregion Sanity Checking
-
- #region Inputs
-
- AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
- Quaternion bodyRotation = agentData.BodyRotation;
-
- // Camera location in world. We'll need to raytrace
- // from this location from time to time.
- m_CameraCenter = agentData.CameraCenter;
- if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance)
- {
- ReprioritizeUpdates();
- m_lastCameraCenter = m_CameraCenter;
- }
-
- // Use these three vectors to figure out what the agent is looking at
- // Convert it to a Matrix and/or Quaternion
- m_CameraAtAxis = agentData.CameraAtAxis;
- m_CameraLeftAxis = agentData.CameraLeftAxis;
- m_CameraUpAxis = agentData.CameraUpAxis;
-
- // The Agent's Draw distance setting
- m_DrawDistance = agentData.Far;
-
- // Check if Client has camera in 'follow cam' or 'build' mode.
- Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation);
-
- m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f)
- && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
-
- m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
- m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
-
- #endregion Inputs
-
- if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
- {
- StandUp();
- }
-
- //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
- // Raycast from the avatar's head to the camera to see if there's anything blocking the view
- if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
- {
- if (m_followCamAuto)
- {
- Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
- m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
- }
- }
- lock (scriptedcontrols)
- {
- if (scriptedcontrols.Count > 0)
- {
- SendControlToScripts((uint)flags);
- flags = RemoveIgnoredControls(flags, IgnoredControls);
- }
- }
-
- if (m_autopilotMoving)
- CheckAtSitTarget();
-
- if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
- {
- m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
- Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
-
- // TODO: This doesn't prevent the user from walking yet.
- // Setting parent ID would fix this, if we knew what value
- // to use. Or we could add a m_isSitting variable.
- //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
- SitGround = true;
- }
-
- // In the future, these values might need to go global.
- // Here's where you get them.
- m_AgentControlFlags = flags;
- m_headrotation = agentData.HeadRotation;
- m_state = agentData.State;
-
- PhysicsActor actor = PhysicsActor;
- if (actor == null)
- {
- return;
- }
-
- bool update_movementflag = false;
-
- if (m_allowMovement && !SitGround)
- {
- if (agentData.UseClientAgentPosition)
- {
- m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
- m_moveToPositionTarget = agentData.ClientAgentPosition;
- }
-
- int i = 0;
-
- bool update_rotation = false;
- bool DCFlagKeyPressed = false;
- Vector3 agent_control_v3 = Vector3.Zero;
- Quaternion q = bodyRotation;
-
- bool oldflying = PhysicsActor.Flying;
-
- if (m_forceFly)
- actor.Flying = true;
- else if (m_flyDisabled)
- actor.Flying = false;
- else
- actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
-
- if (actor.Flying != oldflying)
- update_movementflag = true;
-
- if (q != m_bodyRot)
- {
- m_bodyRot = q;
- update_rotation = true;
- }
-
- //guilty until proven innocent..
- bool Nudging = true;
- //Basically, if there is at least one non-nudge control then we don't need
- //to worry about stopping the avatar
-
- if (m_parentID == 0)
- {
- bool bAllowUpdateMoveToPosition = false;
- bool bResetMoveToPosition = false;
-
- Vector3[] dirVectors;
-
- // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
- // this prevents 'jumping' in inappropriate situations.
- if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying))
- dirVectors = GetWalkDirectionVectors();
- else
- dirVectors = Dir_Vectors;
-
- bool[] isNudge = GetDirectionIsNudge();
-
-
-
-
-
- foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
- {
- if (((uint)flags & (uint)DCF) != 0)
- {
- bResetMoveToPosition = true;
- DCFlagKeyPressed = true;
- try
- {
- agent_control_v3 += dirVectors[i];
- if (isNudge[i] == false)
- {
- Nudging = false;
- }
- }
- catch (IndexOutOfRangeException)
- {
- // Why did I get this?
- }
-
- if ((m_movementflag & (uint)DCF) == 0)
- {
- m_movementflag += (byte)(uint)DCF;
- update_movementflag = true;
- }
- }
- else
- {
- if ((m_movementflag & (uint)DCF) != 0)
- {
- m_movementflag -= (byte)(uint)DCF;
- update_movementflag = true;
- }
- else
- {
- bAllowUpdateMoveToPosition = true;
- }
- }
- i++;
- }
- //Paupaw:Do Proper PID for Autopilot here
- if (bResetMoveToPosition)
- {
- m_moveToPositionTarget = Vector3.Zero;
- m_moveToPositionInProgress = false;
- update_movementflag = true;
- bAllowUpdateMoveToPosition = false;
- }
-
- if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
- {
- //Check the error term of the current position in relation to the target position
- if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
- {
- // we are close enough to the target
- m_moveToPositionTarget = Vector3.Zero;
- m_moveToPositionInProgress = false;
- update_movementflag = true;
- }
- else
- {
- try
- {
- // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
- // This movement vector gets added to the velocity through AddNewMovement().
- // Theoretically we might need a more complex PID approach here if other
- // unknown forces are acting on the avatar and we need to adaptively respond
- // to such forces, but the following simple approach seems to works fine.
- Vector3 LocalVectorToTarget3D =
- (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
- * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
- // Ignore z component of vector
- Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
- LocalVectorToTarget2D.Normalize();
-
- //We're not nudging
- Nudging = false;
- agent_control_v3 += LocalVectorToTarget2D;
-
- // update avatar movement flags. the avatar coordinate system is as follows:
- //
- // +X (forward)
- //
- // ^
- // |
- // |
- // |
- // |
- // (left) +Y <--------o--------> -Y
- // avatar
- // |
- // |
- // |
- // |
- // v
- // -X
- //
-
- // based on the above avatar coordinate system, classify the movement into
- // one of left/right/back/forward.
- if (LocalVectorToTarget2D.Y > 0)//MoveLeft
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
- //AgentControlFlags
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
- update_movementflag = true;
- }
- else if (LocalVectorToTarget2D.Y < 0) //MoveRight
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
- update_movementflag = true;
- }
- if (LocalVectorToTarget2D.X < 0) //MoveBack
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
- update_movementflag = true;
- }
- else if (LocalVectorToTarget2D.X > 0) //Move Forward
- {
- m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
- AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
- update_movementflag = true;
- }
- }
- catch (Exception e)
- {
- //Avoid system crash, can be slower but...
- m_log.DebugFormat("Crash! {0}", e.ToString());
- }
- }
- }
- }
-
- // Cause the avatar to stop flying if it's colliding
- // with something with the down arrow pressed.
-
- // Only do this if we're flying
- if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
- {
- // Landing detection code
-
- // Are the landing controls requirements filled?
- bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
- ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
-
- // Are the collision requirements fulfilled?
- bool colliding = (m_physicsActor.IsColliding == true);
-
- if (m_physicsActor.Flying && colliding && controlland)
- {
- // nesting this check because LengthSquared() is expensive and we don't
- // want to do it every step when flying.
- if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
- StopFlying();
- }
- }
-
- if (update_movementflag || (update_rotation && DCFlagKeyPressed))
- {
- // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
- // m_log.DebugFormat(
- // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
-
- AddNewMovement(agent_control_v3, q, Nudging);
-
-
- }
- }
-
- if (update_movementflag && !SitGround)
- Animator.UpdateMovementAnimations();
-
- m_scene.EventManager.TriggerOnClientMovement(this);
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client)
- {
- m_autopilotMoving = true;
- m_autoPilotTarget = Pos;
- m_sitAtAutoTarget = false;
- PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
- //proxy.PCode = (byte)PCode.ParticleSystem;
- proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
- proxyObjectGroup.AttachToScene(m_scene);
-
- // Commented out this code since it could never have executed, but might still be informative.
-// if (proxyObjectGroup != null)
-// {
- proxyObjectGroup.SendGroupFullUpdate();
- remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
- m_scene.DeleteSceneObject(proxyObjectGroup, false);
-// }
-// else
-// {
-// m_autopilotMoving = false;
-// m_autoPilotTarget = Vector3.Zero;
-// ControllingClient.SendAlertMessage("Autopilot cancelled");
-// }
- }
-
- public void DoMoveToPosition(Object sender, string method, List args)
- {
- try
- {
- float locx = 0f;
- float locy = 0f;
- float locz = 0f;
- uint regionX = 0;
- uint regionY = 0;
- try
- {
- Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
- locx = Convert.ToSingle(args[0]) - (float)regionX;
- locy = Convert.ToSingle(args[1]) - (float)regionY;
- locz = Convert.ToSingle(args[2]);
- }
- catch (InvalidCastException)
- {
- m_log.Error("[CLIENT]: Invalid autopilot request");
- return;
- }
- m_moveToPositionInProgress = true;
- m_moveToPositionTarget = new Vector3(locx, locy, locz);
- }
- catch (Exception ex)
- {
- //Why did I get this error?
- m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex);
- }
- }
-
- private void CheckAtSitTarget()
- {
- //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString());
- if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5)
- {
- if (m_sitAtAutoTarget)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID);
- if (part != null)
- {
- AbsolutePosition = part.AbsolutePosition;
- Velocity = Vector3.Zero;
- SendFullUpdateToAllClients();
-
- HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
- }
- //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
- m_requestedSitTargetUUID = UUID.Zero;
- }
- /*
- else
- {
- //ControllingClient.SendAlertMessage("Autopilot cancelled");
- //SendTerseUpdateToAllClients();
- //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
- //proxy.PCode = (byte)PCode.ParticleSystem;
- ////uint nextUUID = m_scene.NextLocalId;
-
- //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy);
- //if (proxyObjectGroup != null)
- //{
- //proxyObjectGroup.SendGroupFullUpdate();
- //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
- //m_scene.DeleteSceneObject(proxyObjectGroup);
- //}
- }
- */
- m_autoPilotTarget = Vector3.Zero;
- m_autopilotMoving = false;
- }
- }
- ///
- /// Perform the logic necessary to stand the avatar up. This method also executes
- /// the stand animation.
- ///
- public void StandUp()
- {
- SitGround = false;
-
- if (m_parentID != 0)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
- if (part != null)
- {
- part.TaskInventory.LockItemsForRead(true);
- TaskInventoryDictionary taskIDict = part.TaskInventory;
- if (taskIDict != null)
- {
- foreach (UUID taskID in taskIDict.Keys)
- {
- UnRegisterControlEventsToScript(LocalId, taskID);
- taskIDict[taskID].PermsMask &= ~(
- 2048 | //PERMISSION_CONTROL_CAMERA
- 4); // PERMISSION_TAKE_CONTROLS
- }
- }
- part.TaskInventory.LockItemsForRead(false);
- // Reset sit target.
- if (part.GetAvatarOnSitTarget() == UUID)
- part.SetAvatarOnSitTarget(UUID.Zero);
- m_parentPosition = part.GetWorldPosition();
- ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
- }
- // part.GetWorldRotation() is the rotation of the object being sat on
- // Rotation is the sittiing Av's rotation
-
- Quaternion partRot;
-// if (part.LinkNum == 1)
-// { // Root prim of linkset
-// partRot = part.ParentGroup.RootPart.RotationOffset;
-// }
-// else
-// { // single or child prim
-
-// }
- if (part == null) //CW: Part may be gone. llDie() for example.
- {
- partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- partRot = part.GetWorldRotation();
- }
-
- Quaternion partIRot = Quaternion.Inverse(partRot);
-
- Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
- Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
-
-
- if (m_physicsActor == null)
- {
- AddToPhysicalScene(false);
- }
- //CW: If the part isn't null then we can set the current position
- if (part != null)
- {
- Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
- AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
- part.IsOccupied = false;
- part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
- }
- else
- {
- //CW: Since the part doesn't exist, a coarse standup position isn't an issue
- AbsolutePosition = m_lastWorldPosition;
- }
-
- m_parentPosition = Vector3.Zero;
- m_parentID = 0;
- m_linkedPrim = UUID.Zero;
- m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- SendFullUpdateToAllClients();
- m_requestedSitTargetID = 0;
-
- if ((m_physicsActor != null) && (m_avHeight > 0))
- {
- SetHeight(m_avHeight);
- }
- }
- Animator.TrySetMovementAnimation("STAND");
- }
-
- private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
- {
- SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID);
- if (targetPart == null)
- return null;
-
- // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used.
- // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
-
- // Get our own copy of the part array, and sort into the order we want to test
- SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts();
- Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
- {
- // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
- int linkNum1 = p1==targetPart ? -1 : p1.LinkNum;
- int linkNum2 = p2==targetPart ? -1 : p2.LinkNum;
- return linkNum1 - linkNum2;
- }
- );
-
- //look for prims with explicit sit targets that are available
- foreach (SceneObjectPart part in partArray)
- {
- // Is a sit target available?
- Vector3 avSitOffSet = part.SitTargetPosition;
- Quaternion avSitOrientation = part.SitTargetOrientation;
- UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
- bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
- bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
- if (SitTargetisSet && !SitTargetOccupied)
- {
- //switch the target to this prim
- return part;
- }
- }
-
- // no explicit sit target found - use original target
- return targetPart;
- }
-
- private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
- {
- bool autopilot = true;
- Vector3 autopilotTarget = new Vector3();
- Quaternion sitOrientation = Quaternion.Identity;
- Vector3 pos = new Vector3();
- Vector3 cameraEyeOffset = Vector3.Zero;
- Vector3 cameraAtOffset = Vector3.Zero;
- bool forceMouselook = false;
-
- //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
- SceneObjectPart part = FindNextAvailableSitTarget(targetID);
- if (part == null) return;
-
- // TODO: determine position to sit at based on scene geometry; don't trust offset from client
- // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
-
- // part is the prim to sit on
- // offset is the world-ref vector distance from that prim center to the click-spot
- // UUID is the UUID of the Avatar doing the clicking
-
- m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
-
- // Is a sit target available?
- Vector3 avSitOffSet = part.SitTargetPosition;
- Quaternion avSitOrientation = part.SitTargetOrientation;
-
- bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
- // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
- Quaternion partRot;
-// if (part.LinkNum == 1)
-// { // Root prim of linkset
-// partRot = part.ParentGroup.RootPart.RotationOffset;
-// }
-// else
-// { // single or child prim
- partRot = part.GetWorldRotation();
-// }
- Quaternion partIRot = Quaternion.Inverse(partRot);
-//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
- // Sit analysis rewritten by KF 091125
- if (SitTargetisSet) // scipted sit
- {
- if (!part.IsOccupied)
- {
-//Console.WriteLine("Scripted, unoccupied");
- part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
- offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
-
- Quaternion nrot = avSitOrientation;
- if (!part.IsRoot)
- {
- nrot = part.RotationOffset * avSitOrientation;
- }
- sitOrientation = nrot; // Change rotatione to the scripted one
- OffsetRotation = nrot;
- autopilot = false; // Jump direct to scripted llSitPos()
- }
- else
- {
-//Console.WriteLine("Scripted, occupied");
- return;
- }
- }
- else // Not Scripted
- {
- if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
- {
- // large prim & offset, ignore if other Avs sitting
-// offset.Z -= 0.05f;
- m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
- autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
-
-//Console.WriteLine(" offset ={0}", offset);
-//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
-//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
-
- }
- else // small offset
- {
-//Console.WriteLine("Small offset");
- if (!part.IsOccupied)
- {
- m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
- autopilotTarget = part.AbsolutePosition;
-//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
- }
- else return; // occupied small
- } // end large/small
- } // end Scripted/not
- cameraAtOffset = part.GetCameraAtOffset();
- cameraEyeOffset = part.GetCameraEyeOffset();
- forceMouselook = part.GetForceMouselook();
- if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
- if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
-
- if (m_physicsActor != null)
- {
- // If we're not using the client autopilot, we're immediately warping the avatar to the location
- // We can remove the physicsActor until they stand up.
- m_sitAvatarHeight = m_physicsActor.Size.Z;
- if (autopilot)
- { // its not a scripted sit
-// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
- if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
- {
- autopilot = false; // close enough
- m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
- Not using the part's position because returning the AV to the last known standing
- position is likely to be more friendly, isn't it? */
- RemoveFromPhysicalScene();
- Velocity = Vector3.Zero;
- AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
- } // else the autopilot will get us close
- }
- else
- { // its a scripted sit
- m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
- I *am* using the part's position this time because we have no real idea how far away
- the avatar is from the sit target. */
- RemoveFromPhysicalScene();
- Velocity = Vector3.Zero;
- }
- }
- else return; // physactor is null!
-
- Vector3 offsetr; // = offset * partIRot;
- // KF: In a linkset, offsetr needs to be relative to the group root! 091208
- // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
- // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
- // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
- //offsetr = offset * partIRot;
-//
- // else
- // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
- // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
- // (offset * partRot);
- // }
-
-//Console.WriteLine(" ");
-//Console.WriteLine("link number ={0}", part.LinkNum);
-//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
-//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
-//Console.WriteLine("Click offst ={0}", offset);
-//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
-//Console.WriteLine("offsetr ={0}", offsetr);
-//Console.WriteLine("Camera At ={0}", cameraAtOffset);
-//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
-
- //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
- ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
-
- m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
- // This calls HandleAgentSit twice, once from here, and the client calls
- // HandleAgentSit itself after it gets to the location
- // It doesn't get to the location until we've moved them there though
- // which happens in HandleAgentSit :P
- m_autopilotMoving = autopilot;
- m_autoPilotTarget = autopilotTarget;
- m_sitAtAutoTarget = autopilot;
- m_initialSitTarget = autopilotTarget;
- if (!autopilot)
- HandleAgentSit(remoteClient, UUID);
- }
-
- public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
- {
- if (m_parentID != 0)
- {
- StandUp();
- }
- m_nextSitAnimation = "SIT";
-
- //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
- SceneObjectPart part = FindNextAvailableSitTarget(targetID);
-
- if (part != null)
- {
- if (!String.IsNullOrEmpty(part.SitAnimation))
- {
- m_nextSitAnimation = part.SitAnimation;
- }
- m_requestedSitTargetID = part.LocalId;
- //m_requestedSitOffset = offset;
- m_requestedSitTargetUUID = targetID;
-
- m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
-
- if (m_scene.PhysicsScene.SupportsRayCast())
- {
- //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback());
- //SitRayCastAvatarPosition(part);
- //return;
- }
- }
- else
- {
-
- m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
- }
-
-
-
- SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
- }
- /*
- public void SitRayCastAvatarPosition(SceneObjectPart part)
- {
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = AbsolutePosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse);
- }
-
- public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- }
- else
- {
- SitRayCastAvatarPositionCameraZ(part);
- }
- }
- else
- {
- SitRayCastAvatarPositionCameraZ(part);
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part)
- {
- // Next, try to raycast from the camera Z position
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse);
- }
-
- public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- }
- else
- {
- SitRayCastCameraPosition(part);
- }
- }
- else
- {
- SitRayCastCameraPosition(part);
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- public void SitRayCastCameraPosition(SceneObjectPart part)
- {
- // Next, try to raycast from the camera position
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = CameraPosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse);
- }
-
- public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- }
- else
- {
- SitRayHorizontal(part);
- }
- }
- else
- {
- SitRayHorizontal(part);
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- public void SitRayHorizontal(SceneObjectPart part)
- {
- // Next, try to raycast from the avatar position to fwd
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = CameraPosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse);
- }
-
- public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
- {
- SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
- if (part != null)
- {
- if (hitYN)
- {
- if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
- {
- SitRaycastFindEdge(collisionPoint, normal);
- m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
- // Next, try to raycast from the camera position
- Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
- Vector3 StartRayCastPosition = CameraPosition;
- Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
- float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
- //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition);
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position not accessable.");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position not accessable.");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
- }
- else
- {
- ControllingClient.SendAlertMessage("Sit position no longer exists");
- m_requestedSitTargetUUID = UUID.Zero;
- m_requestedSitTargetID = 0;
- m_requestedSitOffset = Vector3.Zero;
- }
-
- }
-
- private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal)
- {
- int i = 0;
- //throw new NotImplementedException();
- //m_requestedSitTargetUUID = UUID.Zero;
- //m_requestedSitTargetID = 0;
- //m_requestedSitOffset = Vector3.Zero;
-
- SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity);
- }
- */
- public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation)
- {
- if (m_parentID != 0)
- {
- StandUp();
- }
- if (!String.IsNullOrEmpty(sitAnimation))
- {
- m_nextSitAnimation = sitAnimation;
- }
- else
- {
- m_nextSitAnimation = "SIT";
- }
-
- //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
- SceneObjectPart part = FindNextAvailableSitTarget(targetID);
- if (part != null)
- {
- m_requestedSitTargetID = part.LocalId;
- //m_requestedSitOffset = offset;
- m_requestedSitTargetUUID = targetID;
-
- m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
-
- if (m_scene.PhysicsScene.SupportsRayCast())
- {
- //SitRayCastAvatarPosition(part);
- //return;
- }
- }
- else
- {
- m_log.Warn("Sit requested on unknown object: " + targetID);
- }
-
- SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
- }
-
- public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
- {
- if (!String.IsNullOrEmpty(m_nextSitAnimation))
- {
- HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
- }
- else
- {
- HandleAgentSit(remoteClient, agentID, "SIT");
- }
- }
-
- public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
- {
- SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
-
- if (m_sitAtAutoTarget || !m_autopilotMoving)
- {
- if (part != null)
- {
-//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
- if (part.GetAvatarOnSitTarget() == UUID)
- {
-//Console.WriteLine("Scripted Sit");
- // Scripted sit
- Vector3 sitTargetPos = part.SitTargetPosition;
- Quaternion sitTargetOrient = part.SitTargetOrientation;
- m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
- m_pos += SIT_TARGET_ADJUSTMENT;
- if (!part.IsRoot)
- {
- m_pos *= part.RotationOffset;
- }
- m_bodyRot = sitTargetOrient;
- m_parentPosition = part.AbsolutePosition;
- part.IsOccupied = true;
- part.ParentGroup.AddAvatar(agentID);
- }
- else
- {
- // if m_avUnscriptedSitPos is zero then Av sits above center
- // Else Av sits at m_avUnscriptedSitPos
-
- // Non-scripted sit by Kitto Flora 21Nov09
- // Calculate angle of line from prim to Av
- Quaternion partIRot;
-// if (part.LinkNum == 1)
-// { // Root prim of linkset
-// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
-// }
-// else
-// { // single or child prim
- partIRot = Quaternion.Inverse(part.GetWorldRotation());
-// }
- Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
- float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
- float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
- if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
- if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
- float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
- // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
- // Av sits at world euler <0,0, z>, translated by part rotation
- m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
-
- m_parentPosition = part.AbsolutePosition;
- part.IsOccupied = true;
- part.ParentGroup.AddAvatar(agentID);
- m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
- (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
- (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
- m_avUnscriptedSitPos; // adds click offset, if any
- //Set up raytrace to find top surface of prim
- Vector3 size = part.Scale;
- float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
- Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
- Vector3 down = new Vector3(0f, 0f, -1f);
-//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
- m_scene.PhysicsScene.RaycastWorld(
- start, // Vector3 position,
- down, // Vector3 direction,
- mag, // float length,
- SitAltitudeCallback); // retMethod
- } // end scripted/not
- }
- else // no Av
- {
- return;
- }
- }
-
- //We want our offsets to reference the root prim, not the child we may have sat on
- if (!part.IsRoot)
- {
- m_parentID = part.ParentGroup.RootPart.LocalId;
- m_pos += part.OffsetPosition;
- }
- else
- {
- m_parentID = m_requestedSitTargetID;
- }
-
- m_linkedPrim = part.UUID;
- if (part.GetAvatarOnSitTarget() != UUID)
- {
- m_offsetRotation = m_offsetRotation / part.RotationOffset;
- }
- Velocity = Vector3.Zero;
- RemoveFromPhysicalScene();
- Animator.TrySetMovementAnimation(sitAnimation);
- SendFullUpdateToAllClients();
- SendTerseUpdateToAllClients();
- }
-
- public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
- {
- // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
- // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
- if(hitYN)
- {
- // m_pos = Av offset from prim center to make look like on center
- // m_parentPosition = Actual center pos of prim
- // collisionPoint = spot on prim where we want to sit
- // collisionPoint.Z = global sit surface height
- SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
- Quaternion partIRot;
-// if (part.LinkNum == 1)
-/// { // Root prim of linkset
-// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
-// }
-// else
-// { // single or child prim
- partIRot = Quaternion.Inverse(part.GetWorldRotation());
-// }
- if (m_initialSitTarget != null)
- {
- float offZ = collisionPoint.Z - m_initialSitTarget.Z;
- Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
- //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
- m_pos += offset;
- // ControllingClient.SendClearFollowCamProperties(part.UUID);
- }
-
- }
- } // End SitAltitudeCallback KF.
-
- ///
- /// Event handler for the 'Always run' setting on the client
- /// Tells the physics plugin to increase speed of movement.
- ///
- public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun)
- {
- m_setAlwaysRun = pSetAlwaysRun;
- if (PhysicsActor != null)
- {
- PhysicsActor.SetAlwaysRun = pSetAlwaysRun;
- }
- }
-
- public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
- {
- Animator.AddAnimation(animID, UUID.Zero);
- }
-
- public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
- {
- Animator.RemoveAnimation(animID);
- }
-
- ///
- /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
- ///
- /// The vector in which to move. This is relative to the rotation argument
- /// The direction in which this avatar should now face.
- public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
- {
- if (m_isChildAgent)
- {
- // WHAT???
- m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!");
-
- // we have to reset the user's child agent connections.
- // Likely, here they've lost the eventqueue for other regions so border
- // crossings will fail at this point unless we reset them.
-
- List regions = new List(KnownChildRegionHandles);
- regions.Remove(m_scene.RegionInfo.RegionHandle);
-
- MakeRootAgent(new Vector3(127f, 127f, 127f), true);
-
- // Async command
- if (m_scene.SceneGridService != null)
- {
- m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions);
-
- // Give the above command some time to try and close the connections.
- // this is really an emergency.. so sleep, or we'll get all discombobulated.
- System.Threading.Thread.Sleep(500);
- }
-
- if (m_scene.SceneGridService != null)
- {
- IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
- if (m_agentTransfer != null)
- m_agentTransfer.EnableChildAgents(this);
- }
-
- return;
- }
-
- m_perfMonMS = Util.EnvironmentTickCount();
-
- Rotation = rotation;
- Vector3 direc = vec * rotation;
- direc.Normalize();
- PhysicsActor actor = m_physicsActor;
- if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
-
- direc *= 0.03f * 128f * m_speedModifier;
-
- if (actor != null)
- {
- if (actor.Flying)
- {
- direc *= 4.0f;
- //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
- //bool colliding = (m_physicsActor.IsColliding==true);
- //if (controlland)
- // m_log.Info("[AGENT]: landCommand");
- //if (colliding)
- // m_log.Info("[AGENT]: colliding");
- //if (m_physicsActor.Flying && colliding && controlland)
- //{
- // StopFlying();
- // m_log.Info("[AGENT]: Stop FLying");
- //}
- }
- else if (!actor.Flying && actor.IsColliding)
- {
- if (direc.Z > 2.0f)
- {
- if(m_animator.m_animTickJump == -1)
- {
- direc.Z *= 3.0f; // jump
- }
- else
- {
- direc.Z *= 0.1f; // prejump
- }
- /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
- Animator.TrySetMovementAnimation("PREJUMP");
- Animator.TrySetMovementAnimation("JUMP");
- */
- }
- }
- }
-
- // TODO: Add the force instead of only setting it to support multiple forces per frame?
- m_forceToApply = direc;
- m_isNudging = Nudging;
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- #endregion
-
- #region Overridden Methods
-
- public override void Update()
- {
- const float ROTATION_TOLERANCE = 0.01f;
- const float VELOCITY_TOLERANCE = 0.001f;
- const float POSITION_TOLERANCE = 0.05f;
- //const int TIME_MS_TOLERANCE = 3000;
-
-
-
- if (m_isChildAgent == false)
- {
-// PhysicsActor actor = m_physicsActor;
-
- // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
- // grab the latest PhysicsActor velocity, whereas m_velocity is often
- // storing a requested force instead of an actual traveling velocity
-
- // Throw away duplicate or insignificant updates
- if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
- !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
- !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
- //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
- {
- SendTerseUpdateToAllClients();
-
- // Update the "last" values
- m_lastPosition = m_pos;
- m_lastRotation = m_bodyRot;
- m_lastVelocity = Velocity;
- //m_lastTerseSent = Environment.TickCount;
- }
-
- // followed suggestion from mic bowman. reversed the two lines below.
- if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something
- CheckForBorderCrossing();
- CheckForSignificantMovement(); // sends update to the modules.
- }
-
- //Sending prim updates AFTER the avatar terse updates are sent
- SendPrimUpdates();
- }
-
- #endregion
-
- #region Update Client(s)
-
- ///
- /// Sends a location update to the client connected to this scenePresence
- ///
- ///
- public void SendTerseUpdateToClient(IClientAPI remoteClient)
- {
- // If the client is inactive, it's getting its updates from another
- // server.
- if (remoteClient.IsActive)
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- PhysicsActor actor = m_physicsActor;
- Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero;
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
-
- remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- m_scene.StatsReporter.AddAgentUpdates(1);
- }
- }
-
- ///
- /// Send a location/velocity/accelleration update to all agents in scene
- ///
- public void SendTerseUpdateToAllClients()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- m_scene.ForEachClient(SendTerseUpdateToClient);
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- public void SendCoarseLocations(List coarseLocations, List avatarUUIDs)
- {
- SendCourseLocationsMethod d = m_sendCourseLocationsMethod;
- if (d != null)
- {
- d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
- }
- }
-
- public void SetSendCourseLocationMethod(SendCourseLocationsMethod d)
- {
- if (d != null)
- m_sendCourseLocationsMethod = d;
- }
-
- public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs)
- {
- m_perfMonMS = Util.EnvironmentTickCount();
- m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- ///
- /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar)
- ///
- ///
- public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar)
- {
- // 2 stage check is needed.
- if (remoteAvatar == null)
- return;
- IClientAPI cl=remoteAvatar.ControllingClient;
- if (cl == null)
- return;
- if (m_appearance.Texture == null)
- return;
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
- m_scene.StatsReporter.AddAgentUpdates(1);
- }
-
- ///
- /// Tell *ALL* agents about this agent
- ///
- public void SendInitialFullUpdateToAllClients()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
- int avUpdates = 0;
- m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
- {
- ++avUpdates;
- // only send if this is the root (children are only "listening posts" in a foreign region)
- if (!IsChildAgent)
- {
- SendFullUpdateToOtherClient(avatar);
- }
-
- if (avatar.LocalId != LocalId)
- {
- if (!avatar.IsChildAgent)
- {
- avatar.SendFullUpdateToOtherClient(this);
- avatar.SendAppearanceToOtherAgent(this);
- avatar.Animator.SendAnimPackToClient(ControllingClient);
- }
- }
- });
-
- m_scene.StatsReporter.AddAgentUpdates(avUpdates);
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
-
- //Animator.SendAnimPack();
- }
-
- public void SendFullUpdateToAllClients()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- // only send update from root agents to other clients; children are only "listening posts"
- int count = 0;
- m_scene.ForEachScenePresence(delegate(ScenePresence sp)
- {
- if (sp.IsChildAgent)
- return;
- SendFullUpdateToOtherClient(sp);
- ++count;
- });
- m_scene.StatsReporter.AddAgentUpdates(count);
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
-
- Animator.SendAnimPack();
- }
-
- ///
- /// Do everything required once a client completes its movement into a region
- ///
- public void SendInitialData()
- {
- // Moved this into CompleteMovement to ensure that m_appearance is initialized before
- // the inventory arrives
- // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- m_controllingClient.SendAvatarDataImmediate(this);
-
- SendInitialFullUpdateToAllClients();
- SendAppearanceToAllOtherAgents();
- }
-
- ///
- /// Tell the client for this scene presence what items it should be wearing now
- ///
- public void SendWearables()
- {
- m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name);
-
- ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
- }
-
- ///
- ///
- ///
- public void SendAppearanceToAllOtherAgents()
- {
- m_perfMonMS = Util.EnvironmentTickCount();
-
- m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
- {
- if (scenePresence.UUID != UUID)
- {
- SendAppearanceToOtherAgent(scenePresence);
- }
- });
-
- m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
- }
-
- ///
- /// Send appearance data to an agent that isn't this one.
- ///
- ///
- public void SendAppearanceToOtherAgent(ScenePresence avatar)
- {
- avatar.ControllingClient.SendAppearance(
- m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
- }
-
- ///
- /// Set appearance data (textureentry and slider settings) received from the client
- ///
- ///
- ///
- public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
- {
- if (m_physicsActor != null)
- {
- if (!IsChildAgent)
- {
- // This may seem like it's redundant, remove the avatar from the physics scene
- // just to add it back again, but it saves us from having to update
- // 3 variables 10 times a second.
- bool flyingTemp = m_physicsActor.Flying;
- RemoveFromPhysicalScene();
- //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
-
- //PhysicsActor = null;
-
- AddToPhysicalScene(flyingTemp);
- }
- }
-
- #region Bake Cache Check
-
- if (textureEntry != null)
- {
- for (int i = 0; i < BAKE_INDICES.Length; i++)
- {
- int j = BAKE_INDICES[i];
- Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
-
- if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
- {
- if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
- {
- m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name);
- this.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
- }
- }
- }
-
- }
-
-
- #endregion Bake Cache Check
-
- m_appearance.SetAppearance(textureEntry, visualParams);
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
-
- // This is not needed, because only the transient data changed
- //AvatarData adata = new AvatarData(m_appearance);
- //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
-
- SendAppearanceToAllOtherAgents();
- if (!m_startAnimationSet)
- {
- Animator.UpdateMovementAnimations();
- m_startAnimationSet = true;
- }
-
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
-
- m_controllingClient.SendAvatarDataImmediate(this);
- }
-
- public void SetWearable(int wearableId, AvatarWearable wearable)
- {
- m_appearance.SetWearable(wearableId, wearable);
- AvatarData adata = new AvatarData(m_appearance);
- m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
- m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
- }
-
- // Because appearance setting is in a module, we actually need
- // to give it access to our appearance directly, otherwise we
- // get a synchronization issue.
- public AvatarAppearance Appearance
- {
- get { return m_appearance; }
- set { m_appearance = value; }
- }
-
- #endregion
-
- #region Significant Movement Method
-
- ///
- /// This checks for a significant movement and sends a courselocationchange update
- ///
- protected void CheckForSignificantMovement()
- {
- // Movement updates for agents in neighboring regions are sent directly to clients.
- // This value only affects how often agent positions are sent to neighbor regions
- // for things such as distance-based update prioritization
- const float SIGNIFICANT_MOVEMENT = 2.0f;
-
- if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT)
- {
- posLastSignificantMove = AbsolutePosition;
- m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient);
- }
-
- // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
- if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance ||
- Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
- {
- m_lastChildAgentUpdatePosition = AbsolutePosition;
- m_lastChildAgentUpdateCamPosition = CameraPosition;
-
- ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
- cadu.ActiveGroupID = UUID.Zero.Guid;
- cadu.AgentID = UUID.Guid;
- cadu.alwaysrun = m_setAlwaysRun;
- cadu.AVHeight = m_avHeight;
- Vector3 tempCameraCenter = m_CameraCenter;
- cadu.cameraPosition = tempCameraCenter;
- cadu.drawdistance = m_DrawDistance;
- cadu.GroupAccess = 0;
- cadu.Position = AbsolutePosition;
- cadu.regionHandle = m_rootRegionHandle;
- float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / (float)innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
- multiplier = 0.25f;
- }
-
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
- cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
- cadu.Velocity = Velocity;
-
- AgentPosition agentpos = new AgentPosition();
- agentpos.CopyFrom(cadu);
-
- m_scene.SendOutChildAgentUpdates(agentpos, this);
- }
- }
-
- #endregion
-
- #region Border Crossing Methods
-
- ///
- /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion
- ///
- protected void CheckForBorderCrossing()
- {
- if (IsChildAgent)
- return;
-
- Vector3 pos2 = AbsolutePosition;
- Vector3 vel = Velocity;
- int neighbor = 0;
- int[] fix = new int[2];
-
- float timeStep = 0.1f;
- pos2.X = pos2.X + (vel.X*timeStep);
- pos2.Y = pos2.Y + (vel.Y*timeStep);
- pos2.Z = pos2.Z + (vel.Z*timeStep);
-
- if (!IsInTransit)
- {
- // Checks if where it's headed exists a region
-
- bool needsTransit = false;
- if (m_scene.TestBorderCross(pos2, Cardinals.W))
- {
- if (m_scene.TestBorderCross(pos2, Cardinals.S))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.SW, ref fix);
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.N))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.NW, ref fix);
- }
- else
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.W, ref fix);
- }
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.E))
- {
- if (m_scene.TestBorderCross(pos2, Cardinals.S))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.SE, ref fix);
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.N))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.NE, ref fix);
- }
- else
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.E, ref fix);
- }
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.S))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.S, ref fix);
- }
- else if (m_scene.TestBorderCross(pos2, Cardinals.N))
- {
- needsTransit = true;
- neighbor = HaveNeighbor(Cardinals.N, ref fix);
- }
-
-
- // Makes sure avatar does not end up outside region
- if (neighbor <= 0)
- {
- if (!needsTransit)
- {
- if (m_requestedSitTargetUUID == UUID.Zero)
- {
- Vector3 pos = AbsolutePosition;
- if (AbsolutePosition.X < 0)
- pos.X += Velocity.X;
- else if (AbsolutePosition.X > Constants.RegionSize)
- pos.X -= Velocity.X;
- if (AbsolutePosition.Y < 0)
- pos.Y += Velocity.Y;
- else if (AbsolutePosition.Y > Constants.RegionSize)
- pos.Y -= Velocity.Y;
- AbsolutePosition = pos;
- }
- }
- }
- else if (neighbor > 0)
- CrossToNewRegion();
- }
- else
- {
- RemoveFromPhysicalScene();
- // This constant has been inferred from experimentation
- // I'm not sure what this value should be, so I tried a few values.
- timeStep = 0.04f;
- pos2 = AbsolutePosition;
- pos2.X = pos2.X + (vel.X * timeStep);
- pos2.Y = pos2.Y + (vel.Y * timeStep);
- pos2.Z = pos2.Z + (vel.Z * timeStep);
- m_pos = pos2;
- }
- }
-
- protected int HaveNeighbor(Cardinals car, ref int[] fix)
- {
- uint neighbourx = m_regionInfo.RegionLocX;
- uint neighboury = m_regionInfo.RegionLocY;
-
- int dir = (int)car;
-
- if (dir > 1 && dir < 5) //Heading East
- neighbourx++;
- else if (dir > 5) // Heading West
- neighbourx--;
-
- if (dir < 3 || dir == 8) // Heading North
- neighboury++;
- else if (dir > 3 && dir < 7) // Heading Sout
- neighboury--;
-
- int x = (int)(neighbourx * Constants.RegionSize);
- int y = (int)(neighboury * Constants.RegionSize);
- GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y);
-
- if (neighbourRegion == null)
- {
- fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx);
- fix[1] = (int)(m_regionInfo.RegionLocY - neighboury);
- return dir * (-1);
- }
- else
- return dir;
- }
-
- ///
- /// Moves the agent outside the region bounds
- /// Tells neighbor region that we're crossing to it
- /// If the neighbor accepts, remove the agent's viewable avatar from this scene
- /// set them to a child agent.
- ///
- protected void CrossToNewRegion()
- {
- InTransit();
- try
- {
- m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying);
- }
- catch
- {
- m_scene.CrossAgentToNewRegion(this, false);
- }
- }
-
- public void InTransit()
- {
- m_inTransit = true;
-
- if ((m_physicsActor != null) && m_physicsActor.Flying)
- m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY;
- else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
- m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY;
- }
-
- public void NotInTransit()
- {
- m_inTransit = false;
- }
-
- public void RestoreInCurrentScene()
- {
- AddToPhysicalScene(false); // not exactly false
- }
-
- public void Reset()
- {
- // Put the child agent back at the center
- AbsolutePosition
- = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
- Animator.ResetAnimations();
- }
-
- ///
- /// Computes which child agents to close when the scene presence moves to another region.
- /// Removes those regions from m_knownRegions.
- ///
- /// The new region's x on the map
- /// The new region's y on the map
- ///
- public void CloseChildAgents(uint newRegionX, uint newRegionY)
- {
- List byebyeRegions = new List();
- m_log.DebugFormat(
- "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
- m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName);
- //DumpKnownRegions();
-
- lock (m_knownChildRegions)
- {
- foreach (ulong handle in m_knownChildRegions.Keys)
- {
- // Don't close the agent on this region yet
- if (handle != Scene.RegionInfo.RegionHandle)
- {
- uint x, y;
- Utils.LongToUInts(handle, out x, out y);
- x = x / Constants.RegionSize;
- y = y / Constants.RegionSize;
-
- //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
- //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
- if (Util.IsOutsideView(x, newRegionX, y, newRegionY))
- {
- byebyeRegions.Add(handle);
- }
- }
- }
- }
-
- if (byebyeRegions.Count > 0)
- {
- m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
- m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions);
- }
-
- foreach (ulong handle in byebyeRegions)
- {
- RemoveNeighbourRegion(handle);
- }
- }
-
- #endregion
-
- ///
- /// This allows the Sim owner the abiility to kick users from their sim currently.
- /// It tells the client that the agent has permission to do so.
- ///
- public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
- {
- if (godStatus)
- {
- // For now, assign god level 200 to anyone
- // who is granted god powers, but has no god level set.
- //
- UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
- if (account != null)
- {
- if (account.UserLevel > 0)
- m_godLevel = account.UserLevel;
- else
- m_godLevel = 200;
- }
- }
- else
- {
- m_godLevel = 0;
- }
-
- ControllingClient.SendAdminResponse(token, (uint)m_godLevel);
- }
-
- #region Child Agent Updates
-
- public void ChildAgentDataUpdate(AgentData cAgentData)
- {
- //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
- if (!IsChildAgent)
- return;
-
- CopyFrom(cAgentData);
- }
-
- ///
- /// This updates important decision making data about a child agent
- /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
- ///
- public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
- {
- if (!IsChildAgent)
- return;
-
- //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
- int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
- int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
-
- Vector3 offset = new Vector3(shiftx, shifty, 0f);
-
- m_DrawDistance = cAgentData.Far;
- if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!!
- m_pos = cAgentData.Position + offset;
-
- if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance)
- {
- posLastSignificantMove = AbsolutePosition;
- ReprioritizeUpdates();
- }
-
- m_CameraCenter = cAgentData.Center + offset;
-
- m_avHeight = cAgentData.Size.Z;
- //SetHeight(cAgentData.AVHeight);
-
- if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
- ControllingClient.SetChildAgentThrottle(cAgentData.Throttles);
-
- // Sends out the objects in the user's draw distance if m_sendTasksToChild is true.
- if (m_scene.m_seeIntoRegionFromNeighbor)
- m_sceneViewer.Reset();
-
- //cAgentData.AVHeight;
- m_rootRegionHandle = cAgentData.RegionHandle;
- //m_velocity = cAgentData.Velocity;
- }
-
- public void CopyTo(AgentData cAgent)
- {
- cAgent.AgentID = UUID;
- cAgent.RegionID = Scene.RegionInfo.RegionID;
-
- cAgent.Position = AbsolutePosition;
- cAgent.Velocity = m_velocity;
- cAgent.Center = m_CameraCenter;
- // Don't copy the size; it is inferred from apearance parameters
- //cAgent.Size = new Vector3(0, 0, m_avHeight);
- cAgent.AtAxis = m_CameraAtAxis;
- cAgent.LeftAxis = m_CameraLeftAxis;
- cAgent.UpAxis = m_CameraUpAxis;
-
- cAgent.Far = m_DrawDistance;
-
- // Throttles
- float multiplier = 1;
- int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
- if (innacurateNeighbors != 0)
- {
- multiplier = 1f / innacurateNeighbors;
- }
- if (multiplier <= 0f)
- {
- multiplier = 0.25f;
- }
- //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
- cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
-
- cAgent.HeadRotation = m_headrotation;
- cAgent.BodyRotation = m_bodyRot;
- cAgent.ControlFlags = (uint)m_AgentControlFlags;
-
- if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
- cAgent.GodLevel = (byte)m_godLevel;
- else
- cAgent.GodLevel = (byte) 0;
-
- cAgent.AlwaysRun = m_setAlwaysRun;
-
- try
- {
- // We might not pass the Wearables in all cases...
- // They're only needed so that persistent changes to the appearance
- // are preserved in the new region where the user is moving to.
- // But in Hypergrid we might not let this happen.
- int i = 0;
- UUID[] wears = new UUID[m_appearance.Wearables.Length * 2];
- foreach (AvatarWearable aw in m_appearance.Wearables)
- {
- if (aw != null)
- {
- wears[i++] = aw.ItemID;
- wears[i++] = aw.AssetID;
- }
- else
- {
- wears[i++] = UUID.Zero;
- wears[i++] = UUID.Zero;
- }
- }
- cAgent.Wearables = wears;
-
- cAgent.VisualParams = m_appearance.VisualParams;
-
- if (m_appearance.Texture != null)
- cAgent.AgentTextures = m_appearance.Texture.GetBytes();
- }
- catch (Exception e)
- {
- m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message);
- }
-
- //Attachments
- List attPoints = m_appearance.GetAttachedPoints();
- if (attPoints != null)
- {
- //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count);
- int i = 0;
- AttachmentData[] attachs = new AttachmentData[attPoints.Count];
- foreach (int point in attPoints)
- {
- attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point));
- }
- cAgent.Attachments = attachs;
- }
-
- lock (scriptedcontrols)
- {
- ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
- int i = 0;
-
- foreach (ScriptControllers c in scriptedcontrols.Values)
- {
- controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
- }
- cAgent.Controllers = controls;
- }
-
- // Animations
- try
- {
- cAgent.Anims = Animator.Animations.ToArray();
- }
- catch { }
-
- // cAgent.GroupID = ??
- // Groups???
-
- }
-
- public void CopyFrom(AgentData cAgent)
- {
- m_originRegionID = cAgent.RegionID;
-
- m_callbackURI = cAgent.CallbackURI;
-
- m_pos = cAgent.Position;
-
- m_velocity = cAgent.Velocity;
- m_CameraCenter = cAgent.Center;
- //m_avHeight = cAgent.Size.Z;
- m_CameraAtAxis = cAgent.AtAxis;
- m_CameraLeftAxis = cAgent.LeftAxis;
- m_CameraUpAxis = cAgent.UpAxis;
-
- m_DrawDistance = cAgent.Far;
-
- if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
- ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
-
- m_headrotation = cAgent.HeadRotation;
- m_bodyRot = cAgent.BodyRotation;
- m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags;
-
- if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
- m_godLevel = cAgent.GodLevel;
- m_setAlwaysRun = cAgent.AlwaysRun;
-
- uint i = 0;
- try
- {
- if (cAgent.Wearables == null)
- cAgent.Wearables = new UUID[0];
- AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2];
- for (uint n = 0; n < cAgent.Wearables.Length; n += 2)
- {
- UUID itemId = cAgent.Wearables[n];
- UUID assetId = cAgent.Wearables[n + 1];
- wears[i++] = new AvatarWearable(itemId, assetId);
- }
- m_appearance.Wearables = wears;
- Primitive.TextureEntry te;
- if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1)
- te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length);
- else
- te = AvatarAppearance.GetDefaultTexture();
- if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT))
- cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams();
- m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone());
- }
- catch (Exception e)
- {
- m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message);
- }
-
- // Attachments
- try
- {
- if (cAgent.Attachments != null)
- {
- m_appearance.ClearAttachments();
- foreach (AttachmentData att in cAgent.Attachments)
- {
- m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID);
- }
- }
- }
- catch { }
-
- try
- {
- lock (scriptedcontrols)
- {
- if (cAgent.Controllers != null)
- {
- scriptedcontrols.Clear();
-
- foreach (ControllerData c in cAgent.Controllers)
- {
- ScriptControllers sc = new ScriptControllers();
- sc.itemID = c.ItemID;
- sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
- sc.eventControls = (ScriptControlled)c.EventControls;
-
- scriptedcontrols[sc.itemID] = sc;
- }
- }
- }
- }
- catch { }
- // Animations
- try
- {
- Animator.ResetAnimations();
- Animator.Animations.FromArray(cAgent.Anims);
- }
- catch { }
-
- //cAgent.GroupID = ??
- //Groups???
- }
-
- public bool CopyAgent(out IAgentData agent)
- {
- agent = new CompleteAgentData();
- CopyTo((AgentData)agent);
- return true;
- }
-
- #endregion Child Agent Updates
-
- ///
- /// Handles part of the PID controller function for moving an avatar.
- ///
- public override void UpdateMovement()
- {
- if (m_forceToApply.HasValue)
- {
-
- Vector3 force = m_forceToApply.Value;
- m_updateflag = true;
- Velocity = force;
-
- m_forceToApply = null;
- }
- else
- {
- if (m_isNudging)
- {
- Vector3 force = Vector3.Zero;
-
- m_updateflag = true;
- Velocity = force;
- m_isNudging = false;
- m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
- }
- }
- }
-
- public override void SetText(string text, Vector3 color, double alpha)
- {
- throw new Exception("Can't set Text on avatar.");
- }
-
- ///
- /// Adds a physical representation of the avatar to the Physics plugin
- ///
- public void AddToPhysicalScene(bool isFlying)
- {
- PhysicsScene scene = m_scene.PhysicsScene;
-
- Vector3 pVec = AbsolutePosition;
-
- // Old bug where the height was in centimeters instead of meters
- if (m_avHeight == 127.0f)
- {
- m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f),
- isFlying);
- }
- else
- {
- m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
- new Vector3(0f, 0f, m_avHeight), isFlying);
- }
- scene.AddPhysicsActorTaint(m_physicsActor);
- //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
- m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
- m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
- m_physicsActor.SubscribeEvents(500);
- m_physicsActor.LocalID = LocalId;
- }
-
- private void OutOfBoundsCall(Vector3 pos)
- {
- //bool flying = m_physicsActor.Flying;
- //RemoveFromPhysicalScene();
-
- //AddToPhysicalScene(flying);
- if (ControllingClient != null)
- ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
- }
-
- // Event called by the physics plugin to tell the avatar about a collision.
- private void PhysicsCollisionUpdate(EventArgs e)
- {
- if (e == null)
- return;
-
- // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
- // as of this comment the interval is set in AddToPhysicalScene
- if (Animator!=null)
- {
- if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
- { // else its will lock out other animation changes, like ground sit.
- Animator.UpdateMovementAnimations();
- m_updateCount--;
- }
- }
-
- CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
- Dictionary coldata = collisionData.m_objCollisionList;
-
- CollisionPlane = Vector4.UnitW;
-
- if (m_lastColCount != coldata.Count)
- {
- m_updateCount = UPDATE_COUNT;
- m_lastColCount = coldata.Count;
- }
-
- if (coldata.Count != 0 && Animator != null)
- {
- switch (Animator.CurrentMovementAnimation)
- {
- case "STAND":
- case "WALK":
- case "RUN":
- case "CROUCH":
- case "CROUCHWALK":
- {
- ContactPoint lowest;
- lowest.SurfaceNormal = Vector3.Zero;
- lowest.Position = Vector3.Zero;
- lowest.Position.Z = Single.NaN;
-
- foreach (ContactPoint contact in coldata.Values)
- {
- if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z)
- {
- lowest = contact;
- }
- }
-
- CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
- }
- break;
- }
- }
-
- List thisHitColliders = new List();
- List endedColliders = new List();
- List startedColliders = new List();
-
- foreach (uint localid in coldata.Keys)
- {
- thisHitColliders.Add(localid);
- if (!m_lastColliders.Contains(localid))
- {
- startedColliders.Add(localid);
- }
- //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
- }
-
- // calculate things that ended colliding
- foreach (uint localID in m_lastColliders)
- {
- if (!thisHitColliders.Contains(localID))
- {
- endedColliders.Add(localID);
- }
- }
- //add the items that started colliding this time to the last colliders list.
- foreach (uint localID in startedColliders)
- {
- m_lastColliders.Add(localID);
- }
- // remove things that ended colliding from the last colliders list
- foreach (uint localID in endedColliders)
- {
- m_lastColliders.Remove(localID);
- }
-
- // do event notification
- if (startedColliders.Count > 0)
- {
- ColliderArgs StartCollidingMessage = new ColliderArgs();
- List colliding = new List();
- foreach (uint localId in startedColliders)
- {
- if (localId == 0)
- continue;
-
- SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
- string data = "";
- if (obj != null)
- {
- DetectedObject detobj = new DetectedObject();
- detobj.keyUUID = obj.UUID;
- detobj.nameStr = obj.Name;
- detobj.ownerUUID = obj.OwnerID;
- detobj.posVector = obj.AbsolutePosition;
- detobj.rotQuat = obj.GetWorldRotation();
- detobj.velVector = obj.Velocity;
- detobj.colliderType = 0;
- detobj.groupUUID = obj.GroupID;
- colliding.Add(detobj);
- }
- }
-
- if (colliding.Count > 0)
- {
- StartCollidingMessage.Colliders = colliding;
-
- foreach (SceneObjectGroup att in Attachments)
- Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
- }
- }
-
- if (endedColliders.Count > 0)
- {
- ColliderArgs EndCollidingMessage = new ColliderArgs();
- List colliding = new List();
- foreach (uint localId in endedColliders)
- {
- if (localId == 0)
- continue;
-
- SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
- string data = "";
- if (obj != null)
- {
- DetectedObject detobj = new DetectedObject();
- detobj.keyUUID = obj.UUID;
- detobj.nameStr = obj.Name;
- detobj.ownerUUID = obj.OwnerID;
- detobj.posVector = obj.AbsolutePosition;
- detobj.rotQuat = obj.GetWorldRotation();
- detobj.velVector = obj.Velocity;
- detobj.colliderType = 0;
- detobj.groupUUID = obj.GroupID;
- colliding.Add(detobj);
- }
- }
-
- if (colliding.Count > 0)
- {
- EndCollidingMessage.Colliders = colliding;
-
- foreach (SceneObjectGroup att in Attachments)
- Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
- }
- }
-
- if (thisHitColliders.Count > 0)
- {
- ColliderArgs CollidingMessage = new ColliderArgs();
- List colliding = new List();
- foreach (uint localId in thisHitColliders)
- {
- if (localId == 0)
- continue;
-
- SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
- string data = "";
- if (obj != null)
- {
- DetectedObject detobj = new DetectedObject();
- detobj.keyUUID = obj.UUID;
- detobj.nameStr = obj.Name;
- detobj.ownerUUID = obj.OwnerID;
- detobj.posVector = obj.AbsolutePosition;
- detobj.rotQuat = obj.GetWorldRotation();
- detobj.velVector = obj.Velocity;
- detobj.colliderType = 0;
- detobj.groupUUID = obj.GroupID;
- colliding.Add(detobj);
- }
- }
-
- if (colliding.Count > 0)
- {
- CollidingMessage.Colliders = colliding;
-
- lock (m_attachments)
- {
- foreach (SceneObjectGroup att in m_attachments)
- Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
- }
- }
- }
-
- if (m_invulnerable)
- return;
-
- float starthealth = Health;
- uint killerObj = 0;
- foreach (uint localid in coldata.Keys)
- {
- SceneObjectPart part = Scene.GetSceneObjectPart(localid);
-
- if (part != null && part.ParentGroup.Damage != -1.0f)
- Health -= part.ParentGroup.Damage;
- else
- {
- if (coldata[localid].PenetrationDepth >= 0.10f)
- Health -= coldata[localid].PenetrationDepth * 5.0f;
- }
-
- if (Health <= 0.0f)
- {
- if (localid != 0)
- killerObj = localid;
- }
- //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
- }
- //Health = 100;
- if (!m_invulnerable)
- {
- if (starthealth != Health)
- {
- ControllingClient.SendHealth(Health);
- }
- if (m_health <= 0)
- m_scene.EventManager.TriggerAvatarKill(killerObj, this);
- }
- }
-
- public void setHealthWithUpdate(float health)
- {
- Health = health;
- ControllingClient.SendHealth(Health);
- }
-
- public void Close()
- {
- lock (m_attachments)
- {
- // Delete attachments from scene
- // Don't try to save, as this thread won't live long
- // enough to complete the save. This would cause no copy
- // attachments to poof!
- //
- foreach (SceneObjectGroup grp in m_attachments)
- {
- m_scene.DeleteSceneObject(grp, false);
- }
- m_attachments.Clear();
- }
-
- lock (m_knownChildRegions)
- {
- m_knownChildRegions.Clear();
- }
-
- lock (m_reprioritization_timer)
- {
- m_reprioritization_timer.Enabled = false;
- m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
- }
-
- // I don't get it but mono crashes when you try to dispose of this timer,
- // unsetting the elapsed callback should be enough to allow for cleanup however.
- // m_reprioritizationTimer.Dispose();
-
- m_sceneViewer.Close();
-
- RemoveFromPhysicalScene();
- m_animator.Close();
- m_animator = null;
- }
-
- public void AddAttachment(SceneObjectGroup gobj)
- {
- lock (m_attachments)
- {
- m_attachments.Add(gobj);
- }
- }
-
- public bool HasAttachments()
- {
- return m_attachments.Count > 0;
- }
-
- public bool HasScriptedAttachments()
- {
- lock (m_attachments)
- {
- foreach (SceneObjectGroup gobj in m_attachments)
- {
- if (gobj != null)
- {
- if (gobj.RootPart.Inventory.ContainsScripts())
- return true;
- }
- }
- }
- return false;
- }
-
- public void RemoveAttachment(SceneObjectGroup gobj)
- {
- lock (m_attachments)
- {
- if (m_attachments.Contains(gobj))
- {
- m_attachments.Remove(gobj);
- }
- }
- }
-
- public bool ValidateAttachments()
- {
- lock (m_attachments)
- {
- // Validate
- foreach (SceneObjectGroup gobj in m_attachments)
- {
- if (gobj == null)
- return false;
-
- if (gobj.IsDeleted)
- return false;
- }
- }
- return true;
- }
-
- ///
- /// Send a script event to this scene presence's attachments
- ///
- /// The name of the event
- /// The arguments for the event
- public void SendScriptEventToAttachments(string eventName, Object[] args)
- {
- if (m_scriptEngines != null)
- {
- lock (m_attachments)
- {
- foreach (SceneObjectGroup grp in m_attachments)
- {
- // 16384 is CHANGED_ANIMATION
- //
- // Send this to all attachment root prims
- //
- foreach (IScriptModule m in m_scriptEngines)
- {
- if (m == null) // No script engine loaded
- continue;
-
- m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
- }
- }
- }
- }
- }
-
-
- public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
- {
- m_controllingClient = client;
- m_regionInfo = region;
- m_scene = scene;
-
- RegisterToEvents();
- if (m_controllingClient != null)
- {
- m_controllingClient.ProcessPendingPackets();
- }
- /*
- AbsolutePosition = client.StartPos;
-
- Animations = new AvatarAnimations();
- Animations.LoadAnims();
-
- m_animations = new List();
- m_animations.Add(Animations.AnimsUUID["STAND"]);
- m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
-
- SetDirectionVectors();
- */
- }
-
- internal void PushForce(Vector3 impulse)
- {
- if (PhysicsActor != null)
- {
- PhysicsActor.AddForce(impulse,true);
- }
- }
-
- public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
- {
- ScriptControllers obj = new ScriptControllers();
- obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
- obj.eventControls = ScriptControlled.CONTROL_ZERO;
-
- obj.itemID = Script_item_UUID;
- if (pass_on == 0 && accept == 0)
- {
- IgnoredControls |= (ScriptControlled)controls;
- obj.ignoreControls = (ScriptControlled)controls;
- }
-
- if (pass_on == 0 && accept == 1)
- {
- IgnoredControls |= (ScriptControlled)controls;
- obj.ignoreControls = (ScriptControlled)controls;
- obj.eventControls = (ScriptControlled)controls;
- }
- if (pass_on == 1 && accept == 1)
- {
- IgnoredControls = ScriptControlled.CONTROL_ZERO;
- obj.eventControls = (ScriptControlled)controls;
- obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
- }
-
- lock (scriptedcontrols)
- {
- if (pass_on == 1 && accept == 0)
- {
- IgnoredControls &= ~(ScriptControlled)controls;
- if (scriptedcontrols.ContainsKey(Script_item_UUID))
- scriptedcontrols.Remove(Script_item_UUID);
- }
- else
- {
- scriptedcontrols[Script_item_UUID] = obj;
- }
- }
- ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
- }
-
- public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
- {
- IgnoredControls = ScriptControlled.CONTROL_ZERO;
- lock (scriptedcontrols)
- {
- scriptedcontrols.Clear();
- }
- ControllingClient.SendTakeControls(int.MaxValue, false, false);
- }
-
- public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
- {
- ScriptControllers takecontrols;
-
- lock (scriptedcontrols)
- {
- if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols))
- {
- ScriptControlled sctc = takecontrols.eventControls;
-
- ControllingClient.SendTakeControls((int)sctc, false, false);
- ControllingClient.SendTakeControls((int)sctc, true, false);
-
- scriptedcontrols.Remove(Script_item_UUID);
- IgnoredControls = ScriptControlled.CONTROL_ZERO;
- foreach (ScriptControllers scData in scriptedcontrols.Values)
- {
- IgnoredControls |= scData.ignoreControls;
- }
- }
- }
- }
-
- internal void SendControlToScripts(uint flags)
- {
- ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
-
- if (MouseDown)
- {
- allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
- {
- allflags = ScriptControlled.CONTROL_ZERO;
- MouseDown = true;
- }
- }
-
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
- {
- allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
- MouseDown = true;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
- {
- allflags |= ScriptControlled.CONTROL_LBUTTON;
- MouseDown = true;
- }
-
- // find all activated controls, whether the scripts are interested in them or not
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_FWD;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_BACK;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_UP;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_DOWN;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_LEFT;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_RIGHT;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
- {
- allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
- }
- if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
- {
- allflags |= ScriptControlled.CONTROL_ROT_LEFT;
- }
- // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
- if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
- {
- lock (scriptedcontrols)
- {
- foreach (KeyValuePair kvp in scriptedcontrols)
- {
- UUID scriptUUID = kvp.Key;
- ScriptControllers scriptControlData = kvp.Value;
-
- ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
- ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
- ScriptControlled localChange = localHeld ^ localLast; // the changed bits
- if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
- {
- // only send if still pressed or just changed
- m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange);
- }
- }
- }
- }
-
- LastCommands = allflags;
- }
-
- internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored)
- {
- if (ignored == ScriptControlled.CONTROL_ZERO)
- return flags;
-
- if ((ignored & ScriptControlled.CONTROL_BACK) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
- if ((ignored & ScriptControlled.CONTROL_FWD) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS);
- if ((ignored & ScriptControlled.CONTROL_DOWN) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG);
- if ((ignored & ScriptControlled.CONTROL_UP) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS);
- if ((ignored & ScriptControlled.CONTROL_LEFT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
- if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG);
- if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG);
- if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS);
- if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN);
- if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0)
- flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN);
-
- //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
- //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
- //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
- //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
- //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
- //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
- //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
-
- return flags;
- }
-
- ///
- /// RezAttachments. This should only be called upon login on the first region.
- /// Attachment rezzings on crossings and TPs are done in a different way.
- ///
- public void RezAttachments()
- {
- if (null == m_appearance)
- {
- m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
- return;
- }
-
- XmlDocument doc = new XmlDocument();
- string stateData = String.Empty;
-
- IAttachmentsService attServ = m_scene.RequestModuleInterface();
- if (attServ != null)
- {
- m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
- stateData = attServ.Get(ControllingClient.AgentId.ToString());
- if (stateData != String.Empty)
- {
- try
- {
- doc.LoadXml(stateData);
- }
- catch { }
- }
- }
-
- Dictionary itemData = new Dictionary();
-
- XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
- if (nodes.Count > 0)
- {
- foreach (XmlNode n in nodes)
- {
- XmlElement elem = (XmlElement)n;
- string itemID = elem.GetAttribute("ItemID");
- string xml = elem.InnerXml;
-
- itemData[new UUID(itemID)] = xml;
- }
- }
-
- List attPoints = m_appearance.GetAttachedPoints();
- foreach (int p in attPoints)
- {
- if (m_isDeleted)
- return;
-
- UUID itemID = m_appearance.GetAttachedItem(p);
- UUID assetID = m_appearance.GetAttachedAsset(p);
-
- // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
- // But they're not used anyway, the item is being looked up for now, so let's proceed.
- //if (UUID.Zero == assetID)
- //{
- // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID);
- // continue;
- //}
-
- try
- {
- string xmlData;
- XmlDocument d = new XmlDocument();
- UUID asset;
- if (itemData.TryGetValue(itemID, out xmlData))
- {
- d.LoadXml(xmlData);
- m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
-
- // Rez from inventory
- asset
- = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
-
- }
- else
- {
- // Rez from inventory (with a null doc to let
- // CHANGED_OWNER happen)
- asset
- = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
- }
-
- m_log.InfoFormat(
- "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
- p, itemID, assetID, asset);
- }
- catch (Exception e)
- {
- m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString());
- }
- }
- }
-
- private void ReprioritizeUpdates()
- {
- if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time)
- {
- lock (m_reprioritization_timer)
- {
- if (!m_reprioritizing)
- m_reprioritization_timer.Enabled = m_reprioritizing = true;
- else
- m_reprioritization_called = true;
- }
- }
- }
-
- private void Reprioritize(object sender, ElapsedEventArgs e)
- {
- m_controllingClient.ReprioritizeUpdates();
-
- lock (m_reprioritization_timer)
- {
- m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called;
- m_reprioritization_called = false;
- }
- }
-
- private Vector3 Quat2Euler(Quaternion rot){
- float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
- (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
- float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
- float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
- (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
- return(new Vector3(x,y,z));
- }
-
-
- }
-}
+/*
+ * Copyright (c) Contributors, http://opensimulator.org/
+ * See CONTRIBUTORS.TXT for a full list of copyright holders.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * * Neither the name of the OpenSimulator Project nor the
+ * names of its contributors may be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
+ * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+using System;
+using System.Xml;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Timers;
+using OpenMetaverse;
+using log4net;
+using OpenSim.Framework;
+using OpenSim.Framework.Client;
+using OpenSim.Region.Framework.Interfaces;
+using OpenSim.Region.Framework.Scenes.Animation;
+using OpenSim.Region.Framework.Scenes.Types;
+using OpenSim.Region.Physics.Manager;
+using GridRegion = OpenSim.Services.Interfaces.GridRegion;
+using OpenSim.Services.Interfaces;
+
+namespace OpenSim.Region.Framework.Scenes
+{
+ enum ScriptControlled : uint
+ {
+ CONTROL_ZERO = 0,
+ CONTROL_FWD = 1,
+ CONTROL_BACK = 2,
+ CONTROL_LEFT = 4,
+ CONTROL_RIGHT = 8,
+ CONTROL_UP = 16,
+ CONTROL_DOWN = 32,
+ CONTROL_ROT_LEFT = 256,
+ CONTROL_ROT_RIGHT = 512,
+ CONTROL_LBUTTON = 268435456,
+ CONTROL_ML_LBUTTON = 1073741824
+ }
+
+ struct ScriptControllers
+ {
+ public UUID itemID;
+ public ScriptControlled ignoreControls;
+ public ScriptControlled eventControls;
+ }
+
+ public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs);
+
+ public class ScenePresence : EntityBase, ISceneEntity
+ {
+// ~ScenePresence()
+// {
+// m_log.Debug("[ScenePresence] Destructor called");
+// }
+
+ private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+
+ private static readonly byte[] BAKE_INDICES = new byte[] { 8, 9, 10, 11, 19, 20 };
+// private static readonly byte[] DEFAULT_TEXTURE = AvatarAppearance.GetDefaultTexture().GetBytes();
+ private static readonly Array DIR_CONTROL_FLAGS = Enum.GetValues(typeof(Dir_ControlFlags));
+ private static readonly Vector3 HEAD_ADJUSTMENT = new Vector3(0f, 0f, 0.3f);
+
+ ///
+ /// Experimentally determined "fudge factor" to make sit-target positions
+ /// the same as in SecondLife. Fudge factor was tested for 36 different
+ /// test cases including prims of type box, sphere, cylinder, and torus,
+ /// with varying parameters for sit target location, prim size, prim
+ /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis
+ /// issue #1716
+ ///
+// private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.1f, 0.0f, 0.3f);
+ // Value revised by KF 091121 by comparison with SL.
+ private static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f);
+
+ public UUID currentParcelUUID = UUID.Zero;
+
+ private ISceneViewer m_sceneViewer;
+
+ ///
+ /// The animator for this avatar
+ ///
+ public ScenePresenceAnimator Animator
+ {
+ get { return m_animator; }
+ }
+ protected ScenePresenceAnimator m_animator;
+
+ ///
+ /// The scene objects attached to this avatar. Do not change this list directly - use methods such as
+ /// AddAttachment() and RemoveAttachment(). Lock this list when performing any read operations upon it.
+ ///
+ public List Attachments
+ {
+ get { return m_attachments; }
+ }
+ protected List m_attachments = new List();
+
+ private Dictionary scriptedcontrols = new Dictionary();
+ private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
+ private bool MouseDown = false;
+ private SceneObjectGroup proxyObjectGroup;
+ //private SceneObjectPart proxyObjectPart = null;
+ public Vector3 lastKnownAllowedPosition;
+ public bool sentMessageAboutRestrictedParcelFlyingDown;
+ public Vector4 CollisionPlane = Vector4.UnitW;
+
+ private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
+ private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
+ private Vector3 m_lastPosition;
+ private Vector3 m_lastWorldPosition;
+ private Quaternion m_lastRotation;
+ private Vector3 m_lastVelocity;
+ //private int m_lastTerseSent;
+
+ private bool m_updateflag;
+ private byte m_movementflag;
+ private Vector3? m_forceToApply;
+ private uint m_requestedSitTargetID;
+ private UUID m_requestedSitTargetUUID;
+ public bool SitGround = false;
+
+ private SendCourseLocationsMethod m_sendCourseLocationsMethod;
+
+ private bool m_startAnimationSet;
+
+ //private Vector3 m_requestedSitOffset = new Vector3();
+
+ private Vector3 m_LastFinitePos;
+
+ private float m_sitAvatarHeight = 2.0f;
+
+ private int m_godLevel;
+ private int m_userLevel;
+
+ private bool m_invulnerable = true;
+
+ private Vector3 m_lastChildAgentUpdatePosition;
+ private Vector3 m_lastChildAgentUpdateCamPosition;
+
+ private int m_perfMonMS;
+
+ private bool m_setAlwaysRun;
+ private bool m_forceFly;
+ private bool m_flyDisabled;
+
+ private float m_speedModifier = 1.0f;
+
+ private Quaternion m_bodyRot= Quaternion.Identity;
+
+ private Quaternion m_bodyRotPrevious = Quaternion.Identity;
+
+ private const int LAND_VELOCITYMAG_MAX = 12;
+
+ public bool IsRestrictedToRegion;
+
+ public string JID = String.Empty;
+
+ private float m_health = 100f;
+
+ // Default AV Height
+ private float m_avHeight = 127.0f;
+
+ protected RegionInfo m_regionInfo;
+ protected ulong crossingFromRegion;
+
+ private readonly Vector3[] Dir_Vectors = new Vector3[11];
+ private bool m_isNudging = false;
+
+ // Position of agent's camera in world (region cordinates)
+ protected Vector3 m_CameraCenter;
+ protected Vector3 m_lastCameraCenter;
+
+ protected Timer m_reprioritization_timer;
+ protected bool m_reprioritizing;
+ protected bool m_reprioritization_called;
+
+ // Use these three vectors to figure out what the agent is looking at
+ // Convert it to a Matrix and/or Quaternion
+ protected Vector3 m_CameraAtAxis;
+ protected Vector3 m_CameraLeftAxis;
+ protected Vector3 m_CameraUpAxis;
+ private AgentManager.ControlFlags m_AgentControlFlags;
+ private Quaternion m_headrotation = Quaternion.Identity;
+ private byte m_state;
+
+ //Reuse the Vector3 instead of creating a new one on the UpdateMovement method
+// private Vector3 movementvector;
+
+ private bool m_autopilotMoving;
+ private Vector3 m_autoPilotTarget;
+ private bool m_sitAtAutoTarget;
+ private Vector3 m_initialSitTarget = Vector3.Zero; //KF: First estimate of where to sit
+
+ private string m_nextSitAnimation = String.Empty;
+
+ //PauPaw:Proper PID Controler for autopilot************
+ private bool m_moveToPositionInProgress;
+ private Vector3 m_moveToPositionTarget;
+ private Quaternion m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+
+ private bool m_followCamAuto;
+
+ private int m_movementUpdateCount;
+ private int m_lastColCount = -1; //KF: Look for Collision chnages
+ private int m_updateCount = 0; //KF: Update Anims for a while
+ private static readonly int UPDATE_COUNT = 10; // how many frames to update for
+ private const int NumMovementsBetweenRayCast = 5;
+ private List m_lastColliders = new List();
+
+ private bool CameraConstraintActive;
+ //private int m_moveToPositionStateStatus;
+ //*****************************************************
+
+ // Agent's Draw distance.
+ protected float m_DrawDistance;
+
+ protected AvatarAppearance m_appearance;
+
+ // neighbouring regions we have enabled a child agent in
+ // holds the seed cap for the child agent in that region
+ private Dictionary m_knownChildRegions = new Dictionary();
+
+ ///
+ /// Implemented Control Flags
+ ///
+ private enum Dir_ControlFlags
+ {
+ DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
+ DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
+ DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
+ DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
+ DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
+ DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
+ DIR_CONTROL_FLAG_FORWARD_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS,
+ DIR_CONTROL_FLAG_BACK_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG,
+ DIR_CONTROL_FLAG_LEFT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS,
+ DIR_CONTROL_FLAG_RIGHT_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG,
+ DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
+ }
+
+ ///
+ /// Position at which a significant movement was made
+ ///
+ private Vector3 posLastSignificantMove;
+
+ // For teleports and crossings callbacks
+ string m_callbackURI;
+ UUID m_originRegionID;
+
+ ulong m_rootRegionHandle;
+
+ ///
+ /// Script engines present in the scene
+ ///
+ private IScriptModule[] m_scriptEngines;
+
+ #region Properties
+
+ ///
+ /// Physical scene representation of this Avatar.
+ ///
+ public PhysicsActor PhysicsActor
+ {
+ set { m_physicsActor = value; }
+ get { return m_physicsActor; }
+ }
+
+ public byte MovementFlag
+ {
+ set { m_movementflag = value; }
+ get { return m_movementflag; }
+ }
+
+ public bool Updated
+ {
+ set { m_updateflag = value; }
+ get { return m_updateflag; }
+ }
+
+ public bool Invulnerable
+ {
+ set { m_invulnerable = value; }
+ get { return m_invulnerable; }
+ }
+
+ public int UserLevel
+ {
+ get { return m_userLevel; }
+ }
+
+ public int GodLevel
+ {
+ get { return m_godLevel; }
+ }
+
+ public ulong RegionHandle
+ {
+ get { return m_rootRegionHandle; }
+ }
+
+ public Vector3 CameraPosition
+ {
+ get { return m_CameraCenter; }
+ }
+
+ public Quaternion CameraRotation
+ {
+ get { return Util.Axes2Rot(m_CameraAtAxis, m_CameraLeftAxis, m_CameraUpAxis); }
+ }
+
+ public Vector3 CameraAtAxis
+ {
+ get { return m_CameraAtAxis; }
+ }
+
+ public Vector3 CameraLeftAxis
+ {
+ get { return m_CameraLeftAxis; }
+ }
+
+ public Vector3 CameraUpAxis
+ {
+ get { return m_CameraUpAxis; }
+ }
+
+ public Vector3 Lookat
+ {
+ get
+ {
+ Vector3 a = new Vector3(m_CameraAtAxis.X, m_CameraAtAxis.Y, 0);
+
+ if (a == Vector3.Zero)
+ return a;
+
+ return Util.GetNormalizedVector(a);
+ }
+ }
+
+ private readonly string m_firstname;
+
+ public string Firstname
+ {
+ get { return m_firstname; }
+ }
+
+ private readonly string m_lastname;
+
+ public string Lastname
+ {
+ get { return m_lastname; }
+ }
+
+ private string m_grouptitle;
+
+ public string Grouptitle
+ {
+ get { return m_grouptitle; }
+ set { m_grouptitle = value; }
+ }
+
+ public float DrawDistance
+ {
+ get { return m_DrawDistance; }
+ }
+
+ protected bool m_allowMovement = true;
+
+ public bool AllowMovement
+ {
+ get { return m_allowMovement; }
+ set { m_allowMovement = value; }
+ }
+
+ public bool SetAlwaysRun
+ {
+ get
+ {
+ if (PhysicsActor != null)
+ {
+ return PhysicsActor.SetAlwaysRun;
+ }
+ else
+ {
+ return m_setAlwaysRun;
+ }
+ }
+ set
+ {
+ m_setAlwaysRun = value;
+ if (PhysicsActor != null)
+ {
+ PhysicsActor.SetAlwaysRun = value;
+ }
+ }
+ }
+
+ public byte State
+ {
+ get { return m_state; }
+ set { m_state = value; }
+ }
+
+ public uint AgentControlFlags
+ {
+ get { return (uint)m_AgentControlFlags; }
+ set { m_AgentControlFlags = (AgentManager.ControlFlags)value; }
+ }
+
+ ///
+ /// This works out to be the ClientView object associated with this avatar, or it's client connection manager
+ ///
+ private IClientAPI m_controllingClient;
+
+ protected PhysicsActor m_physicsActor;
+
+ ///
+ /// The client controlling this presence
+ ///
+ public IClientAPI ControllingClient
+ {
+ get { return m_controllingClient; }
+ }
+
+ public IClientCore ClientView
+ {
+ get { return (IClientCore) m_controllingClient; }
+ }
+
+ protected Vector3 m_parentPosition;
+ public Vector3 ParentPosition
+ {
+ get { return m_parentPosition; }
+ set { m_parentPosition = value; }
+ }
+
+ ///
+ /// Position of this avatar relative to the region the avatar is in
+ ///
+ public override Vector3 AbsolutePosition
+ {
+ get
+ {
+ PhysicsActor actor = m_physicsActor;
+// if (actor != null)
+ if ((actor != null) && (m_parentID == 0)) // KF Do NOT update m_pos here if Av is sitting!
+ m_pos = actor.Position;
+
+ // If we're sitting, we need to update our position
+ if (m_parentID != 0)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_parentID);
+ if (part != null)
+ m_parentPosition = part.AbsolutePosition;
+ }
+
+ return m_parentPosition + m_pos;
+ }
+ set
+ {
+ PhysicsActor actor = m_physicsActor;
+ if (actor != null)
+ {
+ try
+ {
+ lock (m_scene.SyncRoot)
+ m_physicsActor.Position = value;
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[SCENEPRESENCE]: ABSOLUTE POSITION " + e.Message);
+ }
+ }
+
+ if (m_parentID == 0) // KF Do NOT update m_pos here if Av is sitting!
+ m_pos = value;
+ m_parentPosition = Vector3.Zero;
+ }
+ }
+
+ public Vector3 OffsetPosition
+ {
+ get { return m_pos; }
+ set { m_pos = value; }
+ }
+
+ ///
+ /// Current velocity of the avatar.
+ ///
+ public override Vector3 Velocity
+ {
+ get
+ {
+ PhysicsActor actor = m_physicsActor;
+ if (actor != null)
+ m_velocity = actor.Velocity;
+
+ return m_velocity;
+ }
+ set
+ {
+ PhysicsActor actor = m_physicsActor;
+ if (actor != null)
+ {
+ try
+ {
+ lock (m_scene.SyncRoot)
+ actor.Velocity = value;
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[SCENEPRESENCE]: VELOCITY " + e.Message);
+ }
+ }
+
+ m_velocity = value;
+ }
+ }
+
+ public Quaternion OffsetRotation
+ {
+ get { return m_offsetRotation; }
+ set { m_offsetRotation = value; }
+ }
+
+ public Quaternion Rotation
+ {
+ get {
+ if (m_parentID != 0)
+ {
+ if (m_offsetRotation != null)
+ {
+ return m_offsetRotation;
+ }
+ else
+ {
+ return new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+
+ }
+ else
+ {
+ return m_bodyRot;
+ }
+ }
+ set {
+ m_bodyRot = value;
+ if (m_parentID != 0)
+ {
+ m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ }
+ }
+
+ public Quaternion PreviousRotation
+ {
+ get { return m_bodyRotPrevious; }
+ set { m_bodyRotPrevious = value; }
+ }
+
+ ///
+ /// If this is true, agent doesn't have a representation in this scene.
+ /// this is an agent 'looking into' this scene from a nearby scene(region)
+ ///
+ /// if False, this agent has a representation in this scene
+ ///
+ private bool m_isChildAgent = true;
+
+ public bool IsChildAgent
+ {
+ get { return m_isChildAgent; }
+ set { m_isChildAgent = value; }
+ }
+
+ private uint m_parentID;
+
+
+ private UUID m_linkedPrim;
+
+ public uint ParentID
+ {
+ get { return m_parentID; }
+ set { m_parentID = value; }
+ }
+
+ public UUID LinkedPrim
+ {
+ get { return m_linkedPrim; }
+ set { m_linkedPrim = value; }
+ }
+
+ public float Health
+ {
+ get { return m_health; }
+ set { m_health = value; }
+ }
+
+ ///
+ /// These are the region handles known by the avatar.
+ ///
+ public List KnownChildRegionHandles
+ {
+ get
+ {
+ if (m_knownChildRegions.Count == 0)
+ return new List();
+ else
+ return new List(m_knownChildRegions.Keys);
+ }
+ }
+
+ public Dictionary KnownRegions
+ {
+ get { return m_knownChildRegions; }
+ set
+ {
+ m_knownChildRegions = value;
+ }
+ }
+
+ public ISceneViewer SceneViewer
+ {
+ get { return m_sceneViewer; }
+ }
+
+ public void AdjustKnownSeeds()
+ {
+ Dictionary seeds;
+
+ if (Scene.CapsModule != null)
+ seeds = Scene.CapsModule.GetChildrenSeeds(UUID);
+ else
+ seeds = new Dictionary();
+
+ List old = new List();
+ foreach (ulong handle in seeds.Keys)
+ {
+ uint x, y;
+ Utils.LongToUInts(handle, out x, out y);
+ x = x / Constants.RegionSize;
+ y = y / Constants.RegionSize;
+ if (Util.IsOutsideView(x, Scene.RegionInfo.RegionLocX, y, Scene.RegionInfo.RegionLocY))
+ {
+ old.Add(handle);
+ }
+ }
+ DropOldNeighbours(old);
+
+ if (Scene.CapsModule != null)
+ Scene.CapsModule.SetChildrenSeed(UUID, seeds);
+
+ KnownRegions = seeds;
+ //m_log.Debug(" ++++++++++AFTER+++++++++++++ ");
+ //DumpKnownRegions();
+ }
+
+ public void DumpKnownRegions()
+ {
+ m_log.Info("================ KnownRegions "+Scene.RegionInfo.RegionName+" ================");
+ foreach (KeyValuePair kvp in KnownRegions)
+ {
+ uint x, y;
+ Utils.LongToUInts(kvp.Key, out x, out y);
+ x = x / Constants.RegionSize;
+ y = y / Constants.RegionSize;
+ m_log.Info(" >> "+x+", "+y+": "+kvp.Value);
+ }
+ }
+
+ private bool m_inTransit;
+ private bool m_mouseLook;
+ private bool m_leftButtonDown;
+
+ public bool IsInTransit
+ {
+ get { return m_inTransit; }
+ set { m_inTransit = value; }
+ }
+
+ public float SpeedModifier
+ {
+ get { return m_speedModifier; }
+ set { m_speedModifier = value; }
+ }
+
+ public bool ForceFly
+ {
+ get { return m_forceFly; }
+ set { m_forceFly = value; }
+ }
+
+ public bool FlyDisabled
+ {
+ get { return m_flyDisabled; }
+ set { m_flyDisabled = value; }
+ }
+
+ public string Viewer
+ {
+ get { return m_scene.AuthenticateHandler.GetAgentCircuitData(ControllingClient.CircuitCode).Viewer; }
+ }
+
+ #endregion
+
+ #region Constructor(s)
+
+ public ScenePresence()
+ {
+ m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
+ CreateSceneViewer();
+ m_animator = new ScenePresenceAnimator(this);
+ }
+
+ private ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo) : this()
+ {
+ m_rootRegionHandle = reginfo.RegionHandle;
+ m_controllingClient = client;
+ m_firstname = m_controllingClient.FirstName;
+ m_lastname = m_controllingClient.LastName;
+ m_name = String.Format("{0} {1}", m_firstname, m_lastname);
+ m_scene = world;
+ m_uuid = client.AgentId;
+ m_regionInfo = reginfo;
+ m_localId = m_scene.AllocateLocalId();
+
+ UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
+
+ if (account != null)
+ m_userLevel = account.UserLevel;
+
+ IGroupsModule gm = m_scene.RequestModuleInterface();
+ if (gm != null)
+ m_grouptitle = gm.GetGroupTitle(m_uuid);
+
+ m_scriptEngines = m_scene.RequestModuleInterfaces();
+
+ AbsolutePosition = posLastSignificantMove = m_CameraCenter =
+ m_lastCameraCenter = m_controllingClient.StartPos;
+
+ m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
+ m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
+ m_reprioritization_timer.AutoReset = false;
+
+ AdjustKnownSeeds();
+ Animator.TrySetMovementAnimation("STAND");
+ // we created a new ScenePresence (a new child agent) in a fresh region.
+ // Request info about all the (root) agents in this region
+ // Note: This won't send data *to* other clients in that region (children don't send)
+ SendInitialFullUpdateToAllClients();
+ RegisterToEvents();
+ if (m_controllingClient != null)
+ {
+ m_controllingClient.ProcessPendingPackets();
+ }
+ SetDirectionVectors();
+ }
+
+ public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, byte[] visualParams,
+ AvatarWearable[] wearables)
+ : this(client, world, reginfo)
+ {
+ m_appearance = new AvatarAppearance(m_uuid, wearables, visualParams);
+ }
+
+ public ScenePresence(IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance)
+ : this(client, world, reginfo)
+ {
+ m_appearance = appearance;
+ }
+
+ private void CreateSceneViewer()
+ {
+ m_sceneViewer = new SceneViewer(this);
+ }
+
+ public void RegisterToEvents()
+ {
+ m_controllingClient.OnRequestWearables += SendWearables;
+ m_controllingClient.OnSetAppearance += SetAppearance;
+ m_controllingClient.OnCompleteMovementToRegion += CompleteMovement;
+ //m_controllingClient.OnCompleteMovementToRegion += SendInitialData;
+ m_controllingClient.OnAgentUpdate += HandleAgentUpdate;
+ m_controllingClient.OnAgentRequestSit += HandleAgentRequestSit;
+ m_controllingClient.OnAgentSit += HandleAgentSit;
+ m_controllingClient.OnSetAlwaysRun += HandleSetAlwaysRun;
+ m_controllingClient.OnStartAnim += HandleStartAnim;
+ m_controllingClient.OnStopAnim += HandleStopAnim;
+ m_controllingClient.OnForceReleaseControls += HandleForceReleaseControls;
+ m_controllingClient.OnAutoPilotGo += DoAutoPilot;
+ m_controllingClient.AddGenericPacketHandler("autopilot", DoMoveToPosition);
+
+ // ControllingClient.OnChildAgentStatus += new StatusChange(this.ChildStatusChange);
+ // ControllingClient.OnStopMovement += new GenericCall2(this.StopMovement);
+ }
+
+ private void SetDirectionVectors()
+ {
+ Dir_Vectors[0] = Vector3.UnitX; //FORWARD
+ Dir_Vectors[1] = -Vector3.UnitX; //BACK
+ Dir_Vectors[2] = Vector3.UnitY; //LEFT
+ Dir_Vectors[3] = -Vector3.UnitY; //RIGHT
+ Dir_Vectors[4] = Vector3.UnitZ; //UP
+ Dir_Vectors[5] = -Vector3.UnitZ; //DOWN
+ Dir_Vectors[6] = new Vector3(0.5f, 0f, 0f); //FORWARD_NUDGE
+ Dir_Vectors[7] = new Vector3(-0.5f, 0f, 0f); //BACK_NUDGE
+ Dir_Vectors[8] = new Vector3(0f, 0.5f, 0f); //LEFT_NUDGE
+ Dir_Vectors[9] = new Vector3(0f, -0.5f, 0f); //RIGHT_NUDGE
+ Dir_Vectors[10] = new Vector3(0f, 0f, -0.5f); //DOWN_Nudge
+ }
+
+ private Vector3[] GetWalkDirectionVectors()
+ {
+ Vector3[] vector = new Vector3[11];
+ vector[0] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD
+ vector[1] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK
+ vector[2] = Vector3.UnitY; //LEFT
+ vector[3] = -Vector3.UnitY; //RIGHT
+ vector[4] = new Vector3(m_CameraAtAxis.Z, 0f, m_CameraUpAxis.Z); //UP
+ vector[5] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN
+ vector[6] = new Vector3(m_CameraUpAxis.Z, 0f, -m_CameraAtAxis.Z); //FORWARD_NUDGE
+ vector[7] = new Vector3(-m_CameraUpAxis.Z, 0f, m_CameraAtAxis.Z); //BACK_NUDGE
+ vector[8] = Vector3.UnitY; //LEFT_NUDGE
+ vector[9] = -Vector3.UnitY; //RIGHT_NUDGE
+ vector[10] = new Vector3(-m_CameraAtAxis.Z, 0f, -m_CameraUpAxis.Z); //DOWN_NUDGE
+ return vector;
+ }
+
+ private bool[] GetDirectionIsNudge()
+ {
+ bool[] isNudge = new bool[11];
+ isNudge[0] = false; //FORWARD
+ isNudge[1] = false; //BACK
+ isNudge[2] = false; //LEFT
+ isNudge[3] = false; //RIGHT
+ isNudge[4] = false; //UP
+ isNudge[5] = false; //DOWN
+ isNudge[6] = true; //FORWARD_NUDGE
+ isNudge[7] = true; //BACK_NUDGE
+ isNudge[8] = true; //LEFT_NUDGE
+ isNudge[9] = true; //RIGHT_NUDGE
+ isNudge[10] = true; //DOWN_Nudge
+ return isNudge;
+ }
+
+
+ #endregion
+
+ public uint GenerateClientFlags(UUID ObjectID)
+ {
+ return m_scene.Permissions.GenerateClientFlags(m_uuid, ObjectID);
+ }
+
+ ///
+ /// Send updates to the client about prims which have been placed on the update queue. We don't
+ /// necessarily send updates for all the parts on the queue, e.g. if an updates with a more recent
+ /// timestamp has already been sent.
+ ///
+ public void SendPrimUpdates()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ m_sceneViewer.SendPrimUpdates();
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ #region Status Methods
+
+ ///
+ /// This turns a child agent, into a root agent
+ /// This is called when an agent teleports into a region, or if an
+ /// agent crosses into this region from a neighbor over the border
+ ///
+ public void MakeRootAgent(Vector3 pos, bool isFlying)
+ {
+ m_log.DebugFormat(
+ "[SCENE]: Upgrading child to root agent for {0} in {1}",
+ Name, m_scene.RegionInfo.RegionName);
+
+ //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count);
+
+ IGroupsModule gm = m_scene.RequestModuleInterface();
+ if (gm != null)
+ m_grouptitle = gm.GetGroupTitle(m_uuid);
+
+ m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
+ m_scene.SetRootAgentScene(m_uuid);
+
+ // Moved this from SendInitialData to ensure that m_appearance is initialized
+ // before the inventory is processed in MakeRootAgent. This fixes a race condition
+ // related to the handling of attachments
+ //m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
+ if (m_scene.TestBorderCross(pos, Cardinals.E))
+ {
+ Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E);
+ pos.X = crossedBorder.BorderLine.Z - 1;
+ }
+
+ if (m_scene.TestBorderCross(pos, Cardinals.N))
+ {
+ Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
+ pos.Y = crossedBorder.BorderLine.Z - 1;
+ }
+
+ //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
+ //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
+ //they'll bypass the landing point. But I can't think of any decent way of fixing this.
+ if (KnownChildRegionHandles.Count == 0)
+ {
+ ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
+ if (land != null)
+ {
+ //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && UserLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ {
+ pos = land.LandData.UserLocation;
+ }
+ }
+ }
+
+ if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
+ {
+ Vector3 emergencyPos = new Vector3(((int)Constants.RegionSize * 0.5f), ((int)Constants.RegionSize * 0.5f), 128);
+
+ if (pos.X < 0)
+ {
+ emergencyPos.X = (int)Constants.RegionSize + pos.X;
+ if (!(pos.Y < 0))
+ emergencyPos.Y = pos.Y;
+ if (!(pos.Z < 0))
+ emergencyPos.Z = pos.Z;
+ }
+ if (pos.Y < 0)
+ {
+ emergencyPos.Y = (int)Constants.RegionSize + pos.Y;
+ if (!(pos.X < 0))
+ emergencyPos.X = pos.X;
+ if (!(pos.Z < 0))
+ emergencyPos.Z = pos.Z;
+ }
+ if (pos.Z < 0)
+ {
+ emergencyPos.Z = 128;
+ if (!(pos.Y < 0))
+ emergencyPos.Y = pos.Y;
+ if (!(pos.X < 0))
+ emergencyPos.X = pos.X;
+ }
+ }
+
+ if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f)
+ {
+ m_log.WarnFormat(
+ "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping",
+ pos, Name, UUID);
+
+ if (pos.X < 0f) pos.X = 0f;
+ if (pos.Y < 0f) pos.Y = 0f;
+ if (pos.Z < 0f) pos.Z = 0f;
+ }
+
+ float localAVHeight = 1.56f;
+ if (m_avHeight != 127.0f)
+ {
+ localAVHeight = m_avHeight;
+ }
+
+ float posZLimit = 0;
+
+ if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize)
+ posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y];
+
+ float newPosZ = posZLimit + localAVHeight / 2;
+ if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ)))
+ {
+ pos.Z = newPosZ;
+ }
+ AbsolutePosition = pos;
+
+ AddToPhysicalScene(isFlying);
+
+ if (m_forceFly)
+ {
+ m_physicsActor.Flying = true;
+ }
+ else if (m_flyDisabled)
+ {
+ m_physicsActor.Flying = false;
+ }
+
+ if (m_appearance != null)
+ {
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+ }
+ else
+ {
+ m_log.ErrorFormat("[SCENE PRESENCE]: null appearance in MakeRoot in {0}", Scene.RegionInfo.RegionName);
+ // emergency; this really shouldn't happen
+ m_appearance = new AvatarAppearance(UUID);
+ }
+
+ // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying
+ // avatar to return to the standing position in mid-air. On login it looks like this is being sent
+ // elsewhere anyway
+ // Animator.SendAnimPack();
+
+ m_scene.SwapRootAgentCount(false);
+
+ //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(m_uuid);
+ //if (userInfo != null)
+ // userInfo.FetchInventory();
+ //else
+ // m_log.ErrorFormat("[SCENE]: Could not find user info for {0} when making it a root agent", m_uuid);
+
+ // On the next prim update, all objects will be sent
+ //
+ m_sceneViewer.Reset();
+
+ m_isChildAgent = false;
+
+ // send the animations of the other presences to me
+ m_scene.ForEachScenePresence(delegate(ScenePresence presence)
+ {
+ if (presence != this)
+ presence.Animator.SendAnimPackToClient(ControllingClient);
+ });
+
+ m_scene.EventManager.TriggerOnMakeRootAgent(this);
+ }
+
+ ///
+ /// This turns a root agent into a child agent
+ /// when an agent departs this region for a neighbor, this gets called.
+ ///
+ /// It doesn't get called for a teleport. Reason being, an agent that
+ /// teleports out may not end up anywhere near this region
+ ///
+ public void MakeChildAgent()
+ {
+ // It looks like m_animator is set to null somewhere, and MakeChild
+ // is called after that. Probably in aborted teleports.
+ if (m_animator == null)
+ m_animator = new ScenePresenceAnimator(this);
+ else
+ Animator.ResetAnimations();
+
+// m_log.DebugFormat(
+// "[SCENEPRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}",
+// Name, UUID, m_scene.RegionInfo.RegionName);
+
+ // Don't zero out the velocity since this can cause problems when an avatar is making a region crossing,
+ // depending on the exact timing. This shouldn't matter anyway since child agent positions are not updated.
+ //Velocity = new Vector3(0, 0, 0);
+
+ m_isChildAgent = true;
+ m_scene.SwapRootAgentCount(true);
+ RemoveFromPhysicalScene();
+
+ // FIXME: Set m_rootRegionHandle to the region handle of the scene this agent is moving into
+
+ m_scene.EventManager.TriggerOnMakeChildAgent(this);
+ }
+
+ ///
+ /// Removes physics plugin scene representation of this agent if it exists.
+ ///
+ private void RemoveFromPhysicalScene()
+ {
+ if (PhysicsActor != null)
+ {
+ m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
+ m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
+ m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
+ m_physicsActor.UnSubscribeEvents();
+ m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
+ PhysicsActor = null;
+ }
+ }
+
+ ///
+ ///
+ ///
+ ///
+ public void Teleport(Vector3 pos)
+ {
+ bool isFlying = false;
+
+ if (m_physicsActor != null)
+ isFlying = m_physicsActor.Flying;
+
+ RemoveFromPhysicalScene();
+ Velocity = Vector3.Zero;
+ AbsolutePosition = pos;
+ AddToPhysicalScene(isFlying);
+ if (m_appearance != null)
+ {
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+ }
+
+ SendTerseUpdateToAllClients();
+
+ }
+
+ public void TeleportWithMomentum(Vector3 pos)
+ {
+ bool isFlying = false;
+ if (m_physicsActor != null)
+ isFlying = m_physicsActor.Flying;
+
+ RemoveFromPhysicalScene();
+ AbsolutePosition = pos;
+ AddToPhysicalScene(isFlying);
+ if (m_appearance != null)
+ {
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+ }
+
+ SendTerseUpdateToAllClients();
+ }
+
+ ///
+ ///
+ ///
+ public void StopMovement()
+ {
+ }
+
+ public void StopFlying()
+ {
+ ControllingClient.StopFlying(this);
+ }
+
+ public void AddNeighbourRegion(ulong regionHandle, string cap)
+ {
+ lock (m_knownChildRegions)
+ {
+ if (!m_knownChildRegions.ContainsKey(regionHandle))
+ {
+ uint x, y;
+ Utils.LongToUInts(regionHandle, out x, out y);
+ m_knownChildRegions.Add(regionHandle, cap);
+ }
+ }
+ }
+
+ public void RemoveNeighbourRegion(ulong regionHandle)
+ {
+ lock (m_knownChildRegions)
+ {
+ if (m_knownChildRegions.ContainsKey(regionHandle))
+ {
+ m_knownChildRegions.Remove(regionHandle);
+ //m_log.Debug(" !!! removing known region {0} in {1}. Count = {2}", regionHandle, Scene.RegionInfo.RegionName, m_knownChildRegions.Count);
+ }
+ }
+ }
+
+ public void DropOldNeighbours(List oldRegions)
+ {
+ foreach (ulong handle in oldRegions)
+ {
+ RemoveNeighbourRegion(handle);
+ Scene.CapsModule.DropChildSeed(UUID, handle);
+ }
+ }
+
+ public List GetKnownRegionList()
+ {
+ return new List(m_knownChildRegions.Keys);
+ }
+
+ #endregion
+
+ #region Event Handlers
+
+ ///
+ /// Sets avatar height in the phyiscs plugin
+ ///
+ internal void SetHeight(float height)
+ {
+ m_avHeight = height;
+ if (PhysicsActor != null && !IsChildAgent)
+ {
+ Vector3 SetSize = new Vector3(0.45f, 0.6f, m_avHeight);
+ PhysicsActor.Size = SetSize;
+ }
+ }
+
+ ///
+ /// Complete Avatar's movement into the region.
+ /// This is called upon a very important packet sent from the client,
+ /// so it's client-controlled. Never call this method directly.
+ ///
+ public void CompleteMovement(IClientAPI client)
+ {
+ //m_log.Debug("[SCENE PRESENCE]: CompleteMovement");
+
+ Vector3 look = Velocity;
+ if ((look.X == 0) && (look.Y == 0) && (look.Z == 0))
+ {
+ look = new Vector3(0.99f, 0.042f, 0);
+ }
+
+ // Prevent teleporting to an underground location
+ // (may crash client otherwise)
+ //
+ Vector3 pos = AbsolutePosition;
+ float ground = m_scene.GetGroundHeight(pos.X, pos.Y);
+ if (pos.Z < ground + 1.5f)
+ {
+ pos.Z = ground + 1.5f;
+ AbsolutePosition = pos;
+ }
+ m_isChildAgent = false;
+ bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
+ MakeRootAgent(AbsolutePosition, m_flying);
+
+ if ((m_callbackURI != null) && !m_callbackURI.Equals(""))
+ {
+ m_log.DebugFormat("[SCENE PRESENCE]: Releasing agent in URI {0}", m_callbackURI);
+ Scene.SimulationService.ReleaseAgent(m_originRegionID, UUID, m_callbackURI);
+ m_callbackURI = null;
+ }
+
+ //m_log.DebugFormat("Completed movement");
+
+ m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
+ SendInitialData();
+
+ // Create child agents in neighbouring regions
+ if (!m_isChildAgent)
+ {
+ IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
+ if (m_agentTransfer != null)
+ m_agentTransfer.EnableChildAgents(this);
+ else
+ m_log.DebugFormat("[SCENE PRESENCE]: Unable to create child agents in neighbours, because AgentTransferModule is not active");
+
+ IFriendsModule friendsModule = m_scene.RequestModuleInterface();
+ if (friendsModule != null)
+ friendsModule.SendFriendsOnlineIfNeeded(ControllingClient);
+ }
+
+ }
+
+ ///
+ /// Callback for the Camera view block check. Gets called with the results of the camera view block test
+ /// hitYN is true when there's something in the way.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal)
+ {
+ const float POSITION_TOLERANCE = 0.02f;
+ const float VELOCITY_TOLERANCE = 0.02f;
+ const float ROTATION_TOLERANCE = 0.02f;
+
+ if (m_followCamAuto)
+ {
+ if (hitYN)
+ {
+ CameraConstraintActive = true;
+ //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance);
+
+ Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint);
+ ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint)));
+ }
+ else
+ {
+ if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) ||
+ !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
+ !m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE))
+ {
+ if (CameraConstraintActive)
+ {
+ ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f));
+ CameraConstraintActive = false;
+ }
+ }
+ }
+ }
+ }
+
+ ///
+ /// This is the event handler for client movement. If a client is moving, this event is triggering.
+ ///
+ public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
+ {
+ //if (m_isChildAgent)
+ //{
+ // // m_log.Debug("DEBUG: HandleAgentUpdate: child agent");
+ // return;
+ //}
+
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ ++m_movementUpdateCount;
+ if (m_movementUpdateCount < 1)
+ m_movementUpdateCount = 1;
+
+ #region Sanity Checking
+
+ // This is irritating. Really.
+ if (!AbsolutePosition.IsFinite())
+ {
+ RemoveFromPhysicalScene();
+ m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902");
+
+ m_pos = m_LastFinitePos;
+
+ if (!m_pos.IsFinite())
+ {
+ m_pos.X = 127f;
+ m_pos.Y = 127f;
+ m_pos.Z = 127f;
+ m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903");
+ }
+
+ AddToPhysicalScene(false);
+ }
+ else
+ {
+ m_LastFinitePos = m_pos;
+ }
+
+ #endregion Sanity Checking
+
+ #region Inputs
+
+ AgentManager.ControlFlags flags = (AgentManager.ControlFlags)agentData.ControlFlags;
+ Quaternion bodyRotation = agentData.BodyRotation;
+
+ // Camera location in world. We'll need to raytrace
+ // from this location from time to time.
+ m_CameraCenter = agentData.CameraCenter;
+ if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance)
+ {
+ ReprioritizeUpdates();
+ m_lastCameraCenter = m_CameraCenter;
+ }
+
+ // Use these three vectors to figure out what the agent is looking at
+ // Convert it to a Matrix and/or Quaternion
+ m_CameraAtAxis = agentData.CameraAtAxis;
+ m_CameraLeftAxis = agentData.CameraLeftAxis;
+ m_CameraUpAxis = agentData.CameraUpAxis;
+
+ // The Agent's Draw distance setting
+ m_DrawDistance = agentData.Far;
+
+ // Check if Client has camera in 'follow cam' or 'build' mode.
+ Vector3 camdif = (Vector3.One * m_bodyRot - Vector3.One * CameraRotation);
+
+ m_followCamAuto = ((m_CameraUpAxis.Z > 0.959f && m_CameraUpAxis.Z < 0.98f)
+ && (Math.Abs(camdif.X) < 0.4f && Math.Abs(camdif.Y) < 0.4f)) ? true : false;
+
+ m_mouseLook = (flags & AgentManager.ControlFlags.AGENT_CONTROL_MOUSELOOK) != 0;
+ m_leftButtonDown = (flags & AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0;
+
+ #endregion Inputs
+
+ if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_STAND_UP) != 0)
+ {
+ StandUp();
+ }
+
+ //m_log.DebugFormat("[FollowCam]: {0}", m_followCamAuto);
+ // Raycast from the avatar's head to the camera to see if there's anything blocking the view
+ if ((m_movementUpdateCount % NumMovementsBetweenRayCast) == 0 && m_scene.PhysicsScene.SupportsRayCast())
+ {
+ if (m_followCamAuto)
+ {
+ Vector3 posAdjusted = m_pos + HEAD_ADJUSTMENT;
+ m_scene.PhysicsScene.RaycastWorld(m_pos, Vector3.Normalize(m_CameraCenter - posAdjusted), Vector3.Distance(m_CameraCenter, posAdjusted) + 0.3f, RayCastCameraCallback);
+ }
+ }
+ lock (scriptedcontrols)
+ {
+ if (scriptedcontrols.Count > 0)
+ {
+ SendControlToScripts((uint)flags);
+ flags = RemoveIgnoredControls(flags, IgnoredControls);
+ }
+ }
+
+ if (m_autopilotMoving)
+ CheckAtSitTarget();
+
+ if ((flags & AgentManager.ControlFlags.AGENT_CONTROL_SIT_ON_GROUND) != 0)
+ {
+ m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.
+ Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
+
+ // TODO: This doesn't prevent the user from walking yet.
+ // Setting parent ID would fix this, if we knew what value
+ // to use. Or we could add a m_isSitting variable.
+ //Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED");
+ SitGround = true;
+ }
+
+ // In the future, these values might need to go global.
+ // Here's where you get them.
+ m_AgentControlFlags = flags;
+ m_headrotation = agentData.HeadRotation;
+ m_state = agentData.State;
+
+ PhysicsActor actor = PhysicsActor;
+ if (actor == null)
+ {
+ return;
+ }
+
+ bool update_movementflag = false;
+
+ if (m_allowMovement && !SitGround)
+ {
+ if (agentData.UseClientAgentPosition)
+ {
+ m_moveToPositionInProgress = (agentData.ClientAgentPosition - AbsolutePosition).Length() > 0.2f;
+ m_moveToPositionTarget = agentData.ClientAgentPosition;
+ }
+
+ int i = 0;
+
+ bool update_rotation = false;
+ bool DCFlagKeyPressed = false;
+ Vector3 agent_control_v3 = Vector3.Zero;
+ Quaternion q = bodyRotation;
+
+ bool oldflying = PhysicsActor.Flying;
+
+ if (m_forceFly)
+ actor.Flying = true;
+ else if (m_flyDisabled)
+ actor.Flying = false;
+ else
+ actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
+
+ if (actor.Flying != oldflying)
+ update_movementflag = true;
+
+ if (q != m_bodyRot)
+ {
+ m_bodyRot = q;
+ update_rotation = true;
+ }
+
+ //guilty until proven innocent..
+ bool Nudging = true;
+ //Basically, if there is at least one non-nudge control then we don't need
+ //to worry about stopping the avatar
+
+ if (m_parentID == 0)
+ {
+ bool bAllowUpdateMoveToPosition = false;
+ bool bResetMoveToPosition = false;
+
+ Vector3[] dirVectors;
+
+ // use camera up angle when in mouselook and not flying or when holding the left mouse button down and not flying
+ // this prevents 'jumping' in inappropriate situations.
+ if ((m_mouseLook && !m_physicsActor.Flying) || (m_leftButtonDown && !m_physicsActor.Flying))
+ dirVectors = GetWalkDirectionVectors();
+ else
+ dirVectors = Dir_Vectors;
+
+ bool[] isNudge = GetDirectionIsNudge();
+
+
+
+
+
+ foreach (Dir_ControlFlags DCF in DIR_CONTROL_FLAGS)
+ {
+ if (((uint)flags & (uint)DCF) != 0)
+ {
+ bResetMoveToPosition = true;
+ DCFlagKeyPressed = true;
+ try
+ {
+ agent_control_v3 += dirVectors[i];
+ if (isNudge[i] == false)
+ {
+ Nudging = false;
+ }
+ }
+ catch (IndexOutOfRangeException)
+ {
+ // Why did I get this?
+ }
+
+ if ((m_movementflag & (uint)DCF) == 0)
+ {
+ m_movementflag += (byte)(uint)DCF;
+ update_movementflag = true;
+ }
+ }
+ else
+ {
+ if ((m_movementflag & (uint)DCF) != 0)
+ {
+ m_movementflag -= (byte)(uint)DCF;
+ update_movementflag = true;
+ }
+ else
+ {
+ bAllowUpdateMoveToPosition = true;
+ }
+ }
+ i++;
+ }
+ //Paupaw:Do Proper PID for Autopilot here
+ if (bResetMoveToPosition)
+ {
+ m_moveToPositionTarget = Vector3.Zero;
+ m_moveToPositionInProgress = false;
+ update_movementflag = true;
+ bAllowUpdateMoveToPosition = false;
+ }
+
+ if (bAllowUpdateMoveToPosition && (m_moveToPositionInProgress && !m_autopilotMoving))
+ {
+ //Check the error term of the current position in relation to the target position
+ if (Util.GetDistanceTo(AbsolutePosition, m_moveToPositionTarget) <= 0.5f)
+ {
+ // we are close enough to the target
+ m_moveToPositionTarget = Vector3.Zero;
+ m_moveToPositionInProgress = false;
+ update_movementflag = true;
+ }
+ else
+ {
+ try
+ {
+ // move avatar in 2D at one meter/second towards target, in avatar coordinate frame.
+ // This movement vector gets added to the velocity through AddNewMovement().
+ // Theoretically we might need a more complex PID approach here if other
+ // unknown forces are acting on the avatar and we need to adaptively respond
+ // to such forces, but the following simple approach seems to works fine.
+ Vector3 LocalVectorToTarget3D =
+ (m_moveToPositionTarget - AbsolutePosition) // vector from cur. pos to target in global coords
+ * Matrix4.CreateFromQuaternion(Quaternion.Inverse(bodyRotation)); // change to avatar coords
+ // Ignore z component of vector
+ Vector3 LocalVectorToTarget2D = new Vector3((float)(LocalVectorToTarget3D.X), (float)(LocalVectorToTarget3D.Y), 0f);
+ LocalVectorToTarget2D.Normalize();
+
+ //We're not nudging
+ Nudging = false;
+ agent_control_v3 += LocalVectorToTarget2D;
+
+ // update avatar movement flags. the avatar coordinate system is as follows:
+ //
+ // +X (forward)
+ //
+ // ^
+ // |
+ // |
+ // |
+ // |
+ // (left) +Y <--------o--------> -Y
+ // avatar
+ // |
+ // |
+ // |
+ // |
+ // v
+ // -X
+ //
+
+ // based on the above avatar coordinate system, classify the movement into
+ // one of left/right/back/forward.
+ if (LocalVectorToTarget2D.Y > 0)//MoveLeft
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
+ //AgentControlFlags
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT;
+ update_movementflag = true;
+ }
+ else if (LocalVectorToTarget2D.Y < 0) //MoveRight
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT;
+ update_movementflag = true;
+ }
+ if (LocalVectorToTarget2D.X < 0) //MoveBack
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK;
+ update_movementflag = true;
+ }
+ else if (LocalVectorToTarget2D.X > 0) //Move Forward
+ {
+ m_movementflag += (byte)(uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
+ AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD;
+ update_movementflag = true;
+ }
+ }
+ catch (Exception e)
+ {
+ //Avoid system crash, can be slower but...
+ m_log.DebugFormat("Crash! {0}", e.ToString());
+ }
+ }
+ }
+ }
+
+ // Cause the avatar to stop flying if it's colliding
+ // with something with the down arrow pressed.
+
+ // Only do this if we're flying
+ if (m_physicsActor != null && m_physicsActor.Flying && !m_forceFly)
+ {
+ // Landing detection code
+
+ // Are the landing controls requirements filled?
+ bool controlland = (((flags & AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) ||
+ ((flags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
+
+ // Are the collision requirements fulfilled?
+ bool colliding = (m_physicsActor.IsColliding == true);
+
+ if (m_physicsActor.Flying && colliding && controlland)
+ {
+ // nesting this check because LengthSquared() is expensive and we don't
+ // want to do it every step when flying.
+ if ((Velocity.LengthSquared() <= LAND_VELOCITYMAG_MAX))
+ StopFlying();
+ }
+ }
+
+ if (update_movementflag || (update_rotation && DCFlagKeyPressed))
+ {
+ // m_log.DebugFormat("{0} {1}", update_movementflag, (update_rotation && DCFlagKeyPressed));
+ // m_log.DebugFormat(
+ // "In {0} adding velocity to {1} of {2}", m_scene.RegionInfo.RegionName, Name, agent_control_v3);
+
+ AddNewMovement(agent_control_v3, q, Nudging);
+
+
+ }
+ }
+
+ if (update_movementflag && !SitGround)
+ Animator.UpdateMovementAnimations();
+
+ m_scene.EventManager.TriggerOnClientMovement(this);
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ public void DoAutoPilot(uint not_used, Vector3 Pos, IClientAPI remote_client)
+ {
+ m_autopilotMoving = true;
+ m_autoPilotTarget = Pos;
+ m_sitAtAutoTarget = false;
+ PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
+ //proxy.PCode = (byte)PCode.ParticleSystem;
+ proxyObjectGroup = new SceneObjectGroup(UUID, Pos, Rotation, proxy);
+ proxyObjectGroup.AttachToScene(m_scene);
+
+ // Commented out this code since it could never have executed, but might still be informative.
+// if (proxyObjectGroup != null)
+// {
+ proxyObjectGroup.SendGroupFullUpdate();
+ remote_client.SendSitResponse(proxyObjectGroup.UUID, Vector3.Zero, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
+ m_scene.DeleteSceneObject(proxyObjectGroup, false);
+// }
+// else
+// {
+// m_autopilotMoving = false;
+// m_autoPilotTarget = Vector3.Zero;
+// ControllingClient.SendAlertMessage("Autopilot cancelled");
+// }
+ }
+
+ public void DoMoveToPosition(Object sender, string method, List args)
+ {
+ try
+ {
+ float locx = 0f;
+ float locy = 0f;
+ float locz = 0f;
+ uint regionX = 0;
+ uint regionY = 0;
+ try
+ {
+ Utils.LongToUInts(Scene.RegionInfo.RegionHandle, out regionX, out regionY);
+ locx = Convert.ToSingle(args[0]) - (float)regionX;
+ locy = Convert.ToSingle(args[1]) - (float)regionY;
+ locz = Convert.ToSingle(args[2]);
+ }
+ catch (InvalidCastException)
+ {
+ m_log.Error("[CLIENT]: Invalid autopilot request");
+ return;
+ }
+ m_moveToPositionInProgress = true;
+ m_moveToPositionTarget = new Vector3(locx, locy, locz);
+ }
+ catch (Exception ex)
+ {
+ //Why did I get this error?
+ m_log.Error("[SCENEPRESENCE]: DoMoveToPosition" + ex);
+ }
+ }
+
+ private void CheckAtSitTarget()
+ {
+ //m_log.Debug("[AUTOPILOT]: " + Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget).ToString());
+ if (Util.GetDistanceTo(AbsolutePosition, m_autoPilotTarget) <= 1.5)
+ {
+ if (m_sitAtAutoTarget)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ AbsolutePosition = part.AbsolutePosition;
+ Velocity = Vector3.Zero;
+ SendFullUpdateToAllClients();
+
+ HandleAgentSit(ControllingClient, m_requestedSitTargetUUID); //KF ??
+ }
+ //ControllingClient.SendSitResponse(m_requestedSitTargetID, m_requestedSitOffset, Quaternion.Identity, false, Vector3.Zero, Vector3.Zero, false);
+ m_requestedSitTargetUUID = UUID.Zero;
+ }
+ /*
+ else
+ {
+ //ControllingClient.SendAlertMessage("Autopilot cancelled");
+ //SendTerseUpdateToAllClients();
+ //PrimitiveBaseShape proxy = PrimitiveBaseShape.Default;
+ //proxy.PCode = (byte)PCode.ParticleSystem;
+ ////uint nextUUID = m_scene.NextLocalId;
+
+ //proxyObjectGroup = new SceneObjectGroup(m_scene, m_scene.RegionInfo.RegionHandle, UUID, nextUUID, m_autoPilotTarget, Quaternion.Identity, proxy);
+ //if (proxyObjectGroup != null)
+ //{
+ //proxyObjectGroup.SendGroupFullUpdate();
+ //ControllingClient.SendSitResponse(UUID.Zero, m_autoPilotTarget, Quaternion.Identity, true, Vector3.Zero, Vector3.Zero, false);
+ //m_scene.DeleteSceneObject(proxyObjectGroup);
+ //}
+ }
+ */
+ m_autoPilotTarget = Vector3.Zero;
+ m_autopilotMoving = false;
+ }
+ }
+ ///
+ /// Perform the logic necessary to stand the avatar up. This method also executes
+ /// the stand animation.
+ ///
+ public void StandUp()
+ {
+ SitGround = false;
+
+ if (m_parentID != 0)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
+ if (part != null)
+ {
+ part.TaskInventory.LockItemsForRead(true);
+ TaskInventoryDictionary taskIDict = part.TaskInventory;
+ if (taskIDict != null)
+ {
+ foreach (UUID taskID in taskIDict.Keys)
+ {
+ UnRegisterControlEventsToScript(LocalId, taskID);
+ taskIDict[taskID].PermsMask &= ~(
+ 2048 | //PERMISSION_CONTROL_CAMERA
+ 4); // PERMISSION_TAKE_CONTROLS
+ }
+ }
+ part.TaskInventory.LockItemsForRead(false);
+ // Reset sit target.
+ if (part.GetAvatarOnSitTarget() == UUID)
+ part.SetAvatarOnSitTarget(UUID.Zero);
+ m_parentPosition = part.GetWorldPosition();
+ ControllingClient.SendClearFollowCamProperties(part.ParentUUID);
+ }
+ // part.GetWorldRotation() is the rotation of the object being sat on
+ // Rotation is the sittiing Av's rotation
+
+ Quaternion partRot;
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partRot = part.ParentGroup.RootPart.RotationOffset;
+// }
+// else
+// { // single or child prim
+
+// }
+ if (part == null) //CW: Part may be gone. llDie() for example.
+ {
+ partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ partRot = part.GetWorldRotation();
+ }
+
+ Quaternion partIRot = Quaternion.Inverse(partRot);
+
+ Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
+ Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
+
+
+ if (m_physicsActor == null)
+ {
+ AddToPhysicalScene(false);
+ }
+ //CW: If the part isn't null then we can set the current position
+ if (part != null)
+ {
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + ((m_pos - part.OffsetPosition) * partRot); // + av sit offset!
+ AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
+ part.IsOccupied = false;
+ part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
+ }
+ else
+ {
+ //CW: Since the part doesn't exist, a coarse standup position isn't an issue
+ AbsolutePosition = m_lastWorldPosition;
+ }
+
+ m_parentPosition = Vector3.Zero;
+ m_parentID = 0;
+ m_linkedPrim = UUID.Zero;
+ m_offsetRotation = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ SendFullUpdateToAllClients();
+ m_requestedSitTargetID = 0;
+
+ if ((m_physicsActor != null) && (m_avHeight > 0))
+ {
+ SetHeight(m_avHeight);
+ }
+ }
+ Animator.TrySetMovementAnimation("STAND");
+ }
+
+ private SceneObjectPart FindNextAvailableSitTarget(UUID targetID)
+ {
+ SceneObjectPart targetPart = m_scene.GetSceneObjectPart(targetID);
+ if (targetPart == null)
+ return null;
+
+ // If the primitive the player clicked on has a sit target and that sit target is not full, that sit target is used.
+ // If the primitive the player clicked on has no sit target, and one or more other linked objects have sit targets that are not full, the sit target of the object with the lowest link number will be used.
+
+ // Get our own copy of the part array, and sort into the order we want to test
+ SceneObjectPart[] partArray = targetPart.ParentGroup.GetParts();
+ Array.Sort(partArray, delegate(SceneObjectPart p1, SceneObjectPart p2)
+ {
+ // we want the originally selected part first, then the rest in link order -- so make the selected part link num (-1)
+ int linkNum1 = p1==targetPart ? -1 : p1.LinkNum;
+ int linkNum2 = p2==targetPart ? -1 : p2.LinkNum;
+ return linkNum1 - linkNum2;
+ }
+ );
+
+ //look for prims with explicit sit targets that are available
+ foreach (SceneObjectPart part in partArray)
+ {
+ // Is a sit target available?
+ Vector3 avSitOffSet = part.SitTargetPosition;
+ Quaternion avSitOrientation = part.SitTargetOrientation;
+ UUID avOnTargetAlready = part.GetAvatarOnSitTarget();
+ bool SitTargetOccupied = (avOnTargetAlready != UUID.Zero);
+ bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
+ if (SitTargetisSet && !SitTargetOccupied)
+ {
+ //switch the target to this prim
+ return part;
+ }
+ }
+
+ // no explicit sit target found - use original target
+ return targetPart;
+ }
+
+ private void SendSitResponse(IClientAPI remoteClient, UUID targetID, Vector3 offset, Quaternion pSitOrientation)
+ {
+ bool autopilot = true;
+ Vector3 autopilotTarget = new Vector3();
+ Quaternion sitOrientation = Quaternion.Identity;
+ Vector3 pos = new Vector3();
+ Vector3 cameraEyeOffset = Vector3.Zero;
+ Vector3 cameraAtOffset = Vector3.Zero;
+ bool forceMouselook = false;
+
+ //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
+ SceneObjectPart part = FindNextAvailableSitTarget(targetID);
+ if (part == null) return;
+
+ // TODO: determine position to sit at based on scene geometry; don't trust offset from client
+ // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it
+
+ // part is the prim to sit on
+ // offset is the world-ref vector distance from that prim center to the click-spot
+ // UUID is the UUID of the Avatar doing the clicking
+
+ m_avInitialPos = AbsolutePosition; // saved to calculate unscripted sit rotation
+
+ // Is a sit target available?
+ Vector3 avSitOffSet = part.SitTargetPosition;
+ Quaternion avSitOrientation = part.SitTargetOrientation;
+
+ bool SitTargetisSet = (Vector3.Zero != avSitOffSet); //NB Latest SL Spec shows Sit Rotation setting is ignored.
+ // Quaternion partIRot = Quaternion.Inverse(part.GetWorldRotation());
+ Quaternion partRot;
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partRot = part.ParentGroup.RootPart.RotationOffset;
+// }
+// else
+// { // single or child prim
+ partRot = part.GetWorldRotation();
+// }
+ Quaternion partIRot = Quaternion.Inverse(partRot);
+//Console.WriteLine("SendSitResponse offset=" + offset + " Occup=" + part.IsOccupied + " TargSet=" + SitTargetisSet);
+ // Sit analysis rewritten by KF 091125
+ if (SitTargetisSet) // scipted sit
+ {
+ if (!part.IsOccupied)
+ {
+//Console.WriteLine("Scripted, unoccupied");
+ part.SetAvatarOnSitTarget(UUID); // set that Av will be on it
+ offset = new Vector3(avSitOffSet.X, avSitOffSet.Y, avSitOffSet.Z); // change ofset to the scripted one
+
+ Quaternion nrot = avSitOrientation;
+ if (!part.IsRoot)
+ {
+ nrot = part.RotationOffset * avSitOrientation;
+ }
+ sitOrientation = nrot; // Change rotatione to the scripted one
+ OffsetRotation = nrot;
+ autopilot = false; // Jump direct to scripted llSitPos()
+ }
+ else
+ {
+//Console.WriteLine("Scripted, occupied");
+ return;
+ }
+ }
+ else // Not Scripted
+ {
+ if ( (Math.Abs(offset.X) > 0.5f) || (Math.Abs(offset.Y) > 0.5f) )
+ {
+ // large prim & offset, ignore if other Avs sitting
+// offset.Z -= 0.05f;
+ m_avUnscriptedSitPos = offset * partIRot; // (non-zero) sit where clicked
+ autopilotTarget = part.AbsolutePosition + offset; // World location of clicked point
+
+//Console.WriteLine(" offset ={0}", offset);
+//Console.WriteLine(" UnscriptedSitPos={0}", m_avUnscriptedSitPos);
+//Console.WriteLine(" autopilotTarget={0}", autopilotTarget);
+
+ }
+ else // small offset
+ {
+//Console.WriteLine("Small offset");
+ if (!part.IsOccupied)
+ {
+ m_avUnscriptedSitPos = Vector3.Zero; // Zero = Sit on prim center
+ autopilotTarget = part.AbsolutePosition;
+//Console.WriteLine("UsSmall autopilotTarget={0}", autopilotTarget);
+ }
+ else return; // occupied small
+ } // end large/small
+ } // end Scripted/not
+ cameraAtOffset = part.GetCameraAtOffset();
+ cameraEyeOffset = part.GetCameraEyeOffset();
+ forceMouselook = part.GetForceMouselook();
+ if(cameraAtOffset == Vector3.Zero) cameraAtOffset = new Vector3(0f, 0f, 0.1f); //
+ if(cameraEyeOffset == Vector3.Zero) cameraEyeOffset = new Vector3(0f, 0f, 0.1f); //
+
+ if (m_physicsActor != null)
+ {
+ // If we're not using the client autopilot, we're immediately warping the avatar to the location
+ // We can remove the physicsActor until they stand up.
+ m_sitAvatarHeight = m_physicsActor.Size.Z;
+ if (autopilot)
+ { // its not a scripted sit
+// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
+ if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
+ {
+ autopilot = false; // close enough
+ m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
+ Not using the part's position because returning the AV to the last known standing
+ position is likely to be more friendly, isn't it? */
+ RemoveFromPhysicalScene();
+ Velocity = Vector3.Zero;
+ AbsolutePosition = autopilotTarget + new Vector3(0.0f, 0.0f, (m_sitAvatarHeight / 2.0f)); // Warp av to over sit target
+ } // else the autopilot will get us close
+ }
+ else
+ { // its a scripted sit
+ m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
+ I *am* using the part's position this time because we have no real idea how far away
+ the avatar is from the sit target. */
+ RemoveFromPhysicalScene();
+ Velocity = Vector3.Zero;
+ }
+ }
+ else return; // physactor is null!
+
+ Vector3 offsetr; // = offset * partIRot;
+ // KF: In a linkset, offsetr needs to be relative to the group root! 091208
+ // offsetr = (part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) + (offset * partIRot);
+ // if (part.LinkNum < 2) 091216 All this was necessary because of the GetWorldRotation error.
+ // { // Single, or Root prim of linkset, target is ClickOffset * RootRot
+ //offsetr = offset * partIRot;
+//
+ // else
+ // { // Child prim, offset is (ChildOffset * RootRot) + (ClickOffset * ChildRot)
+ // offsetr = //(part.OffsetPosition * Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset)) +
+ // (offset * partRot);
+ // }
+
+//Console.WriteLine(" ");
+//Console.WriteLine("link number ={0}", part.LinkNum);
+//Console.WriteLine("Prim offset ={0}", part.OffsetPosition );
+//Console.WriteLine("Root Rotate ={0}", part.ParentGroup.RootPart.RotationOffset);
+//Console.WriteLine("Click offst ={0}", offset);
+//Console.WriteLine("Prim Rotate ={0}", part.GetWorldRotation());
+//Console.WriteLine("offsetr ={0}", offsetr);
+//Console.WriteLine("Camera At ={0}", cameraAtOffset);
+//Console.WriteLine("Camera Eye ={0}", cameraEyeOffset);
+
+ //NOTE: SendSitResponse should be relative to the GROUP *NOT* THE PRIM if we're sitting on a child
+ ControllingClient.SendSitResponse(part.ParentGroup.UUID, ((offset * part.RotationOffset) + part.OffsetPosition), sitOrientation, autopilot, cameraAtOffset, cameraEyeOffset, forceMouselook);
+
+ m_requestedSitTargetUUID = part.UUID; //KF: Correct autopilot target
+ // This calls HandleAgentSit twice, once from here, and the client calls
+ // HandleAgentSit itself after it gets to the location
+ // It doesn't get to the location until we've moved them there though
+ // which happens in HandleAgentSit :P
+ m_autopilotMoving = autopilot;
+ m_autoPilotTarget = autopilotTarget;
+ m_sitAtAutoTarget = autopilot;
+ m_initialSitTarget = autopilotTarget;
+ if (!autopilot)
+ HandleAgentSit(remoteClient, UUID);
+ }
+
+ public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset)
+ {
+ if (m_parentID != 0)
+ {
+ StandUp();
+ }
+ m_nextSitAnimation = "SIT";
+
+ //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
+ SceneObjectPart part = FindNextAvailableSitTarget(targetID);
+
+ if (part != null)
+ {
+ if (!String.IsNullOrEmpty(part.SitAnimation))
+ {
+ m_nextSitAnimation = part.SitAnimation;
+ }
+ m_requestedSitTargetID = part.LocalId;
+ //m_requestedSitOffset = offset;
+ m_requestedSitTargetUUID = targetID;
+
+ m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
+
+ if (m_scene.PhysicsScene.SupportsRayCast())
+ {
+ //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback());
+ //SitRayCastAvatarPosition(part);
+ //return;
+ }
+ }
+ else
+ {
+
+ m_log.Warn("Sit requested on unknown object: " + targetID.ToString());
+ }
+
+
+
+ SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
+ }
+ /*
+ public void SitRayCastAvatarPosition(SceneObjectPart part)
+ {
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = AbsolutePosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse);
+ }
+
+ public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ }
+ else
+ {
+ SitRayCastAvatarPositionCameraZ(part);
+ }
+ }
+ else
+ {
+ SitRayCastAvatarPositionCameraZ(part);
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part)
+ {
+ // Next, try to raycast from the camera Z position
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse);
+ }
+
+ public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ }
+ else
+ {
+ SitRayCastCameraPosition(part);
+ }
+ }
+ else
+ {
+ SitRayCastCameraPosition(part);
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ public void SitRayCastCameraPosition(SceneObjectPart part)
+ {
+ // Next, try to raycast from the camera position
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = CameraPosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse);
+ }
+
+ public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ }
+ else
+ {
+ SitRayHorizontal(part);
+ }
+ }
+ else
+ {
+ SitRayHorizontal(part);
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ public void SitRayHorizontal(SceneObjectPart part)
+ {
+ // Next, try to raycast from the avatar position to fwd
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = CameraPosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse);
+ }
+
+ public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal)
+ {
+ SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID);
+ if (part != null)
+ {
+ if (hitYN)
+ {
+ if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f))
+ {
+ SitRaycastFindEdge(collisionPoint, normal);
+ m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal);
+ // Next, try to raycast from the camera position
+ Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset;
+ Vector3 StartRayCastPosition = CameraPosition;
+ Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition);
+ float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition);
+ //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition);
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position not accessable.");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position not accessable.");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+ }
+ else
+ {
+ ControllingClient.SendAlertMessage("Sit position no longer exists");
+ m_requestedSitTargetUUID = UUID.Zero;
+ m_requestedSitTargetID = 0;
+ m_requestedSitOffset = Vector3.Zero;
+ }
+
+ }
+
+ private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal)
+ {
+ int i = 0;
+ //throw new NotImplementedException();
+ //m_requestedSitTargetUUID = UUID.Zero;
+ //m_requestedSitTargetID = 0;
+ //m_requestedSitOffset = Vector3.Zero;
+
+ SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity);
+ }
+ */
+ public void HandleAgentRequestSit(IClientAPI remoteClient, UUID agentID, UUID targetID, Vector3 offset, string sitAnimation)
+ {
+ if (m_parentID != 0)
+ {
+ StandUp();
+ }
+ if (!String.IsNullOrEmpty(sitAnimation))
+ {
+ m_nextSitAnimation = sitAnimation;
+ }
+ else
+ {
+ m_nextSitAnimation = "SIT";
+ }
+
+ //SceneObjectPart part = m_scene.GetSceneObjectPart(targetID);
+ SceneObjectPart part = FindNextAvailableSitTarget(targetID);
+ if (part != null)
+ {
+ m_requestedSitTargetID = part.LocalId;
+ //m_requestedSitOffset = offset;
+ m_requestedSitTargetUUID = targetID;
+
+ m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset);
+
+ if (m_scene.PhysicsScene.SupportsRayCast())
+ {
+ //SitRayCastAvatarPosition(part);
+ //return;
+ }
+ }
+ else
+ {
+ m_log.Warn("Sit requested on unknown object: " + targetID);
+ }
+
+ SendSitResponse(remoteClient, targetID, offset, Quaternion.Identity);
+ }
+
+ public void HandleAgentSit(IClientAPI remoteClient, UUID agentID)
+ {
+ if (!String.IsNullOrEmpty(m_nextSitAnimation))
+ {
+ HandleAgentSit(remoteClient, agentID, m_nextSitAnimation);
+ }
+ else
+ {
+ HandleAgentSit(remoteClient, agentID, "SIT");
+ }
+ }
+
+ public void HandleAgentSit(IClientAPI remoteClient, UUID agentID, string sitAnimation)
+ {
+ SceneObjectPart part = m_scene.GetSceneObjectPart(m_requestedSitTargetID);
+
+ if (m_sitAtAutoTarget || !m_autopilotMoving)
+ {
+ if (part != null)
+ {
+//Console.WriteLine("Link #{0}, Rot {1}", part.LinkNum, part.GetWorldRotation());
+ if (part.GetAvatarOnSitTarget() == UUID)
+ {
+//Console.WriteLine("Scripted Sit");
+ // Scripted sit
+ Vector3 sitTargetPos = part.SitTargetPosition;
+ Quaternion sitTargetOrient = part.SitTargetOrientation;
+ m_pos = new Vector3(sitTargetPos.X, sitTargetPos.Y, sitTargetPos.Z);
+ m_pos += SIT_TARGET_ADJUSTMENT;
+ if (!part.IsRoot)
+ {
+ m_pos *= part.RotationOffset;
+ }
+ m_bodyRot = sitTargetOrient;
+ m_parentPosition = part.AbsolutePosition;
+ part.IsOccupied = true;
+ part.ParentGroup.AddAvatar(agentID);
+ }
+ else
+ {
+ // if m_avUnscriptedSitPos is zero then Av sits above center
+ // Else Av sits at m_avUnscriptedSitPos
+
+ // Non-scripted sit by Kitto Flora 21Nov09
+ // Calculate angle of line from prim to Av
+ Quaternion partIRot;
+// if (part.LinkNum == 1)
+// { // Root prim of linkset
+// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+// }
+// else
+// { // single or child prim
+ partIRot = Quaternion.Inverse(part.GetWorldRotation());
+// }
+ Vector3 sitTargetPos= part.AbsolutePosition + m_avUnscriptedSitPos;
+ float y_diff = (m_avInitialPos.Y - sitTargetPos.Y);
+ float x_diff = ( m_avInitialPos.X - sitTargetPos.X);
+ if(Math.Abs(x_diff) < 0.001f) x_diff = 0.001f; // avoid div by 0
+ if(Math.Abs(y_diff) < 0.001f) y_diff = 0.001f; // avoid pol flip at 0
+ float sit_angle = (float)Math.Atan2( (double)y_diff, (double)x_diff);
+ // NOTE: when sitting m_ pos and m_bodyRot are *relative* to the prim location/rotation, not 'World'.
+ // Av sits at world euler <0,0, z>, translated by part rotation
+ m_bodyRot = partIRot * Quaternion.CreateFromEulers(0f, 0f, sit_angle); // sit at 0,0,inv-click
+
+ m_parentPosition = part.AbsolutePosition;
+ part.IsOccupied = true;
+ part.ParentGroup.AddAvatar(agentID);
+ m_pos = new Vector3(0f, 0f, 0.05f) + // corrections to get Sit Animation
+ (new Vector3(0.0f, 0f, 0.61f) * partIRot) + // located on center
+ (new Vector3(0.34f, 0f, 0.0f) * m_bodyRot) +
+ m_avUnscriptedSitPos; // adds click offset, if any
+ //Set up raytrace to find top surface of prim
+ Vector3 size = part.Scale;
+ float mag = 2.0f; // 0.1f + (float)Math.Sqrt((size.X * size.X) + (size.Y * size.Y) + (size.Z * size.Z));
+ Vector3 start = part.AbsolutePosition + new Vector3(0f, 0f, mag);
+ Vector3 down = new Vector3(0f, 0f, -1f);
+//Console.WriteLine("st={0} do={1} ma={2}", start, down, mag);
+ m_scene.PhysicsScene.RaycastWorld(
+ start, // Vector3 position,
+ down, // Vector3 direction,
+ mag, // float length,
+ SitAltitudeCallback); // retMethod
+ } // end scripted/not
+ }
+ else // no Av
+ {
+ return;
+ }
+ }
+
+ //We want our offsets to reference the root prim, not the child we may have sat on
+ if (!part.IsRoot)
+ {
+ m_parentID = part.ParentGroup.RootPart.LocalId;
+ m_pos += part.OffsetPosition;
+ }
+ else
+ {
+ m_parentID = m_requestedSitTargetID;
+ }
+
+ m_linkedPrim = part.UUID;
+ if (part.GetAvatarOnSitTarget() != UUID)
+ {
+ m_offsetRotation = m_offsetRotation / part.RotationOffset;
+ }
+ Velocity = Vector3.Zero;
+ RemoveFromPhysicalScene();
+ Animator.TrySetMovementAnimation(sitAnimation);
+ SendFullUpdateToAllClients();
+ SendTerseUpdateToAllClients();
+ }
+
+ public void SitAltitudeCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 normal)
+ {
+ // KF: 091202 There appears to be a bug in Prim Edit Size - the process sometimes make a prim that RayTrace no longer
+ // sees. Take/re-rez, or sim restart corrects the condition. Result of bug is incorrect sit height.
+ if(hitYN)
+ {
+ // m_pos = Av offset from prim center to make look like on center
+ // m_parentPosition = Actual center pos of prim
+ // collisionPoint = spot on prim where we want to sit
+ // collisionPoint.Z = global sit surface height
+ SceneObjectPart part = m_scene.GetSceneObjectPart(localid);
+ Quaternion partIRot;
+// if (part.LinkNum == 1)
+/// { // Root prim of linkset
+// partIRot = Quaternion.Inverse(part.ParentGroup.RootPart.RotationOffset);
+// }
+// else
+// { // single or child prim
+ partIRot = Quaternion.Inverse(part.GetWorldRotation());
+// }
+ if (m_initialSitTarget != null)
+ {
+ float offZ = collisionPoint.Z - m_initialSitTarget.Z;
+ Vector3 offset = new Vector3(0.0f, 0.0f, offZ) * partIRot; // Altitude correction
+ //Console.WriteLine("sitPoint={0}, offset={1}", sitPoint, offset);
+ m_pos += offset;
+ // ControllingClient.SendClearFollowCamProperties(part.UUID);
+ }
+
+ }
+ } // End SitAltitudeCallback KF.
+
+ ///
+ /// Event handler for the 'Always run' setting on the client
+ /// Tells the physics plugin to increase speed of movement.
+ ///
+ public void HandleSetAlwaysRun(IClientAPI remoteClient, bool pSetAlwaysRun)
+ {
+ m_setAlwaysRun = pSetAlwaysRun;
+ if (PhysicsActor != null)
+ {
+ PhysicsActor.SetAlwaysRun = pSetAlwaysRun;
+ }
+ }
+
+ public void HandleStartAnim(IClientAPI remoteClient, UUID animID)
+ {
+ Animator.AddAnimation(animID, UUID.Zero);
+ }
+
+ public void HandleStopAnim(IClientAPI remoteClient, UUID animID)
+ {
+ Animator.RemoveAnimation(animID);
+ }
+
+ ///
+ /// Rotate the avatar to the given rotation and apply a movement in the given relative vector
+ ///
+ /// The vector in which to move. This is relative to the rotation argument
+ /// The direction in which this avatar should now face.
+ public void AddNewMovement(Vector3 vec, Quaternion rotation, bool Nudging)
+ {
+ if (m_isChildAgent)
+ {
+ // WHAT???
+ m_log.Debug("[SCENEPRESENCE]: AddNewMovement() called on child agent, making root agent!");
+
+ // we have to reset the user's child agent connections.
+ // Likely, here they've lost the eventqueue for other regions so border
+ // crossings will fail at this point unless we reset them.
+
+ List regions = new List(KnownChildRegionHandles);
+ regions.Remove(m_scene.RegionInfo.RegionHandle);
+
+ MakeRootAgent(new Vector3(127f, 127f, 127f), true);
+
+ // Async command
+ if (m_scene.SceneGridService != null)
+ {
+ m_scene.SceneGridService.SendCloseChildAgentConnections(UUID, regions);
+
+ // Give the above command some time to try and close the connections.
+ // this is really an emergency.. so sleep, or we'll get all discombobulated.
+ System.Threading.Thread.Sleep(500);
+ }
+
+ if (m_scene.SceneGridService != null)
+ {
+ IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface();
+ if (m_agentTransfer != null)
+ m_agentTransfer.EnableChildAgents(this);
+ }
+
+ return;
+ }
+
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ Rotation = rotation;
+ Vector3 direc = vec * rotation;
+ direc.Normalize();
+ PhysicsActor actor = m_physicsActor;
+ if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
+
+ direc *= 0.03f * 128f * m_speedModifier;
+
+ if (actor != null)
+ {
+ if (actor.Flying)
+ {
+ direc *= 4.0f;
+ //bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
+ //bool colliding = (m_physicsActor.IsColliding==true);
+ //if (controlland)
+ // m_log.Info("[AGENT]: landCommand");
+ //if (colliding)
+ // m_log.Info("[AGENT]: colliding");
+ //if (m_physicsActor.Flying && colliding && controlland)
+ //{
+ // StopFlying();
+ // m_log.Info("[AGENT]: Stop FLying");
+ //}
+ }
+ else if (!actor.Flying && actor.IsColliding)
+ {
+ if (direc.Z > 2.0f)
+ {
+ if(m_animator.m_animTickJump == -1)
+ {
+ direc.Z *= 3.0f; // jump
+ }
+ else
+ {
+ direc.Z *= 0.1f; // prejump
+ }
+ /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
+ Animator.TrySetMovementAnimation("PREJUMP");
+ Animator.TrySetMovementAnimation("JUMP");
+ */
+ }
+ }
+ }
+
+ // TODO: Add the force instead of only setting it to support multiple forces per frame?
+ m_forceToApply = direc;
+ m_isNudging = Nudging;
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ #endregion
+
+ #region Overridden Methods
+
+ public override void Update()
+ {
+ const float ROTATION_TOLERANCE = 0.01f;
+ const float VELOCITY_TOLERANCE = 0.001f;
+ const float POSITION_TOLERANCE = 0.05f;
+ //const int TIME_MS_TOLERANCE = 3000;
+
+
+
+ if (m_isChildAgent == false)
+ {
+// PhysicsActor actor = m_physicsActor;
+
+ // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to
+ // grab the latest PhysicsActor velocity, whereas m_velocity is often
+ // storing a requested force instead of an actual traveling velocity
+
+ // Throw away duplicate or insignificant updates
+ if (!m_bodyRot.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) ||
+ !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) ||
+ !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))
+ //Environment.TickCount - m_lastTerseSent > TIME_MS_TOLERANCE)
+ {
+ SendTerseUpdateToAllClients();
+
+ // Update the "last" values
+ m_lastPosition = m_pos;
+ m_lastRotation = m_bodyRot;
+ m_lastVelocity = Velocity;
+ //m_lastTerseSent = Environment.TickCount;
+ }
+
+ // followed suggestion from mic bowman. reversed the two lines below.
+ if (m_parentID == 0 && m_physicsActor != null || m_parentID != 0) // Check that we have a physics actor or we're sitting on something
+ CheckForBorderCrossing();
+ CheckForSignificantMovement(); // sends update to the modules.
+ }
+
+ //Sending prim updates AFTER the avatar terse updates are sent
+ SendPrimUpdates();
+ }
+
+ #endregion
+
+ #region Update Client(s)
+
+ ///
+ /// Sends a location update to the client connected to this scenePresence
+ ///
+ ///
+ public void SendTerseUpdateToClient(IClientAPI remoteClient)
+ {
+ // If the client is inactive, it's getting its updates from another
+ // server.
+ if (remoteClient.IsActive)
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ PhysicsActor actor = m_physicsActor;
+ Vector3 velocity = (actor != null) ? actor.Velocity : Vector3.Zero;
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
+
+ remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ m_scene.StatsReporter.AddAgentUpdates(1);
+ }
+ }
+
+ ///
+ /// Send a location/velocity/accelleration update to all agents in scene
+ ///
+ public void SendTerseUpdateToAllClients()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ m_scene.ForEachClient(SendTerseUpdateToClient);
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ public void SendCoarseLocations(List coarseLocations, List avatarUUIDs)
+ {
+ SendCourseLocationsMethod d = m_sendCourseLocationsMethod;
+ if (d != null)
+ {
+ d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs);
+ }
+ }
+
+ public void SetSendCourseLocationMethod(SendCourseLocationsMethod d)
+ {
+ if (d != null)
+ m_sendCourseLocationsMethod = d;
+ }
+
+ public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs)
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+ m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations);
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ ///
+ /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar)
+ ///
+ ///
+ public void SendFullUpdateToOtherClient(ScenePresence remoteAvatar)
+ {
+ // 2 stage check is needed.
+ if (remoteAvatar == null)
+ return;
+ IClientAPI cl=remoteAvatar.ControllingClient;
+ if (cl == null)
+ return;
+ if (m_appearance.Texture == null)
+ return;
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
+ m_scene.StatsReporter.AddAgentUpdates(1);
+ }
+
+ ///
+ /// Tell *ALL* agents about this agent
+ ///
+ public void SendInitialFullUpdateToAllClients()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+ int avUpdates = 0;
+ m_scene.ForEachScenePresence(delegate(ScenePresence avatar)
+ {
+ ++avUpdates;
+ // only send if this is the root (children are only "listening posts" in a foreign region)
+ if (!IsChildAgent)
+ {
+ SendFullUpdateToOtherClient(avatar);
+ }
+
+ if (avatar.LocalId != LocalId)
+ {
+ if (!avatar.IsChildAgent)
+ {
+ avatar.SendFullUpdateToOtherClient(this);
+ avatar.SendAppearanceToOtherAgent(this);
+ avatar.Animator.SendAnimPackToClient(ControllingClient);
+ }
+ }
+ });
+
+ m_scene.StatsReporter.AddAgentUpdates(avUpdates);
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+
+ //Animator.SendAnimPack();
+ }
+
+ public void SendFullUpdateToAllClients()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ // only send update from root agents to other clients; children are only "listening posts"
+ int count = 0;
+ m_scene.ForEachScenePresence(delegate(ScenePresence sp)
+ {
+ if (sp.IsChildAgent)
+ return;
+ SendFullUpdateToOtherClient(sp);
+ ++count;
+ });
+ m_scene.StatsReporter.AddAgentUpdates(count);
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+
+ Animator.SendAnimPack();
+ }
+
+ ///
+ /// Do everything required once a client completes its movement into a region
+ ///
+ public void SendInitialData()
+ {
+ // Moved this into CompleteMovement to ensure that m_appearance is initialized before
+ // the inventory arrives
+ // m_scene.GetAvatarAppearance(m_controllingClient, out m_appearance);
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ m_controllingClient.SendAvatarDataImmediate(this);
+
+ SendInitialFullUpdateToAllClients();
+ SendAppearanceToAllOtherAgents();
+ }
+
+ ///
+ /// Tell the client for this scene presence what items it should be wearing now
+ ///
+ public void SendWearables()
+ {
+ m_log.DebugFormat("[SCENE]: Received request for wearables of {0}", Name);
+
+ ControllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
+ }
+
+ ///
+ ///
+ ///
+ public void SendAppearanceToAllOtherAgents()
+ {
+ m_perfMonMS = Util.EnvironmentTickCount();
+
+ m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence)
+ {
+ if (scenePresence.UUID != UUID)
+ {
+ SendAppearanceToOtherAgent(scenePresence);
+ }
+ });
+
+ m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
+ }
+
+ ///
+ /// Send appearance data to an agent that isn't this one.
+ ///
+ ///
+ public void SendAppearanceToOtherAgent(ScenePresence avatar)
+ {
+ avatar.ControllingClient.SendAppearance(
+ m_appearance.Owner, m_appearance.VisualParams, m_appearance.Texture.GetBytes());
+ }
+
+ ///
+ /// Set appearance data (textureentry and slider settings) received from the client
+ ///
+ ///
+ ///
+ public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
+ {
+ if (m_physicsActor != null)
+ {
+ if (!IsChildAgent)
+ {
+ // This may seem like it's redundant, remove the avatar from the physics scene
+ // just to add it back again, but it saves us from having to update
+ // 3 variables 10 times a second.
+ bool flyingTemp = m_physicsActor.Flying;
+ RemoveFromPhysicalScene();
+ //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
+
+ //PhysicsActor = null;
+
+ AddToPhysicalScene(flyingTemp);
+ }
+ }
+
+ #region Bake Cache Check
+
+ if (textureEntry != null)
+ {
+ for (int i = 0; i < BAKE_INDICES.Length; i++)
+ {
+ int j = BAKE_INDICES[i];
+ Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
+
+ if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
+ {
+ if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
+ {
+ m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name);
+ this.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
+ }
+ }
+ }
+
+ }
+
+
+ #endregion Bake Cache Check
+
+ m_appearance.SetAppearance(textureEntry, visualParams);
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
+
+ // This is not needed, because only the transient data changed
+ //AvatarData adata = new AvatarData(m_appearance);
+ //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
+
+ SendAppearanceToAllOtherAgents();
+ if (!m_startAnimationSet)
+ {
+ Animator.UpdateMovementAnimations();
+ m_startAnimationSet = true;
+ }
+
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
+
+ m_controllingClient.SendAvatarDataImmediate(this);
+ }
+
+ public void SetWearable(int wearableId, AvatarWearable wearable)
+ {
+ m_appearance.SetWearable(wearableId, wearable);
+ AvatarData adata = new AvatarData(m_appearance);
+ m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
+ m_controllingClient.SendWearables(m_appearance.Wearables, m_appearance.Serial++);
+ }
+
+ // Because appearance setting is in a module, we actually need
+ // to give it access to our appearance directly, otherwise we
+ // get a synchronization issue.
+ public AvatarAppearance Appearance
+ {
+ get { return m_appearance; }
+ set { m_appearance = value; }
+ }
+
+ #endregion
+
+ #region Significant Movement Method
+
+ ///
+ /// This checks for a significant movement and sends a courselocationchange update
+ ///
+ protected void CheckForSignificantMovement()
+ {
+ // Movement updates for agents in neighboring regions are sent directly to clients.
+ // This value only affects how often agent positions are sent to neighbor regions
+ // for things such as distance-based update prioritization
+ const float SIGNIFICANT_MOVEMENT = 2.0f;
+
+ if (Util.GetDistanceTo(AbsolutePosition, posLastSignificantMove) > SIGNIFICANT_MOVEMENT)
+ {
+ posLastSignificantMove = AbsolutePosition;
+ m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient);
+ }
+
+ // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
+ if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance ||
+ Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance)
+ {
+ m_lastChildAgentUpdatePosition = AbsolutePosition;
+ m_lastChildAgentUpdateCamPosition = CameraPosition;
+
+ ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
+ cadu.ActiveGroupID = UUID.Zero.Guid;
+ cadu.AgentID = UUID.Guid;
+ cadu.alwaysrun = m_setAlwaysRun;
+ cadu.AVHeight = m_avHeight;
+ Vector3 tempCameraCenter = m_CameraCenter;
+ cadu.cameraPosition = tempCameraCenter;
+ cadu.drawdistance = m_DrawDistance;
+ cadu.GroupAccess = 0;
+ cadu.Position = AbsolutePosition;
+ cadu.regionHandle = m_rootRegionHandle;
+ float multiplier = 1;
+ int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
+ if (innacurateNeighbors != 0)
+ {
+ multiplier = 1f / (float)innacurateNeighbors;
+ }
+ if (multiplier <= 0f)
+ {
+ multiplier = 0.25f;
+ }
+
+ //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
+ cadu.throttles = ControllingClient.GetThrottlesPacked(multiplier);
+ cadu.Velocity = Velocity;
+
+ AgentPosition agentpos = new AgentPosition();
+ agentpos.CopyFrom(cadu);
+
+ m_scene.SendOutChildAgentUpdates(agentpos, this);
+ }
+ }
+
+ #endregion
+
+ #region Border Crossing Methods
+
+ ///
+ /// Checks to see if the avatar is in range of a border and calls CrossToNewRegion
+ ///
+ protected void CheckForBorderCrossing()
+ {
+ if (IsChildAgent)
+ return;
+
+ Vector3 pos2 = AbsolutePosition;
+ Vector3 vel = Velocity;
+ int neighbor = 0;
+ int[] fix = new int[2];
+
+ float timeStep = 0.1f;
+ pos2.X = pos2.X + (vel.X*timeStep);
+ pos2.Y = pos2.Y + (vel.Y*timeStep);
+ pos2.Z = pos2.Z + (vel.Z*timeStep);
+
+ if (!IsInTransit)
+ {
+ // Checks if where it's headed exists a region
+
+ bool needsTransit = false;
+ if (m_scene.TestBorderCross(pos2, Cardinals.W))
+ {
+ if (m_scene.TestBorderCross(pos2, Cardinals.S))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.SW, ref fix);
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.N))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.NW, ref fix);
+ }
+ else
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.W, ref fix);
+ }
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.E))
+ {
+ if (m_scene.TestBorderCross(pos2, Cardinals.S))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.SE, ref fix);
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.N))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.NE, ref fix);
+ }
+ else
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.E, ref fix);
+ }
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.S))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.S, ref fix);
+ }
+ else if (m_scene.TestBorderCross(pos2, Cardinals.N))
+ {
+ needsTransit = true;
+ neighbor = HaveNeighbor(Cardinals.N, ref fix);
+ }
+
+
+ // Makes sure avatar does not end up outside region
+ if (neighbor <= 0)
+ {
+ if (!needsTransit)
+ {
+ if (m_requestedSitTargetUUID == UUID.Zero)
+ {
+ Vector3 pos = AbsolutePosition;
+ if (AbsolutePosition.X < 0)
+ pos.X += Velocity.X;
+ else if (AbsolutePosition.X > Constants.RegionSize)
+ pos.X -= Velocity.X;
+ if (AbsolutePosition.Y < 0)
+ pos.Y += Velocity.Y;
+ else if (AbsolutePosition.Y > Constants.RegionSize)
+ pos.Y -= Velocity.Y;
+ AbsolutePosition = pos;
+ }
+ }
+ }
+ else if (neighbor > 0)
+ CrossToNewRegion();
+ }
+ else
+ {
+ RemoveFromPhysicalScene();
+ // This constant has been inferred from experimentation
+ // I'm not sure what this value should be, so I tried a few values.
+ timeStep = 0.04f;
+ pos2 = AbsolutePosition;
+ pos2.X = pos2.X + (vel.X * timeStep);
+ pos2.Y = pos2.Y + (vel.Y * timeStep);
+ pos2.Z = pos2.Z + (vel.Z * timeStep);
+ m_pos = pos2;
+ }
+ }
+
+ protected int HaveNeighbor(Cardinals car, ref int[] fix)
+ {
+ uint neighbourx = m_regionInfo.RegionLocX;
+ uint neighboury = m_regionInfo.RegionLocY;
+
+ int dir = (int)car;
+
+ if (dir > 1 && dir < 5) //Heading East
+ neighbourx++;
+ else if (dir > 5) // Heading West
+ neighbourx--;
+
+ if (dir < 3 || dir == 8) // Heading North
+ neighboury++;
+ else if (dir > 3 && dir < 7) // Heading Sout
+ neighboury--;
+
+ int x = (int)(neighbourx * Constants.RegionSize);
+ int y = (int)(neighboury * Constants.RegionSize);
+ GridRegion neighbourRegion = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, x, y);
+
+ if (neighbourRegion == null)
+ {
+ fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx);
+ fix[1] = (int)(m_regionInfo.RegionLocY - neighboury);
+ return dir * (-1);
+ }
+ else
+ return dir;
+ }
+
+ ///
+ /// Moves the agent outside the region bounds
+ /// Tells neighbor region that we're crossing to it
+ /// If the neighbor accepts, remove the agent's viewable avatar from this scene
+ /// set them to a child agent.
+ ///
+ protected void CrossToNewRegion()
+ {
+ InTransit();
+ try
+ {
+ m_scene.CrossAgentToNewRegion(this, m_physicsActor.Flying);
+ }
+ catch
+ {
+ m_scene.CrossAgentToNewRegion(this, false);
+ }
+ }
+
+ public void InTransit()
+ {
+ m_inTransit = true;
+
+ if ((m_physicsActor != null) && m_physicsActor.Flying)
+ m_AgentControlFlags |= AgentManager.ControlFlags.AGENT_CONTROL_FLY;
+ else if ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0)
+ m_AgentControlFlags &= ~AgentManager.ControlFlags.AGENT_CONTROL_FLY;
+ }
+
+ public void NotInTransit()
+ {
+ m_inTransit = false;
+ }
+
+ public void RestoreInCurrentScene()
+ {
+ AddToPhysicalScene(false); // not exactly false
+ }
+
+ public void Reset()
+ {
+ // Put the child agent back at the center
+ AbsolutePosition
+ = new Vector3(((float)Constants.RegionSize * 0.5f), ((float)Constants.RegionSize * 0.5f), 70);
+ Animator.ResetAnimations();
+ }
+
+ ///
+ /// Computes which child agents to close when the scene presence moves to another region.
+ /// Removes those regions from m_knownRegions.
+ ///
+ /// The new region's x on the map
+ /// The new region's y on the map
+ ///
+ public void CloseChildAgents(uint newRegionX, uint newRegionY)
+ {
+ List byebyeRegions = new List();
+ m_log.DebugFormat(
+ "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}",
+ m_knownChildRegions.Keys.Count, Scene.RegionInfo.RegionName);
+ //DumpKnownRegions();
+
+ lock (m_knownChildRegions)
+ {
+ foreach (ulong handle in m_knownChildRegions.Keys)
+ {
+ // Don't close the agent on this region yet
+ if (handle != Scene.RegionInfo.RegionHandle)
+ {
+ uint x, y;
+ Utils.LongToUInts(handle, out x, out y);
+ x = x / Constants.RegionSize;
+ y = y / Constants.RegionSize;
+
+ //m_log.Debug("---> x: " + x + "; newx:" + newRegionX + "; Abs:" + (int)Math.Abs((int)(x - newRegionX)));
+ //m_log.Debug("---> y: " + y + "; newy:" + newRegionY + "; Abs:" + (int)Math.Abs((int)(y - newRegionY)));
+ if (Util.IsOutsideView(x, newRegionX, y, newRegionY))
+ {
+ byebyeRegions.Add(handle);
+ }
+ }
+ }
+ }
+
+ if (byebyeRegions.Count > 0)
+ {
+ m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents");
+ m_scene.SceneGridService.SendCloseChildAgentConnections(m_controllingClient.AgentId, byebyeRegions);
+ }
+
+ foreach (ulong handle in byebyeRegions)
+ {
+ RemoveNeighbourRegion(handle);
+ }
+ }
+
+ #endregion
+
+ ///
+ /// This allows the Sim owner the abiility to kick users from their sim currently.
+ /// It tells the client that the agent has permission to do so.
+ ///
+ public void GrantGodlikePowers(UUID agentID, UUID sessionID, UUID token, bool godStatus)
+ {
+ if (godStatus)
+ {
+ // For now, assign god level 200 to anyone
+ // who is granted god powers, but has no god level set.
+ //
+ UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, agentID);
+ if (account != null)
+ {
+ if (account.UserLevel > 0)
+ m_godLevel = account.UserLevel;
+ else
+ m_godLevel = 200;
+ }
+ }
+ else
+ {
+ m_godLevel = 0;
+ }
+
+ ControllingClient.SendAdminResponse(token, (uint)m_godLevel);
+ }
+
+ #region Child Agent Updates
+
+ public void ChildAgentDataUpdate(AgentData cAgentData)
+ {
+ //m_log.Debug(" >>> ChildAgentDataUpdate <<< " + Scene.RegionInfo.RegionName);
+ if (!IsChildAgent)
+ return;
+
+ CopyFrom(cAgentData);
+ }
+
+ ///
+ /// This updates important decision making data about a child agent
+ /// The main purpose is to figure out what objects to send to a child agent that's in a neighboring region
+ ///
+ public void ChildAgentDataUpdate(AgentPosition cAgentData, uint tRegionX, uint tRegionY, uint rRegionX, uint rRegionY)
+ {
+ if (!IsChildAgent)
+ return;
+
+ //m_log.Debug(" >>> ChildAgentPositionUpdate <<< " + rRegionX + "-" + rRegionY);
+ int shiftx = ((int)rRegionX - (int)tRegionX) * (int)Constants.RegionSize;
+ int shifty = ((int)rRegionY - (int)tRegionY) * (int)Constants.RegionSize;
+
+ Vector3 offset = new Vector3(shiftx, shifty, 0f);
+
+ m_DrawDistance = cAgentData.Far;
+ if (cAgentData.Position != new Vector3(-1f, -1f, -1f)) // UGH!!
+ m_pos = cAgentData.Position + offset;
+
+ if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance)
+ {
+ posLastSignificantMove = AbsolutePosition;
+ ReprioritizeUpdates();
+ }
+
+ m_CameraCenter = cAgentData.Center + offset;
+
+ m_avHeight = cAgentData.Size.Z;
+ //SetHeight(cAgentData.AVHeight);
+
+ if ((cAgentData.Throttles != null) && cAgentData.Throttles.Length > 0)
+ ControllingClient.SetChildAgentThrottle(cAgentData.Throttles);
+
+ // Sends out the objects in the user's draw distance if m_sendTasksToChild is true.
+ if (m_scene.m_seeIntoRegionFromNeighbor)
+ m_sceneViewer.Reset();
+
+ //cAgentData.AVHeight;
+ m_rootRegionHandle = cAgentData.RegionHandle;
+ //m_velocity = cAgentData.Velocity;
+ }
+
+ public void CopyTo(AgentData cAgent)
+ {
+ cAgent.AgentID = UUID;
+ cAgent.RegionID = Scene.RegionInfo.RegionID;
+
+ cAgent.Position = AbsolutePosition;
+ cAgent.Velocity = m_velocity;
+ cAgent.Center = m_CameraCenter;
+ // Don't copy the size; it is inferred from apearance parameters
+ //cAgent.Size = new Vector3(0, 0, m_avHeight);
+ cAgent.AtAxis = m_CameraAtAxis;
+ cAgent.LeftAxis = m_CameraLeftAxis;
+ cAgent.UpAxis = m_CameraUpAxis;
+
+ cAgent.Far = m_DrawDistance;
+
+ // Throttles
+ float multiplier = 1;
+ int innacurateNeighbors = m_scene.GetInaccurateNeighborCount();
+ if (innacurateNeighbors != 0)
+ {
+ multiplier = 1f / innacurateNeighbors;
+ }
+ if (multiplier <= 0f)
+ {
+ multiplier = 0.25f;
+ }
+ //m_log.Info("[NeighborThrottle]: " + m_scene.GetInaccurateNeighborCount().ToString() + " - m: " + multiplier.ToString());
+ cAgent.Throttles = ControllingClient.GetThrottlesPacked(multiplier);
+
+ cAgent.HeadRotation = m_headrotation;
+ cAgent.BodyRotation = m_bodyRot;
+ cAgent.ControlFlags = (uint)m_AgentControlFlags;
+
+ if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
+ cAgent.GodLevel = (byte)m_godLevel;
+ else
+ cAgent.GodLevel = (byte) 0;
+
+ cAgent.AlwaysRun = m_setAlwaysRun;
+
+ try
+ {
+ // We might not pass the Wearables in all cases...
+ // They're only needed so that persistent changes to the appearance
+ // are preserved in the new region where the user is moving to.
+ // But in Hypergrid we might not let this happen.
+ int i = 0;
+ UUID[] wears = new UUID[m_appearance.Wearables.Length * 2];
+ foreach (AvatarWearable aw in m_appearance.Wearables)
+ {
+ if (aw != null)
+ {
+ wears[i++] = aw.ItemID;
+ wears[i++] = aw.AssetID;
+ }
+ else
+ {
+ wears[i++] = UUID.Zero;
+ wears[i++] = UUID.Zero;
+ }
+ }
+ cAgent.Wearables = wears;
+
+ cAgent.VisualParams = m_appearance.VisualParams;
+
+ if (m_appearance.Texture != null)
+ cAgent.AgentTextures = m_appearance.Texture.GetBytes();
+ }
+ catch (Exception e)
+ {
+ m_log.Warn("[SCENE PRESENCE]: exception in CopyTo " + e.Message);
+ }
+
+ //Attachments
+ List attPoints = m_appearance.GetAttachedPoints();
+ if (attPoints != null)
+ {
+ //m_log.DebugFormat("[SCENE PRESENCE]: attachments {0}", attPoints.Count);
+ int i = 0;
+ AttachmentData[] attachs = new AttachmentData[attPoints.Count];
+ foreach (int point in attPoints)
+ {
+ attachs[i++] = new AttachmentData(point, m_appearance.GetAttachedItem(point), m_appearance.GetAttachedAsset(point));
+ }
+ cAgent.Attachments = attachs;
+ }
+
+ lock (scriptedcontrols)
+ {
+ ControllerData[] controls = new ControllerData[scriptedcontrols.Count];
+ int i = 0;
+
+ foreach (ScriptControllers c in scriptedcontrols.Values)
+ {
+ controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls);
+ }
+ cAgent.Controllers = controls;
+ }
+
+ // Animations
+ try
+ {
+ cAgent.Anims = Animator.Animations.ToArray();
+ }
+ catch { }
+
+ // cAgent.GroupID = ??
+ // Groups???
+
+ }
+
+ public void CopyFrom(AgentData cAgent)
+ {
+ m_originRegionID = cAgent.RegionID;
+
+ m_callbackURI = cAgent.CallbackURI;
+
+ m_pos = cAgent.Position;
+
+ m_velocity = cAgent.Velocity;
+ m_CameraCenter = cAgent.Center;
+ //m_avHeight = cAgent.Size.Z;
+ m_CameraAtAxis = cAgent.AtAxis;
+ m_CameraLeftAxis = cAgent.LeftAxis;
+ m_CameraUpAxis = cAgent.UpAxis;
+
+ m_DrawDistance = cAgent.Far;
+
+ if ((cAgent.Throttles != null) && cAgent.Throttles.Length > 0)
+ ControllingClient.SetChildAgentThrottle(cAgent.Throttles);
+
+ m_headrotation = cAgent.HeadRotation;
+ m_bodyRot = cAgent.BodyRotation;
+ m_AgentControlFlags = (AgentManager.ControlFlags)cAgent.ControlFlags;
+
+ if (m_scene.Permissions.IsGod(new UUID(cAgent.AgentID)))
+ m_godLevel = cAgent.GodLevel;
+ m_setAlwaysRun = cAgent.AlwaysRun;
+
+ uint i = 0;
+ try
+ {
+ if (cAgent.Wearables == null)
+ cAgent.Wearables = new UUID[0];
+ AvatarWearable[] wears = new AvatarWearable[cAgent.Wearables.Length / 2];
+ for (uint n = 0; n < cAgent.Wearables.Length; n += 2)
+ {
+ UUID itemId = cAgent.Wearables[n];
+ UUID assetId = cAgent.Wearables[n + 1];
+ wears[i++] = new AvatarWearable(itemId, assetId);
+ }
+ m_appearance.Wearables = wears;
+ Primitive.TextureEntry te;
+ if (cAgent.AgentTextures != null && cAgent.AgentTextures.Length > 1)
+ te = new Primitive.TextureEntry(cAgent.AgentTextures, 0, cAgent.AgentTextures.Length);
+ else
+ te = AvatarAppearance.GetDefaultTexture();
+ if ((cAgent.VisualParams == null) || (cAgent.VisualParams.Length < AvatarAppearance.VISUALPARAM_COUNT))
+ cAgent.VisualParams = AvatarAppearance.GetDefaultVisualParams();
+ m_appearance.SetAppearance(te, (byte[])cAgent.VisualParams.Clone());
+ }
+ catch (Exception e)
+ {
+ m_log.Warn("[SCENE PRESENCE]: exception in CopyFrom " + e.Message);
+ }
+
+ // Attachments
+ try
+ {
+ if (cAgent.Attachments != null)
+ {
+ m_appearance.ClearAttachments();
+ foreach (AttachmentData att in cAgent.Attachments)
+ {
+ m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID);
+ }
+ }
+ }
+ catch { }
+
+ try
+ {
+ lock (scriptedcontrols)
+ {
+ if (cAgent.Controllers != null)
+ {
+ scriptedcontrols.Clear();
+
+ foreach (ControllerData c in cAgent.Controllers)
+ {
+ ScriptControllers sc = new ScriptControllers();
+ sc.itemID = c.ItemID;
+ sc.ignoreControls = (ScriptControlled)c.IgnoreControls;
+ sc.eventControls = (ScriptControlled)c.EventControls;
+
+ scriptedcontrols[sc.itemID] = sc;
+ }
+ }
+ }
+ }
+ catch { }
+ // Animations
+ try
+ {
+ Animator.ResetAnimations();
+ Animator.Animations.FromArray(cAgent.Anims);
+ }
+ catch { }
+
+ //cAgent.GroupID = ??
+ //Groups???
+ }
+
+ public bool CopyAgent(out IAgentData agent)
+ {
+ agent = new CompleteAgentData();
+ CopyTo((AgentData)agent);
+ return true;
+ }
+
+ #endregion Child Agent Updates
+
+ ///
+ /// Handles part of the PID controller function for moving an avatar.
+ ///
+ public override void UpdateMovement()
+ {
+ if (m_forceToApply.HasValue)
+ {
+
+ Vector3 force = m_forceToApply.Value;
+ m_updateflag = true;
+ Velocity = force;
+
+ m_forceToApply = null;
+ }
+ else
+ {
+ if (m_isNudging)
+ {
+ Vector3 force = Vector3.Zero;
+
+ m_updateflag = true;
+ Velocity = force;
+ m_isNudging = false;
+ m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
+ }
+ }
+ }
+
+ public override void SetText(string text, Vector3 color, double alpha)
+ {
+ throw new Exception("Can't set Text on avatar.");
+ }
+
+ ///
+ /// Adds a physical representation of the avatar to the Physics plugin
+ ///
+ public void AddToPhysicalScene(bool isFlying)
+ {
+ PhysicsScene scene = m_scene.PhysicsScene;
+
+ Vector3 pVec = AbsolutePosition;
+
+ // Old bug where the height was in centimeters instead of meters
+ if (m_avHeight == 127.0f)
+ {
+ m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec, new Vector3(0f, 0f, 1.56f),
+ isFlying);
+ }
+ else
+ {
+ m_physicsActor = scene.AddAvatar(Firstname + "." + Lastname, pVec,
+ new Vector3(0f, 0f, m_avHeight), isFlying);
+ }
+ scene.AddPhysicsActorTaint(m_physicsActor);
+ //m_physicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients;
+ m_physicsActor.OnCollisionUpdate += PhysicsCollisionUpdate;
+ m_physicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong
+ m_physicsActor.SubscribeEvents(500);
+ m_physicsActor.LocalID = LocalId;
+ }
+
+ private void OutOfBoundsCall(Vector3 pos)
+ {
+ //bool flying = m_physicsActor.Flying;
+ //RemoveFromPhysicalScene();
+
+ //AddToPhysicalScene(flying);
+ if (ControllingClient != null)
+ ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true);
+ }
+
+ // Event called by the physics plugin to tell the avatar about a collision.
+ private void PhysicsCollisionUpdate(EventArgs e)
+ {
+ if (e == null)
+ return;
+
+ // The Physics Scene will send (spam!) updates every 500 ms grep: m_physicsActor.SubscribeEvents(
+ // as of this comment the interval is set in AddToPhysicalScene
+ if (Animator!=null)
+ {
+ if (m_updateCount > 0) //KF: DO NOT call UpdateMovementAnimations outside of the m_updateCount wrapper,
+ { // else its will lock out other animation changes, like ground sit.
+ Animator.UpdateMovementAnimations();
+ m_updateCount--;
+ }
+ }
+
+ CollisionEventUpdate collisionData = (CollisionEventUpdate)e;
+ Dictionary coldata = collisionData.m_objCollisionList;
+
+ CollisionPlane = Vector4.UnitW;
+
+ if (m_lastColCount != coldata.Count)
+ {
+ m_updateCount = UPDATE_COUNT;
+ m_lastColCount = coldata.Count;
+ }
+
+ if (coldata.Count != 0 && Animator != null)
+ {
+ switch (Animator.CurrentMovementAnimation)
+ {
+ case "STAND":
+ case "WALK":
+ case "RUN":
+ case "CROUCH":
+ case "CROUCHWALK":
+ {
+ ContactPoint lowest;
+ lowest.SurfaceNormal = Vector3.Zero;
+ lowest.Position = Vector3.Zero;
+ lowest.Position.Z = Single.NaN;
+
+ foreach (ContactPoint contact in coldata.Values)
+ {
+ if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z)
+ {
+ lowest = contact;
+ }
+ }
+
+ CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal));
+ }
+ break;
+ }
+ }
+
+ List thisHitColliders = new List();
+ List endedColliders = new List();
+ List startedColliders = new List();
+
+ foreach (uint localid in coldata.Keys)
+ {
+ thisHitColliders.Add(localid);
+ if (!m_lastColliders.Contains(localid))
+ {
+ startedColliders.Add(localid);
+ }
+ //m_log.Debug("[SCENE PRESENCE]: Collided with:" + localid.ToString() + " at depth of: " + collissionswith[localid].ToString());
+ }
+
+ // calculate things that ended colliding
+ foreach (uint localID in m_lastColliders)
+ {
+ if (!thisHitColliders.Contains(localID))
+ {
+ endedColliders.Add(localID);
+ }
+ }
+ //add the items that started colliding this time to the last colliders list.
+ foreach (uint localID in startedColliders)
+ {
+ m_lastColliders.Add(localID);
+ }
+ // remove things that ended colliding from the last colliders list
+ foreach (uint localID in endedColliders)
+ {
+ m_lastColliders.Remove(localID);
+ }
+
+ // do event notification
+ if (startedColliders.Count > 0)
+ {
+ ColliderArgs StartCollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in startedColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ StartCollidingMessage.Colliders = colliding;
+
+ foreach (SceneObjectGroup att in Attachments)
+ Scene.EventManager.TriggerScriptCollidingStart(att.LocalId, StartCollidingMessage);
+ }
+ }
+
+ if (endedColliders.Count > 0)
+ {
+ ColliderArgs EndCollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in endedColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ EndCollidingMessage.Colliders = colliding;
+
+ foreach (SceneObjectGroup att in Attachments)
+ Scene.EventManager.TriggerScriptCollidingEnd(att.LocalId, EndCollidingMessage);
+ }
+ }
+
+ if (thisHitColliders.Count > 0)
+ {
+ ColliderArgs CollidingMessage = new ColliderArgs();
+ List colliding = new List();
+ foreach (uint localId in thisHitColliders)
+ {
+ if (localId == 0)
+ continue;
+
+ SceneObjectPart obj = Scene.GetSceneObjectPart(localId);
+ string data = "";
+ if (obj != null)
+ {
+ DetectedObject detobj = new DetectedObject();
+ detobj.keyUUID = obj.UUID;
+ detobj.nameStr = obj.Name;
+ detobj.ownerUUID = obj.OwnerID;
+ detobj.posVector = obj.AbsolutePosition;
+ detobj.rotQuat = obj.GetWorldRotation();
+ detobj.velVector = obj.Velocity;
+ detobj.colliderType = 0;
+ detobj.groupUUID = obj.GroupID;
+ colliding.Add(detobj);
+ }
+ }
+
+ if (colliding.Count > 0)
+ {
+ CollidingMessage.Colliders = colliding;
+
+ lock (m_attachments)
+ {
+ foreach (SceneObjectGroup att in m_attachments)
+ Scene.EventManager.TriggerScriptColliding(att.LocalId, CollidingMessage);
+ }
+ }
+ }
+
+ if (m_invulnerable)
+ return;
+
+ float starthealth = Health;
+ uint killerObj = 0;
+ foreach (uint localid in coldata.Keys)
+ {
+ SceneObjectPart part = Scene.GetSceneObjectPart(localid);
+
+ if (part != null && part.ParentGroup.Damage != -1.0f)
+ Health -= part.ParentGroup.Damage;
+ else
+ {
+ if (coldata[localid].PenetrationDepth >= 0.10f)
+ Health -= coldata[localid].PenetrationDepth * 5.0f;
+ }
+
+ if (Health <= 0.0f)
+ {
+ if (localid != 0)
+ killerObj = localid;
+ }
+ //m_log.Debug("[AVATAR]: Collision with localid: " + localid.ToString() + " at depth: " + coldata[localid].ToString());
+ }
+ //Health = 100;
+ if (!m_invulnerable)
+ {
+ if (starthealth != Health)
+ {
+ ControllingClient.SendHealth(Health);
+ }
+ if (m_health <= 0)
+ m_scene.EventManager.TriggerAvatarKill(killerObj, this);
+ }
+ }
+
+ public void setHealthWithUpdate(float health)
+ {
+ Health = health;
+ ControllingClient.SendHealth(Health);
+ }
+
+ public void Close()
+ {
+ lock (m_attachments)
+ {
+ // Delete attachments from scene
+ // Don't try to save, as this thread won't live long
+ // enough to complete the save. This would cause no copy
+ // attachments to poof!
+ //
+ foreach (SceneObjectGroup grp in m_attachments)
+ {
+ m_scene.DeleteSceneObject(grp, false);
+ }
+ m_attachments.Clear();
+ }
+
+ lock (m_knownChildRegions)
+ {
+ m_knownChildRegions.Clear();
+ }
+
+ lock (m_reprioritization_timer)
+ {
+ m_reprioritization_timer.Enabled = false;
+ m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
+ }
+
+ // I don't get it but mono crashes when you try to dispose of this timer,
+ // unsetting the elapsed callback should be enough to allow for cleanup however.
+ // m_reprioritizationTimer.Dispose();
+
+ m_sceneViewer.Close();
+
+ RemoveFromPhysicalScene();
+ m_animator.Close();
+ m_animator = null;
+ }
+
+ public void AddAttachment(SceneObjectGroup gobj)
+ {
+ lock (m_attachments)
+ {
+ m_attachments.Add(gobj);
+ }
+ }
+
+ public bool HasAttachments()
+ {
+ return m_attachments.Count > 0;
+ }
+
+ public bool HasScriptedAttachments()
+ {
+ lock (m_attachments)
+ {
+ foreach (SceneObjectGroup gobj in m_attachments)
+ {
+ if (gobj != null)
+ {
+ if (gobj.RootPart.Inventory.ContainsScripts())
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+ public void RemoveAttachment(SceneObjectGroup gobj)
+ {
+ lock (m_attachments)
+ {
+ if (m_attachments.Contains(gobj))
+ {
+ m_attachments.Remove(gobj);
+ }
+ }
+ }
+
+ public bool ValidateAttachments()
+ {
+ lock (m_attachments)
+ {
+ // Validate
+ foreach (SceneObjectGroup gobj in m_attachments)
+ {
+ if (gobj == null)
+ return false;
+
+ if (gobj.IsDeleted)
+ return false;
+ }
+ }
+ return true;
+ }
+
+ ///
+ /// Send a script event to this scene presence's attachments
+ ///
+ /// The name of the event
+ /// The arguments for the event
+ public void SendScriptEventToAttachments(string eventName, Object[] args)
+ {
+ if (m_scriptEngines != null)
+ {
+ lock (m_attachments)
+ {
+ foreach (SceneObjectGroup grp in m_attachments)
+ {
+ // 16384 is CHANGED_ANIMATION
+ //
+ // Send this to all attachment root prims
+ //
+ foreach (IScriptModule m in m_scriptEngines)
+ {
+ if (m == null) // No script engine loaded
+ continue;
+
+ m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
+ }
+ }
+ }
+ }
+ }
+
+
+ public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
+ {
+ m_controllingClient = client;
+ m_regionInfo = region;
+ m_scene = scene;
+
+ RegisterToEvents();
+ if (m_controllingClient != null)
+ {
+ m_controllingClient.ProcessPendingPackets();
+ }
+ /*
+ AbsolutePosition = client.StartPos;
+
+ Animations = new AvatarAnimations();
+ Animations.LoadAnims();
+
+ m_animations = new List();
+ m_animations.Add(Animations.AnimsUUID["STAND"]);
+ m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
+
+ SetDirectionVectors();
+ */
+ }
+
+ internal void PushForce(Vector3 impulse)
+ {
+ if (PhysicsActor != null)
+ {
+ PhysicsActor.AddForce(impulse,true);
+ }
+ }
+
+ public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID)
+ {
+ ScriptControllers obj = new ScriptControllers();
+ obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
+ obj.eventControls = ScriptControlled.CONTROL_ZERO;
+
+ obj.itemID = Script_item_UUID;
+ if (pass_on == 0 && accept == 0)
+ {
+ IgnoredControls |= (ScriptControlled)controls;
+ obj.ignoreControls = (ScriptControlled)controls;
+ }
+
+ if (pass_on == 0 && accept == 1)
+ {
+ IgnoredControls |= (ScriptControlled)controls;
+ obj.ignoreControls = (ScriptControlled)controls;
+ obj.eventControls = (ScriptControlled)controls;
+ }
+ if (pass_on == 1 && accept == 1)
+ {
+ IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ obj.eventControls = (ScriptControlled)controls;
+ obj.ignoreControls = ScriptControlled.CONTROL_ZERO;
+ }
+
+ lock (scriptedcontrols)
+ {
+ if (pass_on == 1 && accept == 0)
+ {
+ IgnoredControls &= ~(ScriptControlled)controls;
+ if (scriptedcontrols.ContainsKey(Script_item_UUID))
+ scriptedcontrols.Remove(Script_item_UUID);
+ }
+ else
+ {
+ scriptedcontrols[Script_item_UUID] = obj;
+ }
+ }
+ ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
+ }
+
+ public void HandleForceReleaseControls(IClientAPI remoteClient, UUID agentID)
+ {
+ IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ lock (scriptedcontrols)
+ {
+ scriptedcontrols.Clear();
+ }
+ ControllingClient.SendTakeControls(int.MaxValue, false, false);
+ }
+
+ public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID)
+ {
+ ScriptControllers takecontrols;
+
+ lock (scriptedcontrols)
+ {
+ if (scriptedcontrols.TryGetValue(Script_item_UUID, out takecontrols))
+ {
+ ScriptControlled sctc = takecontrols.eventControls;
+
+ ControllingClient.SendTakeControls((int)sctc, false, false);
+ ControllingClient.SendTakeControls((int)sctc, true, false);
+
+ scriptedcontrols.Remove(Script_item_UUID);
+ IgnoredControls = ScriptControlled.CONTROL_ZERO;
+ foreach (ScriptControllers scData in scriptedcontrols.Values)
+ {
+ IgnoredControls |= scData.ignoreControls;
+ }
+ }
+ }
+ }
+
+ internal void SendControlToScripts(uint flags)
+ {
+ ScriptControlled allflags = ScriptControlled.CONTROL_ZERO;
+
+ if (MouseDown)
+ {
+ allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON);
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0)
+ {
+ allflags = ScriptControlled.CONTROL_ZERO;
+ MouseDown = true;
+ }
+ }
+
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_ML_LBUTTON;
+ MouseDown = true;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_LBUTTON;
+ MouseDown = true;
+ }
+
+ // find all activated controls, whether the scripts are interested in them or not
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_FWD;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_BACK;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_UP;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_DOWN;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_LEFT;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_RIGHT;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_ROT_RIGHT;
+ }
+ if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS) != 0)
+ {
+ allflags |= ScriptControlled.CONTROL_ROT_LEFT;
+ }
+ // optimization; we have to check per script, but if nothing is pressed and nothing changed, we can skip that
+ if (allflags != ScriptControlled.CONTROL_ZERO || allflags != LastCommands)
+ {
+ lock (scriptedcontrols)
+ {
+ foreach (KeyValuePair kvp in scriptedcontrols)
+ {
+ UUID scriptUUID = kvp.Key;
+ ScriptControllers scriptControlData = kvp.Value;
+
+ ScriptControlled localHeld = allflags & scriptControlData.eventControls; // the flags interesting for us
+ ScriptControlled localLast = LastCommands & scriptControlData.eventControls; // the activated controls in the last cycle
+ ScriptControlled localChange = localHeld ^ localLast; // the changed bits
+ if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO)
+ {
+ // only send if still pressed or just changed
+ m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange);
+ }
+ }
+ }
+ }
+
+ LastCommands = allflags;
+ }
+
+ internal static AgentManager.ControlFlags RemoveIgnoredControls(AgentManager.ControlFlags flags, ScriptControlled ignored)
+ {
+ if (ignored == ScriptControlled.CONTROL_ZERO)
+ return flags;
+
+ if ((ignored & ScriptControlled.CONTROL_BACK) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG);
+ if ((ignored & ScriptControlled.CONTROL_FWD) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS | AgentManager.ControlFlags.AGENT_CONTROL_AT_POS);
+ if ((ignored & ScriptControlled.CONTROL_DOWN) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG);
+ if ((ignored & ScriptControlled.CONTROL_UP) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_POS | AgentManager.ControlFlags.AGENT_CONTROL_UP_POS);
+ if ((ignored & ScriptControlled.CONTROL_LEFT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS | AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_POS);
+ if ((ignored & ScriptControlled.CONTROL_RIGHT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_LEFT_NEG | AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG);
+ if ((ignored & ScriptControlled.CONTROL_ROT_LEFT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_NEG);
+ if ((ignored & ScriptControlled.CONTROL_ROT_RIGHT) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_YAW_POS);
+ if ((ignored & ScriptControlled.CONTROL_ML_LBUTTON) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN);
+ if ((ignored & ScriptControlled.CONTROL_LBUTTON) != 0)
+ flags &= ~(AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP | AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN);
+
+ //DIR_CONTROL_FLAG_FORWARD = AgentManager.ControlFlags.AGENT_CONTROL_AT_POS,
+ //DIR_CONTROL_FLAG_BACK = AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG,
+ //DIR_CONTROL_FLAG_LEFT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS,
+ //DIR_CONTROL_FLAG_RIGHT = AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG,
+ //DIR_CONTROL_FLAG_UP = AgentManager.ControlFlags.AGENT_CONTROL_UP_POS,
+ //DIR_CONTROL_FLAG_DOWN = AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG,
+ //DIR_CONTROL_FLAG_DOWN_NUDGE = AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG
+
+ return flags;
+ }
+
+ ///
+ /// RezAttachments. This should only be called upon login on the first region.
+ /// Attachment rezzings on crossings and TPs are done in a different way.
+ ///
+ public void RezAttachments()
+ {
+ if (null == m_appearance)
+ {
+ m_log.WarnFormat("[ATTACHMENT]: Appearance has not been initialized for agent {0}", UUID);
+ return;
+ }
+
+ XmlDocument doc = new XmlDocument();
+ string stateData = String.Empty;
+
+ IAttachmentsService attServ = m_scene.RequestModuleInterface();
+ if (attServ != null)
+ {
+ m_log.DebugFormat("[ATTACHMENT]: Loading attachment data from attachment service");
+ stateData = attServ.Get(ControllingClient.AgentId.ToString());
+ if (stateData != String.Empty)
+ {
+ try
+ {
+ doc.LoadXml(stateData);
+ }
+ catch { }
+ }
+ }
+
+ Dictionary itemData = new Dictionary();
+
+ XmlNodeList nodes = doc.GetElementsByTagName("Attachment");
+ if (nodes.Count > 0)
+ {
+ foreach (XmlNode n in nodes)
+ {
+ XmlElement elem = (XmlElement)n;
+ string itemID = elem.GetAttribute("ItemID");
+ string xml = elem.InnerXml;
+
+ itemData[new UUID(itemID)] = xml;
+ }
+ }
+
+ List attPoints = m_appearance.GetAttachedPoints();
+ foreach (int p in attPoints)
+ {
+ if (m_isDeleted)
+ return;
+
+ UUID itemID = m_appearance.GetAttachedItem(p);
+ UUID assetID = m_appearance.GetAttachedAsset(p);
+
+ // For some reason assetIDs are being written as Zero's in the DB -- need to track tat down
+ // But they're not used anyway, the item is being looked up for now, so let's proceed.
+ //if (UUID.Zero == assetID)
+ //{
+ // m_log.DebugFormat("[ATTACHMENT]: Cannot rez attachment in point {0} with itemID {1}", p, itemID);
+ // continue;
+ //}
+
+ try
+ {
+ string xmlData;
+ XmlDocument d = new XmlDocument();
+ UUID asset;
+ if (itemData.TryGetValue(itemID, out xmlData))
+ {
+ d.LoadXml(xmlData);
+ m_log.InfoFormat("[ATTACHMENT]: Found saved state for item {0}, loading it", itemID);
+
+ // Rez from inventory
+ asset
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, d);
+
+ }
+ else
+ {
+ // Rez from inventory (with a null doc to let
+ // CHANGED_OWNER happen)
+ asset
+ = m_scene.AttachmentsModule.RezSingleAttachmentFromInventory(ControllingClient, itemID, (uint)p, true, null);
+ }
+
+ m_log.InfoFormat(
+ "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
+ p, itemID, assetID, asset);
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat("[ATTACHMENT]: Unable to rez attachment: {0}", e.ToString());
+ }
+ }
+ }
+
+ private void ReprioritizeUpdates()
+ {
+ if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != UpdatePrioritizationSchemes.Time)
+ {
+ lock (m_reprioritization_timer)
+ {
+ if (!m_reprioritizing)
+ m_reprioritization_timer.Enabled = m_reprioritizing = true;
+ else
+ m_reprioritization_called = true;
+ }
+ }
+ }
+
+ private void Reprioritize(object sender, ElapsedEventArgs e)
+ {
+ m_controllingClient.ReprioritizeUpdates();
+
+ lock (m_reprioritization_timer)
+ {
+ m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called;
+ m_reprioritization_called = false;
+ }
+ }
+
+ private Vector3 Quat2Euler(Quaternion rot){
+ float x = Utils.RAD_TO_DEG * (float)Math.Atan2((double)((2.0f * rot.X * rot.W) - (2.0f * rot.Y * rot.Z)) ,
+ (double)(1 - (2.0f * rot.X * rot.X) - (2.0f * rot.Z * rot.Z)));
+ float y = Utils.RAD_TO_DEG * (float)Math.Asin ((double)((2.0f * rot.X * rot.Y) + (2.0f * rot.Z * rot.W)));
+ float z = Utils.RAD_TO_DEG * (float)Math.Atan2(((double)(2.0f * rot.Y * rot.W) - (2.0f * rot.X * rot.Z)) ,
+ (double)(1 - (2.0f * rot.Y * rot.Y) - (2.0f * rot.Z * rot.Z)));
+ return(new Vector3(x,y,z));
+ }
+
+
+ }
+}
--
cgit v1.1
From 1582e05ac78ac46708de84f5d35f79c935febd5b Mon Sep 17 00:00:00 2001
From: meta7
Date: Tue, 10 Aug 2010 09:55:40 -0700
Subject: Fix a nullref issue in the AgentSetAppearance packet handler when
removing the physactor from the scene
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 17 +++++++++++------
1 file changed, 11 insertions(+), 6 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3154872..4064339 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1090,12 +1090,17 @@ namespace OpenSim.Region.Framework.Scenes
{
if (PhysicsActor != null)
{
- m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
- m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
- m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
- m_physicsActor.UnSubscribeEvents();
- m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
- PhysicsActor = null;
+ try
+ {
+ m_physicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients;
+ m_physicsActor.OnOutOfBounds -= OutOfBoundsCall;
+ m_physicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate;
+ m_scene.PhysicsScene.RemoveAvatar(PhysicsActor);
+ m_physicsActor.UnSubscribeEvents();
+ PhysicsActor = null;
+ }
+ catch
+ { }
}
}
--
cgit v1.1
From eea5d8368acb9a7934e55b6e4b6ccddb40bc5611 Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Thu, 2 Sep 2010 20:08:39 +0200
Subject: Experimentally comment the sending of unbaked avatars
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cd80eb0..2acf8ff 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2806,7 +2806,9 @@ namespace OpenSim.Region.Framework.Scenes
m_controllingClient.SendAvatarDataImmediate(this);
SendInitialFullUpdateToAllClients();
- SendAppearanceToAllOtherAgents();
+ // Experimentally commenting this. We don't have bakes at this time
+ // and 1.23 will not display an avatar without bakes.
+ //SendAppearanceToAllOtherAgents();
}
///
--
cgit v1.1
From 5ea979d51517b11895a4c5431e3c3c02767a23ac Mon Sep 17 00:00:00 2001
From: Melanie Thielker
Date: Thu, 2 Sep 2010 20:51:27 +0200
Subject: Remove commented code and the comment, as the change has proven out
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 3 ---
1 file changed, 3 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2acf8ff..604ffad 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2806,9 +2806,6 @@ namespace OpenSim.Region.Framework.Scenes
m_controllingClient.SendAvatarDataImmediate(this);
SendInitialFullUpdateToAllClients();
- // Experimentally commenting this. We don't have bakes at this time
- // and 1.23 will not display an avatar without bakes.
- //SendAppearanceToAllOtherAgents();
}
///
--
cgit v1.1
From 16814dd8f18b51f5dd8841ae341847e117bb83b3 Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Thu, 2 Sep 2010 21:51:19 +0000
Subject: Fixes to JUMP system.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 66 ++++++++++++++++--------
1 file changed, 44 insertions(+), 22 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cd80eb0..f682ee5 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -1471,6 +1471,9 @@ namespace OpenSim.Region.Framework.Scenes
if (actor.Flying != oldflying)
update_movementflag = true;
+ if (m_animator.m_jumping) // add for jumping
+ update_movementflag = true;
+
if (q != m_bodyRot)
{
m_bodyRot = q;
@@ -2580,6 +2583,7 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.Info("[AGENT]: Stop FLying");
//}
}
+ /* This jumping section removed to SPA
else if (!actor.Flying && actor.IsColliding)
{
if (direc.Z > 2.0f)
@@ -2592,12 +2596,12 @@ namespace OpenSim.Region.Framework.Scenes
{
direc.Z *= 0.1f; // prejump
}
- /* Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
+ / * Animations are controlled via GetMovementAnimation() in ScenePresenceAnimator.cs
Animator.TrySetMovementAnimation("PREJUMP");
Animator.TrySetMovementAnimation("JUMP");
- */
+ * /
}
- }
+ } */
}
// TODO: Add the force instead of only setting it to support multiple forces per frame?
@@ -3543,28 +3547,46 @@ namespace OpenSim.Region.Framework.Scenes
///
public override void UpdateMovement()
{
- if (m_forceToApply.HasValue)
- {
+ if (Animator!=null) // add for jumping
+ { // add for jumping
+ // if (!m_animator.m_jumping) // add for jumping
+ // { // add for jumping
- Vector3 force = m_forceToApply.Value;
- m_updateflag = true;
- Velocity = force;
+ if (m_forceToApply.HasValue) // this section realigned
+ {
- m_forceToApply = null;
- }
- else
- {
- if (m_isNudging)
- {
- Vector3 force = Vector3.Zero;
+ Vector3 force = m_forceToApply.Value;
+ m_updateflag = true;
+if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
+ Velocity = force;
+//Console.WriteLine("UM1 {0}", Velocity);
+ m_forceToApply = null;
+ }
+ else
+ {
+ if (m_isNudging)
+ {
+ Vector3 force = Vector3.Zero;
+
+ m_updateflag = true;
+if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
+ Velocity = force;
+//Console.WriteLine("UM2 {0}", Velocity);
+ m_isNudging = false;
+ m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
+ }
+ else // add for jumping
+ { // add for jumping
+ Vector3 force = Vector3.Zero; // add for jumping
+if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for jumping
+//Console.WriteLine("UM3 {0}", Velocity);
+ Velocity = force; // add for jumping
+ }
- m_updateflag = true;
- Velocity = force;
- m_isNudging = false;
- m_updateCount = UPDATE_COUNT; //KF: Update anims to pickup "STAND"
- }
- }
- }
+ }
+ // } // end realign
+ } // add for jumping
+ } // add for jumping
///
/// Adds a physical representation of the avatar to the Physics plugin
--
cgit v1.1
From c719e016ed9bfbb56fd8c571b9b7b9622bcef566 Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Mon, 6 Sep 2010 21:45:07 +0000
Subject: Falling animation fix, comment out instrumentation.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 2ed00a0..faf6354 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2568,9 +2568,11 @@ namespace OpenSim.Region.Framework.Scenes
if (actor != null)
{
- if (actor.Flying)
+// rm falling if (actor.Flying)
+ if ((actor.Flying) || Animator.m_falling) // add for falling lateral speed
{
- direc *= 4.0f;
+// rm speed mod direc *= 4.0f;
+ direc *= 5.2f; // for speed mod
//bool controlland = (((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_UP_NEG) != 0) || ((m_AgentControlFlags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_UP_NEG) != 0));
//bool colliding = (m_physicsActor.IsColliding==true);
//if (controlland)
--
cgit v1.1
From 2f41bc4ca738cd27730639c8cd49a154404c6a82 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Tue, 14 Sep 2010 22:14:08 +0100
Subject: Fix merge issues
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index caf376b..ed92d86 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -4330,8 +4330,8 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
}
m_log.InfoFormat(
- "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2} ({3})",
- p, itemID, assetID, asset);
+ "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {3}",
+ p, itemID, asset);
}
catch (Exception e)
{
--
cgit v1.1
From ec89dc99b705f86fb4ed2f984125c2196d8c6288 Mon Sep 17 00:00:00 2001
From: root
Date: Thu, 16 Sep 2010 18:58:25 +0200
Subject: Some small bug fixes
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index ed92d86..8da9bdc 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -4330,7 +4330,7 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
}
m_log.InfoFormat(
- "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {3}",
+ "[ATTACHMENT]: Rezzed attachment in point {0} from item {1} and asset {2}",
p, itemID, asset);
}
catch (Exception e)
--
cgit v1.1
From 841c84831fedcfa40e0b0fa9c99990f6754591fa Mon Sep 17 00:00:00 2001
From: Melanie
Date: Mon, 27 Sep 2010 19:34:16 +0200
Subject: Try to prevent threading issues in SP.SetAppearance by locking it
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 85 +++++++++++++-----------
1 file changed, 45 insertions(+), 40 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index b3df1ea..ec3f004 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -229,6 +229,8 @@ namespace OpenSim.Region.Framework.Scenes
private const int NumMovementsBetweenRayCast = 5;
private List m_lastColliders = new List();
+ private object m_syncRoot = new Object();
+
private bool CameraConstraintActive;
//private int m_moveToPositionStateStatus;
//*****************************************************
@@ -2861,66 +2863,69 @@ namespace OpenSim.Region.Framework.Scenes
///
public void SetAppearance(Primitive.TextureEntry textureEntry, byte[] visualParams)
{
- if (m_physicsActor != null)
+ lock (m_syncRoot)
{
- if (!IsChildAgent)
+ if (m_physicsActor != null)
{
- // This may seem like it's redundant, remove the avatar from the physics scene
- // just to add it back again, but it saves us from having to update
- // 3 variables 10 times a second.
- bool flyingTemp = m_physicsActor.Flying;
- RemoveFromPhysicalScene();
- //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
+ if (!IsChildAgent)
+ {
+ // This may seem like it's redundant, remove the avatar from the physics scene
+ // just to add it back again, but it saves us from having to update
+ // 3 variables 10 times a second.
+ bool flyingTemp = m_physicsActor.Flying;
+ RemoveFromPhysicalScene();
+ //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
- //PhysicsActor = null;
+ //PhysicsActor = null;
- AddToPhysicalScene(flyingTemp);
+ AddToPhysicalScene(flyingTemp);
+ }
}
- }
- #region Bake Cache Check
+ #region Bake Cache Check
- if (textureEntry != null)
- {
- for (int i = 0; i < BAKE_INDICES.Length; i++)
+ if (textureEntry != null)
{
- int j = BAKE_INDICES[i];
- Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
-
- if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
+ for (int i = 0; i < BAKE_INDICES.Length; i++)
{
- if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
+ int j = BAKE_INDICES[i];
+ Primitive.TextureEntryFace face = textureEntry.FaceTextures[j];
+
+ if (face != null && face.TextureID != AppearanceManager.DEFAULT_AVATAR_TEXTURE)
{
- m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name);
- this.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
+ if (m_scene.AssetService.Get(face.TextureID.ToString()) == null)
+ {
+ m_log.Warn("[APPEARANCE]: Missing baked texture " + face.TextureID + " (" + j + ") for avatar " + this.Name);
+ this.ControllingClient.SendRebakeAvatarTextures(face.TextureID);
+ }
}
}
- }
- }
+ }
- #endregion Bake Cache Check
+ #endregion Bake Cache Check
- m_appearance.SetAppearance(textureEntry, visualParams);
- if (m_appearance.AvatarHeight > 0)
- SetHeight(m_appearance.AvatarHeight);
+ m_appearance.SetAppearance(textureEntry, visualParams);
+ if (m_appearance.AvatarHeight > 0)
+ SetHeight(m_appearance.AvatarHeight);
- // This is not needed, because only the transient data changed
- //AvatarData adata = new AvatarData(m_appearance);
- //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
+ // This is not needed, because only the transient data changed
+ //AvatarData adata = new AvatarData(m_appearance);
+ //m_scene.AvatarService.SetAvatar(m_controllingClient.AgentId, adata);
- SendAppearanceToAllOtherAgents();
- if (!m_startAnimationSet)
- {
- Animator.UpdateMovementAnimations();
- m_startAnimationSet = true;
- }
+ SendAppearanceToAllOtherAgents();
+ if (!m_startAnimationSet)
+ {
+ Animator.UpdateMovementAnimations();
+ m_startAnimationSet = true;
+ }
- Vector3 pos = m_pos;
- pos.Z += m_appearance.HipOffset;
+ Vector3 pos = m_pos;
+ pos.Z += m_appearance.HipOffset;
- m_controllingClient.SendAvatarDataImmediate(this);
+ m_controllingClient.SendAvatarDataImmediate(this);
+ }
}
public void SetWearable(int wearableId, AvatarWearable wearable)
--
cgit v1.1
From cf78f3fae311be4aa4c0ab37d2a7c8b6679fb22d Mon Sep 17 00:00:00 2001
From: Melanie
Date: Mon, 25 Oct 2010 00:53:38 +0200
Subject: Comment repeated add and remove of avatars from the physical scene.
It's no longer needed.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 38 ++++++++++++++----------
1 file changed, 22 insertions(+), 16 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 618f425..7bf0a99 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -2865,22 +2865,28 @@ namespace OpenSim.Region.Framework.Scenes
{
lock (m_syncRoot)
{
- if (m_physicsActor != null)
- {
- if (!IsChildAgent)
- {
- // This may seem like it's redundant, remove the avatar from the physics scene
- // just to add it back again, but it saves us from having to update
- // 3 variables 10 times a second.
- bool flyingTemp = m_physicsActor.Flying;
- RemoveFromPhysicalScene();
- //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
-
- //PhysicsActor = null;
-
- AddToPhysicalScene(flyingTemp);
- }
- }
+// MT: Commented this because it's no longer needed.
+// It used to be that the avatar height was calculated from the visual
+// params, so any call to this method could change the physical actor's
+// height. Now the height is supplied in the agent circuit data and never
+// changes here. So, we can leave physics alone.
+//
+// if (m_physicsActor != null)
+// {
+// if (!IsChildAgent)
+// {
+// // This may seem like it's redundant, remove the avatar from the physics scene
+// // just to add it back again, but it saves us from having to update
+// // 3 variables 10 times a second.
+// bool flyingTemp = m_physicsActor.Flying;
+// RemoveFromPhysicalScene();
+// //m_scene.PhysicsScene.RemoveAvatar(m_physicsActor);
+//
+// //PhysicsActor = null;
+//
+// AddToPhysicalScene(flyingTemp);
+// }
+// }
#region Bake Cache Check
--
cgit v1.1
From f985775962ae8da0010cc5ef5f903a53b550f5d2 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Fri, 5 Nov 2010 14:27:14 +0100
Subject: Revert "Fix for hanging on "Connecting to region".. caused by packets
being processed before the presence has bound to receive events. Fixed this
by adding packets to a queue and then processing them when the presence is
ready."
This reverts commit 91b1d17e5bd3ff6ed006744bc529b53a67af1a64.
Conflicts:
OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs
OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
OpenSim/Region/Framework/Scenes/ScenePresence.cs
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 84 ++++++++++++++++--------
1 file changed, 58 insertions(+), 26 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 3866647..ec39df8 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
- private Vector3 m_lastPosition;
+ private Vector3 m_lastPosition;
private Vector3 m_lastWorldPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
@@ -766,11 +766,8 @@ namespace OpenSim.Region.Framework.Scenes
// MIC: This gets called again in CompleteMovement
SendInitialFullUpdateToAllClients();
+
RegisterToEvents();
- if (m_controllingClient != null)
- {
- m_controllingClient.ProcessPendingPackets();
- }
SetDirectionVectors();
}
@@ -895,7 +892,11 @@ namespace OpenSim.Region.Framework.Scenes
m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
+<<<<<<< HEAD
m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
+=======
+ m_scene.SetRootAgentScene(m_uuid);
+>>>>>>> 91b1d17... Fix for hanging on "Connecting to region".. caused by packets being processed before the presence has bound to receive events. Fixed this by adding packets to a queue and then processing them when the presence is ready.
// Moved this from SendInitialData to ensure that m_appearance is initialized
// before the inventory is processed in MakeRootAgent. This fixes a race condition
@@ -911,6 +912,7 @@ namespace OpenSim.Region.Framework.Scenes
{
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
pos.Y = crossedBorder.BorderLine.Z - 1;
+<<<<<<< HEAD
}
//If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
@@ -927,6 +929,24 @@ namespace OpenSim.Region.Framework.Scenes
pos = land.LandData.UserLocation;
}
}
+=======
+ }
+
+ //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
+ //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
+ //they'll bypass the landing point. But I can't think of any decent way of fixing this.
+ if (KnownChildRegionHandles.Count == 0)
+ {
+ ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
+ if (land != null)
+ {
+ //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
+ if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
+ {
+ pos = land.LandData.UserLocation;
+ }
+ }
+>>>>>>> 91b1d17... Fix for hanging on "Connecting to region".. caused by packets being processed before the presence has bound to receive events. Fixed this by adding packets to a queue and then processing them when the presence is ready.
}
if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
@@ -1110,8 +1130,8 @@ namespace OpenSim.Region.Framework.Scenes
bool isFlying = false;
if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
+ isFlying = m_physicsActor.Flying;
+
RemoveFromPhysicalScene();
Velocity = Vector3.Zero;
AbsolutePosition = pos;
@@ -1122,7 +1142,7 @@ namespace OpenSim.Region.Framework.Scenes
SetHeight(m_appearance.AvatarHeight);
}
- SendTerseUpdateToAllClients();
+ SendTerseUpdateToAllClients();
}
@@ -1240,6 +1260,7 @@ namespace OpenSim.Region.Framework.Scenes
pos.Z = ground + 1.5f;
AbsolutePosition = pos;
}
+
m_isChildAgent = false;
bool m_flying = ((m_AgentControlFlags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0);
MakeRootAgent(AbsolutePosition, m_flying);
@@ -1827,14 +1848,14 @@ namespace OpenSim.Region.Framework.Scenes
// else
// { // single or child prim
-// }
- if (part == null) //CW: Part may be gone. llDie() for example.
- {
- partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- partRot = part.GetWorldRotation();
+// }
+ if (part == null) //CW: Part may be gone. llDie() for example.
+ {
+ partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ partRot = part.GetWorldRotation();
}
Quaternion partIRot = Quaternion.Inverse(partRot);
@@ -1842,6 +1863,7 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
+<<<<<<< HEAD
if (m_physicsActor == null)
{
@@ -1854,11 +1876,24 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
part.IsOccupied = false;
part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
+=======
+
+ if (m_physicsActor == null)
+ {
+ AddToPhysicalScene(false);
+>>>>>>> 91b1d17... Fix for hanging on "Connecting to region".. caused by packets being processed before the presence has bound to receive events. Fixed this by adding packets to a queue and then processing them when the presence is ready.
}
- else
- {
- //CW: Since the part doesn't exist, a coarse standup position isn't an issue
- AbsolutePosition = m_lastWorldPosition;
+ //CW: If the part isn't null then we can set the current position
+ if (part != null)
+ {
+ Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
+ AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
+ part.IsOccupied = false;
+ }
+ else
+ {
+ //CW: Since the part doesn't exist, a coarse standup position isn't an issue
+ AbsolutePosition = m_lastWorldPosition;
}
m_parentPosition = Vector3.Zero;
@@ -2022,7 +2057,7 @@ namespace OpenSim.Region.Framework.Scenes
// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
{
- autopilot = false; // close enough
+ autopilot = false; // close enough
m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
Not using the part's position because returning the AV to the last known standing
position is likely to be more friendly, isn't it? */
@@ -2032,7 +2067,7 @@ namespace OpenSim.Region.Framework.Scenes
} // else the autopilot will get us close
}
else
- { // its a scripted sit
+ { // its a scripted sit
m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
I *am* using the part's position this time because we have no real idea how far away
the avatar is from the sit target. */
@@ -3993,10 +4028,7 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
m_scene = scene;
RegisterToEvents();
- if (m_controllingClient != null)
- {
- m_controllingClient.ProcessPendingPackets();
- }
+
/*
AbsolutePosition = client.StartPos;
--
cgit v1.1
From 78448720671e364862ae5c17464ccf112bbf7034 Mon Sep 17 00:00:00 2001
From: Melanie
Date: Fri, 5 Nov 2010 14:46:13 +0100
Subject: Fix merge artefacts
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 73 ++++++------------------
1 file changed, 18 insertions(+), 55 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index ec39df8..b637317 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -127,7 +127,7 @@ namespace OpenSim.Region.Framework.Scenes
private Vector3 m_avInitialPos; // used to calculate unscripted sit rotation
private Vector3 m_avUnscriptedSitPos; // for non-scripted prims
- private Vector3 m_lastPosition;
+ private Vector3 m_lastPosition;
private Vector3 m_lastWorldPosition;
private Quaternion m_lastRotation;
private Vector3 m_lastVelocity;
@@ -892,11 +892,7 @@ namespace OpenSim.Region.Framework.Scenes
m_rootRegionHandle = m_scene.RegionInfo.RegionHandle;
-<<<<<<< HEAD
m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene);
-=======
- m_scene.SetRootAgentScene(m_uuid);
->>>>>>> 91b1d17... Fix for hanging on "Connecting to region".. caused by packets being processed before the presence has bound to receive events. Fixed this by adding packets to a queue and then processing them when the presence is ready.
// Moved this from SendInitialData to ensure that m_appearance is initialized
// before the inventory is processed in MakeRootAgent. This fixes a race condition
@@ -912,7 +908,6 @@ namespace OpenSim.Region.Framework.Scenes
{
Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N);
pos.Y = crossedBorder.BorderLine.Z - 1;
-<<<<<<< HEAD
}
//If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
@@ -929,24 +924,6 @@ namespace OpenSim.Region.Framework.Scenes
pos = land.LandData.UserLocation;
}
}
-=======
- }
-
- //If they're TP'ing in or logging in, we haven't had time to add any known child regions yet.
- //This has the unfortunate consequence that if somebody is TP'ing who is already a child agent,
- //they'll bypass the landing point. But I can't think of any decent way of fixing this.
- if (KnownChildRegionHandles.Count == 0)
- {
- ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y);
- if (land != null)
- {
- //Don't restrict gods, estate managers, or land owners to the TP point. This behaviour mimics agni.
- if (land.LandData.LandingType == (byte)1 && land.LandData.UserLocation != Vector3.Zero && m_userLevel < 200 && !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid) && land.LandData.OwnerID != m_uuid)
- {
- pos = land.LandData.UserLocation;
- }
- }
->>>>>>> 91b1d17... Fix for hanging on "Connecting to region".. caused by packets being processed before the presence has bound to receive events. Fixed this by adding packets to a queue and then processing them when the presence is ready.
}
if (pos.X < 0 || pos.Y < 0 || pos.Z < 0)
@@ -1130,8 +1107,8 @@ namespace OpenSim.Region.Framework.Scenes
bool isFlying = false;
if (m_physicsActor != null)
- isFlying = m_physicsActor.Flying;
-
+ isFlying = m_physicsActor.Flying;
+
RemoveFromPhysicalScene();
Velocity = Vector3.Zero;
AbsolutePosition = pos;
@@ -1142,7 +1119,7 @@ namespace OpenSim.Region.Framework.Scenes
SetHeight(m_appearance.AvatarHeight);
}
- SendTerseUpdateToAllClients();
+ SendTerseUpdateToAllClients();
}
@@ -1848,14 +1825,14 @@ namespace OpenSim.Region.Framework.Scenes
// else
// { // single or child prim
-// }
- if (part == null) //CW: Part may be gone. llDie() for example.
- {
- partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
- }
- else
- {
- partRot = part.GetWorldRotation();
+// }
+ if (part == null) //CW: Part may be gone. llDie() for example.
+ {
+ partRot = new Quaternion(0.0f, 0.0f, 0.0f, 1.0f);
+ }
+ else
+ {
+ partRot = part.GetWorldRotation();
}
Quaternion partIRot = Quaternion.Inverse(partRot);
@@ -1863,7 +1840,6 @@ namespace OpenSim.Region.Framework.Scenes
Quaternion avatarRot = Quaternion.Inverse(Quaternion.Inverse(Rotation) * partIRot); // world or. of the av
Vector3 avStandUp = new Vector3(1.0f, 0f, 0f) * avatarRot; // 1M infront of av
-<<<<<<< HEAD
if (m_physicsActor == null)
{
@@ -1876,24 +1852,11 @@ namespace OpenSim.Region.Framework.Scenes
AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
part.IsOccupied = false;
part.ParentGroup.DeleteAvatar(ControllingClient.AgentId);
-=======
-
- if (m_physicsActor == null)
- {
- AddToPhysicalScene(false);
->>>>>>> 91b1d17... Fix for hanging on "Connecting to region".. caused by packets being processed before the presence has bound to receive events. Fixed this by adding packets to a queue and then processing them when the presence is ready.
}
- //CW: If the part isn't null then we can set the current position
- if (part != null)
- {
- Vector3 avWorldStandUp = avStandUp + part.GetWorldPosition() + (m_pos * partRot); // + av sit offset!
- AbsolutePosition = avWorldStandUp; //KF: Fix stand up.
- part.IsOccupied = false;
- }
- else
- {
- //CW: Since the part doesn't exist, a coarse standup position isn't an issue
- AbsolutePosition = m_lastWorldPosition;
+ else
+ {
+ //CW: Since the part doesn't exist, a coarse standup position isn't an issue
+ AbsolutePosition = m_lastWorldPosition;
}
m_parentPosition = Vector3.Zero;
@@ -2057,7 +2020,7 @@ namespace OpenSim.Region.Framework.Scenes
// if (Util.GetDistanceTo(AbsolutePosition, autopilotTarget) < 4.5)
if( (Math.Abs(AbsolutePosition.X - autopilotTarget.X) < 256.0f) && (Math.Abs(AbsolutePosition.Y - autopilotTarget.Y) < 256.0f) )
{
- autopilot = false; // close enough
+ autopilot = false; // close enough
m_lastWorldPosition = m_pos; /* CW - This give us a position to return the avatar to if the part is killed before standup.
Not using the part's position because returning the AV to the last known standing
position is likely to be more friendly, isn't it? */
@@ -2067,7 +2030,7 @@ namespace OpenSim.Region.Framework.Scenes
} // else the autopilot will get us close
}
else
- { // its a scripted sit
+ { // its a scripted sit
m_lastWorldPosition = part.AbsolutePosition; /* CW - This give us a position to return the avatar to if the part is killed before standup.
I *am* using the part's position this time because we have no real idea how far away
the avatar is from the sit target. */
--
cgit v1.1
From 9462a1861b3a10467370380d11cf2e82a91c4ab7 Mon Sep 17 00:00:00 2001
From: Kitto Flora
Date: Thu, 11 Nov 2010 04:49:47 +0000
Subject: Fix excessive forward motion and flailing while descending a slope,
prevent adding motion while falling from flying.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 18 ++++++++++++++++--
1 file changed, 16 insertions(+), 2 deletions(-)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index b637317..f20eb33 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -161,6 +161,8 @@ namespace OpenSim.Region.Framework.Scenes
private bool m_setAlwaysRun;
private bool m_forceFly;
private bool m_flyDisabled;
+ private bool m_flyingOld; // add for fly velocity control
+ public bool m_wasFlying; // add for fly velocity control
private float m_speedModifier = 1.0f;
@@ -2564,14 +2566,22 @@ namespace OpenSim.Region.Framework.Scenes
Vector3 direc = vec * rotation;
direc.Normalize();
PhysicsActor actor = m_physicsActor;
+
+ if (actor.Flying != m_flyingOld) // add for fly velocity control
+ {
+ m_flyingOld = actor.Flying; // add for fly velocity control
+ if (!actor.Flying) m_wasFlying = true; // add for fly velocity control
+ }
+
+ if (m_physicsActor.IsColliding == true) m_wasFlying = false; // add for fly velocity control
+
if ((vec.Z == 0f) && !actor.Flying) direc.Z = 0f; // Prevent camera WASD up.
direc *= 0.03f * 128f * m_speedModifier;
if (actor != null)
{
-// rm falling if (actor.Flying)
- if ((actor.Flying) || Animator.m_falling) // add for falling lateral speed
+ if (actor.Flying)
{
// rm speed mod direc *= 4.0f;
direc *= 5.2f; // for speed mod
@@ -2587,6 +2597,10 @@ namespace OpenSim.Region.Framework.Scenes
// m_log.Info("[AGENT]: Stop FLying");
//}
}
+ if (Animator.m_falling && m_wasFlying) // if falling from flying, disable motion add
+ {
+ direc *= 0.0f;
+ }
/* This jumping section removed to SPA
else if (!actor.Flying && actor.IsColliding)
{
--
cgit v1.1
From 4f15b8d4e6be1e1fe88ad32aa43595861d1005ad Mon Sep 17 00:00:00 2001
From: Melanie
Date: Tue, 16 Nov 2010 20:44:39 +0100
Subject: Change the way attachments are persisted. Editing a worn attachment
will now save properly, as will the results of a resizer script working.
Attachment positions are no longer saved on each move, but instead are saved
once on logout. Attachment script states are saved as part of the attachment
now when detaching.
---
OpenSim/Region/Framework/Scenes/ScenePresence.cs | 18 ++++++++++++++++++
1 file changed, 18 insertions(+)
(limited to 'OpenSim/Region/Framework/Scenes/ScenePresence.cs')
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index cc9c445..dfaf06d 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -4340,6 +4340,24 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
return(new Vector3(x,y,z));
}
+ public void SaveChangedAttachments()
+ {
+ // Need to copy this list because DetachToInventoryPrep mods it
+ List attachments = new List