From 0149265ee83581cf2fb150dcd5d8734c02926261 Mon Sep 17 00:00:00 2001 From: CasperW Date: Sat, 21 Nov 2009 15:36:38 +0100 Subject: Improved avatar responsiveness. --- .../Region/ClientStack/LindenUDP/LLClientView.cs | 4 +- .../Region/ClientStack/LindenUDP/LLUDPServer.cs | 24 +++--- .../Region/ClientStack/LindenUDP/OpenSimUDPBase.cs | 89 +++++++++++++++++++--- .../Scenes/Animation/ScenePresenceAnimator.cs | 4 +- OpenSim/Region/Framework/Scenes/Scene.cs | 10 +-- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 80 +++++++++++++++---- 6 files changed, 163 insertions(+), 48 deletions(-) (limited to 'OpenSim/Region') diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 49b9378..39eb968 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -3121,7 +3121,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data); - OutPacket(objupdate, ThrottleOutPacketType.Task); } @@ -3172,8 +3171,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue(); } - // HACK: Using the task category until the tiered reprioritization code is in - OutPacket(terse, ThrottleOutPacketType.Task); + OutPacket(terse, ThrottleOutPacketType.State); } public void SendCoarseLocationUpdate(List users, List CoarseLocations) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs index 0b05ed9..4a7bdfe 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs @@ -571,23 +571,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Sorry, i know it's not optimal, but until the LL client //manages packets correctly and re-orders them as required, this is necessary. - if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate - || outgoingPacket.Type == PacketType.ChatFromSimulator - || outgoingPacket.Type == PacketType.ObjectUpdate - || outgoingPacket.Type == PacketType.LayerData) + + // Put the UDP payload on the wire + if (outgoingPacket.Type == PacketType.ImprovedTerseObjectUpdate) { - sendSynchronous = true; + SyncBeginPrioritySend(buffer, 2); // highest priority } - - // Put the UDP payload on the wire - if (sendSynchronous == true) + else if (outgoingPacket.Type == PacketType.ObjectUpdate + || outgoingPacket.Type == PacketType.ChatFromSimulator + || outgoingPacket.Type == PacketType.LayerData) { - SyncBeginSend(buffer); + SyncBeginPrioritySend(buffer, 1); // medium priority } else { - AsyncBeginSend(buffer); + SyncBeginPrioritySend(buffer, 0); // normal priority } + + //AsyncBeginSend(buffer); + // Keep track of when this packet was sent out (right now) outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; } @@ -862,7 +864,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); - AsyncBeginSend(buffer); + SyncBeginPrioritySend(buffer, 1); //Setting this to a medium priority should help minimise resends } private bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) diff --git a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs index 63579ac..45d9170 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/OpenSimUDPBase.cs @@ -29,6 +29,7 @@ using System; using System.Net; using System.Net.Sockets; using System.Threading; +using System.Collections.Generic; using log4net; namespace OpenMetaverse @@ -52,12 +53,25 @@ namespace OpenMetaverse /// Local IP address to bind to in server mode protected IPAddress m_localBindAddress; + /// + /// Standard queue for our outgoing SyncBeginPrioritySend + /// + private List m_standardQueue = new List(); + + /// + /// Prioritised queue for our outgoing SyncBeginPrioritySend + /// + private List m_priorityQueue = new List(); + /// UDP socket, used in either client or server mode private Socket m_udpSocket; /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; + /// Are we currently sending data asynchronously? + private volatile bool m_sendingData = false; + /// The all important shutdown flag private volatile bool m_shutdownFlag = true; @@ -246,25 +260,48 @@ namespace OpenMetaverse } } - public void SyncBeginSend(UDPPacketBuffer buf) + public void SyncBeginPrioritySend(UDPPacketBuffer buf, int Priority) { if (!m_shutdownFlag) { - try + if (!m_sendingData) { - m_udpSocket.SendTo( - buf.Data, - 0, - buf.DataLength, - SocketFlags.None, - buf.RemoteEndPoint); + m_sendingData = true; + try + { + AsyncBeginSend(buf); + } + catch (SocketException) { } + catch (ObjectDisposedException) { } + } + else + { + if (Priority == 2) + { + lock (m_priorityQueue) + { + m_priorityQueue.Add(buf); + } + } + else + { + lock (m_standardQueue) + { + if (Priority != 0) + { + m_standardQueue.Insert(0, buf); + } + else + { + m_standardQueue.Add(buf); + } + } + } } - catch (SocketException) { } - catch (ObjectDisposedException) { } } } - public void AsyncBeginSend(UDPPacketBuffer buf) + private void AsyncBeginSend(UDPPacketBuffer buf) { if (!m_shutdownFlag) { @@ -288,8 +325,36 @@ namespace OpenMetaverse { try { -// UDPPacketBuffer buf = (UDPPacketBuffer)result.AsyncState; m_udpSocket.EndSendTo(result); + + if (m_sendingData) + { + lock (m_priorityQueue) + { + if (m_priorityQueue.Count > 0) + { + UDPPacketBuffer buf = m_priorityQueue[0]; + m_priorityQueue.RemoveAt(0); + AsyncBeginSend(buf); + } + else + { + lock (m_standardQueue) + { + if (m_standardQueue.Count > 0) + { + UDPPacketBuffer buf = m_standardQueue[0]; + m_standardQueue.RemoveAt(0); + AsyncBeginSend(buf); + } + else + { + m_sendingData = false; + } + } + } + } + } } catch (SocketException) { } catch (ObjectDisposedException) { } diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index cbe4118..2230fba 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -156,8 +156,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation Vector3 left = Vector3.Transform(Vector3.UnitY, rotMatrix); // Check control flags - bool heldForward = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS; - bool heldBack = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG; + bool heldForward = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_AT_POS || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS); + bool heldBack = ((controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_AT_NEG || (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_NEG); bool heldLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_POS; bool heldRight = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG) == AgentManager.ControlFlags.AGENT_CONTROL_LEFT_NEG; //bool heldTurnLeft = (controlFlags & AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT) == AgentManager.ControlFlags.AGENT_CONTROL_TURN_LEFT; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a430b1e..5058457 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1164,16 +1164,16 @@ namespace OpenSim.Region.Framework.Scenes // Check if any objects have reached their targets CheckAtTargets(); - // Update SceneObjectGroups that have scheduled themselves for updates - // Objects queue their updates onto all scene presences - if (m_frame % m_update_objects == 0) - m_sceneGraph.UpdateObjectGroups(); - // Run through all ScenePresences looking for updates // Presence updates and queued object updates for each presence are sent to clients if (m_frame % m_update_presences == 0) m_sceneGraph.UpdatePresences(); + // Update SceneObjectGroups that have scheduled themselves for updates + // Objects queue their updates onto all scene presences + if (m_frame % m_update_objects == 0) + m_sceneGraph.UpdateObjectGroups(); + int TempPhysicsMS2 = Environment.TickCount; if ((m_frame % m_update_physics == 0) && m_physics_enabled) m_sceneGraph.UpdatePreparePhysics(); 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