示例#1
0
            /// <summary>
            /// Send appearance from all other root agents to this agent. this agent
            /// can be either root or child
            /// </summary>
            public void SendOtherAgentsAppearanceToMe()
            {
                int count = 0;

                m_sp.Scene.ForEachScenePresence(delegate(IScenePresence scenePresence)
                {
                    // only send information about root agents
                    if (scenePresence.IsChildAgent)
                    {
                        return;
                    }

                    // only send information about other root agents
                    if (scenePresence.UUID == m_sp.UUID)
                    {
                        return;
                    }

                    IAvatarAppearanceModule appearance = scenePresence.RequestModuleInterface <IAvatarAppearanceModule> ();
                    if (appearance != null)
                    {
                        appearance.SendAppearanceToAgent(m_sp);
                    }
                    count++;
                });

                IAgentUpdateMonitor reporter = (IAgentUpdateMonitor)m_sp.Scene.RequestModuleInterface <IMonitorModule> ().GetMonitor(m_sp.Scene.RegionInfo.RegionID.ToString(), "Agent Update Count");

                if (reporter != null)
                {
                    reporter.AddAgentUpdates(count);
                }
            }
示例#2
0
            /// <summary>
            /// Send this agent's appearance to all other root and child agents in the scene
            /// This agent must be root.
            /// </summary>
            public void SendAppearanceToAllOtherAgents()
            {
                // only send update from root agents to other clients; children are only "listening posts"
                if (m_sp.IsChildAgent)
                {
                    m_log.Warn("[SCENEPRESENCE] attempt to send avatar data from a child agent");
                    return;
                }

                int count = 0;

                m_sp.Scene.ForEachScenePresence(delegate(IScenePresence scenePresence)
                {
                    if (scenePresence.UUID == m_sp.UUID)
                    {
                        return;
                    }

                    SendAppearanceToAgent(scenePresence);
                    count++;
                });

                IAgentUpdateMonitor reporter = (IAgentUpdateMonitor)m_sp.Scene.RequestModuleInterface <IMonitorModule> ().GetMonitor(m_sp.Scene.RegionInfo.RegionID.ToString(), "Agent Update Count");

                if (reporter != null)
                {
                    reporter.AddAgentUpdates(count);
                }
            }
            public AvatarAppearanceModule(IScenePresence sp)
            {
                m_sp = sp;
                m_sp.Scene.EventManager.OnMakeRootAgent += EventManager_OnMakeRootAgent;

                AgentCircuitData circuitInfo = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID);

                if (circuitInfo.CachedUserInfo != null)
                {
                    Appearance = circuitInfo.CachedUserInfo.Appearance;
                }
                if (Appearance == null)
                {
                    Appearance = sp.Scene.AvatarService.GetAppearance(sp.UUID);
                }
                if (Appearance == null)
                {
                    MainConsole.Instance.Debug("[Scene]: No avatar appearance found for " + sp.Name);
                    Appearance = new AvatarAppearance(sp.UUID);
                }
                _updateMonitor = m_sp.Scene.RequestModuleInterface <IMonitorModule> ().GetMonitor <IAgentUpdateMonitor> (sp.Scene);
            }
            public AvatarAppearanceModule (IScenePresence sp)
            {
                m_sp = sp;
                m_sp.Scene.EventManager.OnMakeRootAgent += EventManager_OnMakeRootAgent;

                AgentCircuitData circuitInfo = sp.Scene.AuthenticateHandler.GetAgentCircuitData (sp.UUID);
                if (circuitInfo.CachedUserInfo != null)
                    Appearance = circuitInfo.CachedUserInfo.Appearance;
                if (Appearance == null)
                    Appearance = sp.Scene.AvatarService.GetAppearance (sp.UUID);
                if (Appearance == null) {
                    MainConsole.Instance.Debug ("[Scene]: No avatar appearance found for " + sp.Name);
                    Appearance = new AvatarAppearance (sp.UUID);
                }
                _updateMonitor = m_sp.Scene.RequestModuleInterface<IMonitorModule> ().GetMonitor<IAgentUpdateMonitor> (sp.Scene);
            }
示例#5
0
            /// <summary>
            ///     This is called by a timer and makes a SimStats class of the current stats that we have in this simulator.
            ///     It then sends the packet to the client and triggers the events to tell followers about the updated stats
            ///     and updates the LastSet* values for monitors.
            /// </summary>
            /// <param name="sender"></param>
            /// <param name="e"></param>
            private void statsHeartBeat(object sender, EventArgs e)
            {
                if (m_currentScene.PhysicsScene == null)
                {
                    return;
                }
                m_report.Stop();
                if (rb == null)
                {
                    buildInitialRegionBlock();
                }

                // Know what's not thread safe in Mono... modifying timers.
                lock (m_report)
                {
                    ISimFrameMonitor           simFrameMonitor         = GetMonitor <ISimFrameMonitor>();
                    ITimeDilationMonitor       timeDilationMonitor     = GetMonitor <ITimeDilationMonitor>();
                    ITotalFrameTimeMonitor     totalFrameMonitor       = GetMonitor <ITotalFrameTimeMonitor>();
                    ISleepFrameMonitor         sleepFrameMonitor       = GetMonitor <ISleepFrameMonitor>();
                    IOtherFrameMonitor         otherFrameMonitor       = GetMonitor <IOtherFrameMonitor>();
                    IPhysicsFrameMonitor       physicsFrameMonitor     = GetMonitor <IPhysicsFrameMonitor>();
                    IPhysicsSyncFrameMonitor   physicsSyncFrameMonitor = GetMonitor <IPhysicsSyncFrameMonitor>();
                    IPhysicsUpdateFrameMonitor physicsTimeFrameMonitor = GetMonitor <IPhysicsUpdateFrameMonitor>();
                    IAgentUpdateMonitor        agentUpdateFrameMonitor = GetMonitor <IAgentUpdateMonitor>();
                    INetworkMonitor            networkMonitor          = GetMonitor <INetworkMonitor>();
                    IImageFrameTimeMonitor     imagesMonitor           = GetMonitor <IImageFrameTimeMonitor>();
                    IScriptFrameTimeMonitor    scriptMonitor           = GetMonitor <IScriptFrameTimeMonitor>();
                    IScriptCountMonitor        totalScriptMonitor      = GetMonitor <IScriptCountMonitor>();

                    #region various statistic googly moogly

                    float simfps = simFrameMonitor.SimFPS / statsUpdateFactor;
                    // save the reported value so there is something available for llGetRegionFPS
                    simFrameMonitor.LastReportedSimFPS = simfps;

                    float physfps = physicsFrameMonitor.PhysicsFPS / statsUpdateFactor;
                    physicsFrameMonitor.LastReportedPhysicsFPS = physfps;
                    //Update the time dilation with the newest physicsFPS
                    timeDilationMonitor.SetPhysicsFPS(physfps);

                    #endregion

                    #region Add the stats packets

                    //Some info on this packet http://wiki.secondlife.com/wiki/Statistics_Bar_Guide

                    sb[0].StatID    = (uint)Stats.TimeDilation;
                    sb[0].StatValue = (float)timeDilationMonitor.GetValue();

                    sb[1].StatID    = (uint)Stats.FPS;
                    sb[1].StatValue = simfps;

                    float realsimfps = simfps * 2;

                    sb[2].StatID    = (uint)Stats.PhysFPS;
                    sb[2].StatValue = physfps;

                    sb[3].StatID    = (uint)Stats.AgentUpdates;
                    sb[3].StatValue = (agentUpdateFrameMonitor.AgentUpdates / realsimfps);

                    sb[4].StatID = (uint)Stats.FrameMS;
                    float TotalFrames = (float)(totalFrameMonitor.GetValue() / realsimfps);
                    sb[4].StatValue = TotalFrames;

                    sb[5].StatID    = (uint)Stats.NetMS;
                    sb[5].StatValue = 0; //TODO: Implement this

                    sb[6].StatID = (uint)Stats.SimOtherMS;
                    float otherMS = (float)(otherFrameMonitor.GetValue() / realsimfps);
                    sb[6].StatValue = otherMS;

                    sb[7].StatID = (uint)Stats.SimPhysicsMS;
                    float PhysicsMS = (float)(physicsTimeFrameMonitor.GetValue() / realsimfps);
                    sb[7].StatValue = PhysicsMS;

                    sb[8].StatID    = (uint)Stats.AgentMS;
                    sb[8].StatValue = (agentUpdateFrameMonitor.AgentFrameTime / realsimfps);

                    sb[9].StatID = (uint)Stats.ImagesMS;
                    float imageMS = (float)(imagesMonitor.GetValue() / realsimfps);
                    sb[9].StatValue = imageMS;

                    sb[10].StatID = (uint)Stats.ScriptMS;
                    float ScriptMS = (float)(scriptMonitor.GetValue() / realsimfps);
                    sb[10].StatValue = ScriptMS;

                    sb[11].StatID = (uint)Stats.TotalObjects;
                    sb[12].StatID = (uint)Stats.ActiveObjects;
                    sb[13].StatID = (uint)Stats.NumAgentMain;
                    sb[14].StatID = (uint)Stats.NumAgentChild;

                    IEntityCountModule entityCountModule = m_currentScene.RequestModuleInterface <IEntityCountModule>();
                    if (entityCountModule != null)
                    {
                        sb[11].StatValue = entityCountModule.Objects;

                        sb[12].StatValue = entityCountModule.ActiveObjects;

                        sb[13].StatValue = entityCountModule.RootAgents;

                        sb[14].StatValue = entityCountModule.ChildAgents;
                    }

                    sb[15].StatID    = (uint)Stats.NumScriptActive;
                    sb[15].StatValue = totalScriptMonitor.ActiveScripts;

                    sb[16].StatID    = (uint)Stats.LSLIPS;
                    sb[16].StatValue = 0; //This isn't used anymore, and has been superseeded by LSLEPS

                    sb[17].StatID    = (uint)Stats.InPPS;
                    sb[17].StatValue = (networkMonitor.InPacketsPerSecond / statsUpdateFactor);

                    sb[18].StatID    = (uint)Stats.OutPPS;
                    sb[18].StatValue = (networkMonitor.OutPacketsPerSecond / statsUpdateFactor);

                    sb[19].StatID    = (uint)Stats.PendingDownloads;
                    sb[19].StatValue = (networkMonitor.PendingDownloads);

                    sb[20].StatID    = (uint)Stats.PendingUploads;
                    sb[20].StatValue = (networkMonitor.PendingUploads);

                    //21 and 22 are forced to the GC memory as they WILL make memory usage go up rapidly otherwise!
                    sb[21].StatID    = (uint)Stats.VirtualSizeKB;
                    sb[21].StatValue = GC.GetTotalMemory(false) / 1024;
                    // System.Diagnostics.Process.GetCurrentProcess().WorkingSet64 / (1024);

                    sb[22].StatID    = (uint)Stats.ResidentSizeKB;
                    sb[22].StatValue = GC.GetTotalMemory(false) / 1024;
                    //(float)System.Diagnostics.Process.GetCurrentProcess().PrivateMemorySize64 / (1024);

                    sb[23].StatID    = (uint)Stats.PendingLocalUploads;
                    sb[23].StatValue = (networkMonitor.PendingUploads / statsUpdateFactor);

                    sb[24].StatID    = (uint)Stats.TotalUnackedBytes;
                    sb[24].StatValue = (networkMonitor.UnackedBytes);

                    sb[25].StatID    = (uint)Stats.PhysicsPinnedTasks;
                    sb[25].StatValue = 0;

                    sb[26].StatID    = (uint)Stats.PhysicsLODTasks;
                    sb[26].StatValue = 0;

                    sb[27].StatID    = (uint)Stats.SimPhysicsStepMS;
                    sb[27].StatValue = m_currentScene.PhysicsScene.StepTime;

                    sb[28].StatID    = (uint)Stats.SimPhysicsShape;
                    sb[28].StatValue = 0;

                    sb[29].StatID    = (uint)Stats.SimPhysicsOtherMS;
                    sb[29].StatValue = (float)(physicsSyncFrameMonitor.GetValue() / realsimfps);

                    sb[30].StatID    = (uint)Stats.SimPhysicsMemory;
                    sb[30].StatValue = 0;

                    sb[31].StatID    = (uint)Stats.ScriptEPS;
                    sb[31].StatValue = totalScriptMonitor.ScriptEPS / statsUpdateFactor;

                    sb[32].StatID = (uint)Stats.SimSpareTime;
                    //Spare time is the total time minus the stats that are in the same category in the client
                    // It is the sleep time, physics step, update physics shape, physics other, and pumpI0.
                    // Note: take out agent Update and script time for now, as they are not a part of the heartbeat right now and will mess this calc up
                    float SpareTime = TotalFrames - (
                        /*NetMS + */ PhysicsMS + otherMS + imageMS);
//                         + /*(agentUpdateFrameMonitor.AgentFrameTime / statsUpdateFactor) +*/
//                        (imagesMonitor.GetValue() / statsUpdateFactor) /* + ScriptMS*/));

                    sb[32].StatValue = SpareTime;

                    sb[33].StatID    = (uint)Stats.SimSleepTime;
                    sb[33].StatValue = (float)(sleepFrameMonitor.GetValue() / realsimfps);

                    sb[34].StatID    = (uint)Stats.IOPumpTime;
                    sb[34].StatValue = 0; //TODO: implement this

                    #endregion

                    for (int i = 0; i < sb.Length; i++)
                    {
                        if (float.IsInfinity(sb[i].StatValue) ||
                            float.IsNaN(sb[i].StatValue))
                        {
                            sb[i].StatValue = 0; //Don't send huge values
                        }
                        lastReportedSimStats[i] = sb[i].StatValue;
                    }

                    SimStats simStats
                        = new SimStats(rb, sb, m_currentScene.RegionInfo.RegionID);

                    //Fire the event and tell followers about the new stats
                    m_module.SendStatsResults(simStats);

                    //Tell all the scene presences about the new stats
                    foreach (IScenePresence agent in m_currentScene.GetScenePresences().Where(agent => !agent.IsChildAgent))
                    {
                        agent.ControllingClient.SendSimStats(simStats);
                    }

                    //Now fix any values that require reseting
                    ResetValues();
                }
                m_report.Start();
            }
示例#6
0
        /// <summary>
        ///   This method is called by the LLUDPServer and should never be called by anyone else
        ///   It loops through the available updates and sends them out (no waiting)
        /// </summary>
        /// <param name = "numUpdates">The number of updates to send</param>
        public void SendPrimUpdates(int numPrimUpdates, int numAvaUpdates)
        {
            if (m_numberOfLoops < NUMBER_OF_LOOPS_TO_WAIT)
            //Wait for the client to finish connecting fully before sending out bunches of updates
            {
                m_numberOfLoops++;
                return;
            }

            if (m_inUse || m_presence.IsInTransit)
            {
                return;
            }

            m_inUse = true;
            //This is for stats
            int AgentMS = Util.EnvironmentTickCount();

            #region New client entering the Scene, requires all objects in the Scene

            ///If we havn't started processing this client yet, we need to send them ALL the prims that we have in this Scene (and deal with culling as well...)
            if (!m_SentInitialObjects && m_presence.DrawDistance != 0.0f)
            {
                SendInitialObjects();
            }

            int presenceNumToSend       = numAvaUpdates;
            List <EntityUpdate> updates = new List <EntityUpdate>();
            lock (m_presenceUpdatesToSendLock)
            {
                //Send the numUpdates of them if that many
                // if we don't have that many, we send as many as possible, then switch to objects
                if (m_presenceUpdatesToSend.Count != 0)
                {
                    try
                    {
#if UseDictionaryForEntityUpdates
                        Dictionary <uint, EntityUpdate> .Enumerator e = m_presenceUpdatesToSend.GetEnumerator();
                        e.MoveNext();
                        List <uint> entitiesToRemove = new List <uint>();
#endif
                        int count = m_presenceUpdatesToSend.Count > presenceNumToSend
                                        ? presenceNumToSend
                                        : m_presenceUpdatesToSend.Count;
                        for (int i = 0; i < count; i++)
                        {
#if UseRemovingEntityUpdates
                            EntityUpdate update = ((EntityUpdate)m_presenceUpdatesToSend[0]);

                            /*if (m_EntitiesInPacketQueue.Contains (update.Entity.UUID))
                             * {
                             *  m_presenceUpdatesToSend.RemoveAt (0);
                             *  m_presenceUpdatesToSend.Insert (m_presenceUpdatesToSend.Count, update.Entity.UUID, update);
                             *  continue;
                             * }
                             * m_EntitiesInPacketQueue.Add (update.Entity.UUID);*/
                            m_presenceUpdatesToSend.RemoveAt(0);
                            if (update.Flags == PrimUpdateFlags.ForcedFullUpdate)
                            {
                                SendFullUpdateForPresence((IScenePresence)update.Entity);
                            }
                            else
                            {
                                updates.Add(update);
                            }
#elif UseDictionaryForEntityUpdates
                            EntityUpdate update = e.Current.Value;
                            entitiesToRemove.Add(update.Entity.LocalId); //Remove it later
                            if (update.Flags == PrimUpdateFlags.ForcedFullUpdate)
                            {
                                SendFullUpdateForPresence((IScenePresence)update.Entity);
                            }
                            else
                            {
                                updates.Add(update);
                            }
                            e.MoveNext();
#else
                            EntityUpdate update = m_presenceUpdatesToSend.Dequeue();
                            if (update.Flags == PrimUpdateFlags.ForcedFullUpdate)
                            {
                                SendFullUpdateForPresence((IScenePresence)update.Entity);
                            }
                            else
                            {
                                updates.Add(update);
                            }
#endif
                        }
#if UseDictionaryForEntityUpdates
                        foreach (uint id in entitiesToRemove)
                        {
                            m_presenceUpdatesToSend.Remove(id);
                        }
#endif
                    }
                    catch (Exception ex)
                    {
                        MainConsole.Instance.WarnFormat("[SceneViewer]: Exception while running presence loop: {0}", ex);
                    }
                }
            }
            if (updates.Count != 0)
            {
                presenceNumToSend -= updates.Count;
                m_presence.ControllingClient.SendAvatarUpdate(updates);
            }
            updates.Clear();

            List <AnimationGroup> animationsToSend = new List <AnimationGroup>();
            lock (m_presenceAnimationsToSendLock)
            {
                //Send the numUpdates of them if that many
                // if we don't have that many, we send as many as possible, then switch to objects
                if (m_presenceAnimationsToSend.Count != 0 && presenceNumToSend > 0)
                {
                    try
                    {
                        int count = m_presenceAnimationsToSend.Count > presenceNumToSend
                                        ? presenceNumToSend
                                        : m_presenceAnimationsToSend.Count;
                        for (int i = 0; i < count; i++)
                        {
                            AnimationGroup update = m_presenceAnimationsToSend.Dequeue();

                            /*if (m_AnimationsInPacketQueue.Contains (update.AvatarID))
                             * {
                             *  m_presenceAnimationsToSend.RemoveAt (0);
                             *  m_presenceAnimationsToSend.Insert (m_presenceAnimationsToSend.Count, update.AvatarID, update);
                             *  continue;
                             * }
                             * m_AnimationsInPacketQueue.Add (update.AvatarID);*/
                            animationsToSend.Add(update);
                        }
                    }
                    catch (Exception ex)
                    {
                        MainConsole.Instance.WarnFormat("[SceneViewer]: Exception while running presence loop: {0}", ex);
                    }
                }
            }
            foreach (AnimationGroup update in animationsToSend)
            {
                m_presence.ControllingClient.SendAnimations(update);
            }
            animationsToSend.Clear();

            int primsNumToSend = numPrimUpdates;

            List <IEntity> entities = new List <IEntity>();
            lock (m_objectPropertiesToSendLock)
            {
                //Send the numUpdates of them if that many
                // if we don't have that many, we send as many as possible, then switch to objects
                if (m_objectPropertiesToSend.Count != 0)
                {
                    try
                    {
                        int count = m_objectPropertiesToSend.Count > primsNumToSend
                                        ? primsNumToSend
                                        : m_objectPropertiesToSend.Count;
                        for (int i = 0; i < count; i++)
                        {
                            ISceneChildEntity entity = ((ISceneChildEntity)m_objectPropertiesToSend[0]);

                            /*if (m_PropertiesInPacketQueue.Contains (entity.UUID))
                             * {
                             *  m_objectPropertiesToSend.RemoveAt (0);
                             *  m_objectPropertiesToSend.Insert (m_objectPropertiesToSend.Count, entity.UUID, entity);
                             *  continue;
                             * }
                             * m_PropertiesInPacketQueue.Add (entity.UUID);*/
                            m_objectPropertiesToSend.RemoveAt(0);
                            entities.Add(entity);
                        }
                    }
                    catch (Exception ex)
                    {
                        MainConsole.Instance.WarnFormat("[SceneViewer]: Exception while running presence loop: {0}", ex);
                    }
                }
            }
            if (entities.Count > 0)
            {
                primsNumToSend -= entities.Count;
                m_presence.ControllingClient.SendObjectPropertiesReply(entities);
            }

            updates = new List <EntityUpdate>();
            lock (m_objectUpdatesToSendLock)
            {
                if (m_objectUpdatesToSend.Count != 0)
                {
                    try
                    {
                        int count = m_objectUpdatesToSend.Count > primsNumToSend
                                        ? primsNumToSend
                                        : m_objectUpdatesToSend.Count;
                        for (int i = 0; i < count; i++)
                        {
                            EntityUpdate update = ((EntityUpdate)m_objectUpdatesToSend[0]);

                            /*if (m_EntitiesInPacketQueue.Contains (update.Entity.UUID))
                             * {
                             *  m_objectUpdatesToSend.RemoveAt (0);
                             *  m_objectUpdatesToSend.Insert (m_objectUpdatesToSend.Count, update.Entity.UUID, update);
                             *  continue;
                             * }
                             * m_EntitiesInPacketQueue.Add (update.Entity.UUID);*/

                            //Fix the CRC for this update
                            //Increment the CRC code so that the client won't be sent a cached update for this
                            if (update.Flags != PrimUpdateFlags.PrimFlags)
                            {
                                ((ISceneChildEntity)update.Entity).CRC++;
                            }

                            updates.Add(update);
                            m_objectUpdatesToSend.RemoveAt(0);
                        }
                    }
                    catch (Exception ex)
                    {
                        MainConsole.Instance.WarnFormat("[SceneViewer]: Exception while running object loop: {0}", ex);
                    }
                    m_presence.ControllingClient.SendPrimUpdate(updates);
                }
            }


            //Add the time to the stats tracker
            IAgentUpdateMonitor reporter =
                (IAgentUpdateMonitor)
                m_presence.Scene.RequestModuleInterface <IMonitorModule>().GetMonitor(
                    m_presence.Scene.RegionInfo.RegionID.ToString(), MonitorModuleHelper.AgentUpdateCount);
            if (reporter != null)
            {
                reporter.AddAgentTime(Util.EnvironmentTickCountSubtract(AgentMS));
            }

            m_inUse = false;
        }
示例#7
0
        /// <summary>
        /// This method is called by the LLUDPServer and should never be called by anyone else
        /// It loops through the available updates and sends them out (no waiting)
        /// </summary>
        /// <param name="numUpdates">The number of updates to send</param>
        public void SendPrimUpdates(int numUpdates)
        {
            if (m_inUse)
            {
                return;
            }
            m_inUse = true;
            //This is for stats
            int AgentMS = Util.EnvironmentTickCount();

            #region New client entering the Scene, requires all objects in the Scene

            ///If we havn't started processing this client yet, we need to send them ALL the prims that we have in this Scene (and deal with culling as well...)
            if (!m_SentInitialObjects)
            {
                m_SentInitialObjects = true;
                //If they are not in this region, we check to make sure that we allow seeing into neighbors
                if (!m_presence.IsChildAgent || (m_presence.Scene.RegionInfo.SeeIntoThisSimFromNeighbor) && Culler != null && m_prioritizer != null)
                {
                    ISceneEntity[] entities = m_presence.Scene.Entities.GetEntities();
                    PriorityQueue <EntityUpdate, double> m_entsqueue = new PriorityQueue <EntityUpdate, double> (entities.Length);

                    // build a prioritized list of things we need to send

                    foreach (ISceneEntity e in entities)
                    {
                        if (e != null && e is SceneObjectGroup)
                        {
                            if (e.IsDeleted)
                            {
                                continue;
                            }

                            //Check for culling here!
                            if (!Culler.ShowEntityToClient(m_presence, e))
                            {
                                continue;
                            }

                            double priority = m_prioritizer.GetUpdatePriority(m_presence, e);
                            //Send the root object first!
                            EntityUpdate rootupdate = new EntityUpdate(e.RootChild, PrimUpdateFlags.FullUpdate);
                            PriorityQueueItem <EntityUpdate, double> rootitem = new PriorityQueueItem <EntityUpdate, double> ();
                            rootitem.Value    = rootupdate;
                            rootitem.Priority = priority;
                            m_entsqueue.Enqueue(rootitem);

                            foreach (ISceneChildEntity child in e.ChildrenEntities())
                            {
                                if (child == e.RootChild)
                                {
                                    continue; //Already sent
                                }
                                EntityUpdate update = new EntityUpdate(child, PrimUpdateFlags.FullUpdate);
                                PriorityQueueItem <EntityUpdate, double> item = new PriorityQueueItem <EntityUpdate, double> ();
                                item.Value    = update;
                                item.Priority = priority;
                                m_entsqueue.Enqueue(item);
                            }
                        }
                    }
                    entities = null;
                    // send them
                    SendQueued(m_entsqueue);
                }
            }

            lock (m_presenceUpdatesToSend)
            {
                int numToSend = (int)(numUpdates * PresenceSendPercentage);
                //Send the numUpdates of them if that many
                // if we don't have that many, we send as many as possible, then switch to objects
                if (m_presenceUpdatesToSend.Count != 0)
                {
                    int count = m_presenceUpdatesToSend.Count > numToSend ? numToSend : m_presenceUpdatesToSend.Count;
                    List <EntityUpdate> updates = new List <EntityUpdate> ();
                    for (int i = 0; i < count; i++)
                    {
                        updates.Add((EntityUpdate)m_presenceUpdatesToSend[0]);
                        m_presenceUpdatesToSend.RemoveAt(0);
                    }
                    //If we're first, we definitely got set, so we don't need to check this at all
                    m_ourPresenceHasUpdate = false;
                    m_presence.ControllingClient.SendPrimUpdate(updates);
                }
            }

            lock (m_objectUpdatesToSend)
            {
                int numToSend = (int)(numUpdates * PrimSendPercentage);
                if (m_objectUpdatesToSend.Count != 0)
                {
                    int count = m_objectUpdatesToSend.Count > numToSend ? numToSend : m_objectUpdatesToSend.Count;
                    List <EntityUpdate> updates = new List <EntityUpdate> ();
                    for (int i = 0; i < count; i++)
                    {
                        updates.Add((EntityUpdate)m_objectUpdatesToSend[0]);
                        m_objectUpdatesToSend.RemoveAt(0);
                    }
                    m_presence.ControllingClient.SendPrimUpdate(updates);
                }
            }

            //Add the time to the stats tracker
            IAgentUpdateMonitor reporter = (IAgentUpdateMonitor)m_presence.Scene.RequestModuleInterface <IMonitorModule> ().GetMonitor(m_presence.Scene.RegionInfo.RegionID.ToString(), "Agent Update Count");
            if (reporter != null)
            {
                reporter.AddAgentTime(Util.EnvironmentTickCountSubtract(AgentMS));
            }

            m_inUse = false;
        }