예제 #1
0
        private void DoSignificantClientMovement(object o)
        {
            ISceneEntity[] entities = m_presence.Scene.Entities.GetEntities(m_presence.AbsolutePosition, m_presence.DrawDistance);
            PriorityQueue <EntityUpdate, double> m_entsqueue = new PriorityQueue <EntityUpdate, double> (entities.Length);

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

            HashSet <ISceneEntity> NewGrpsInView = new HashSet <ISceneEntity> ();

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

                    //Check for culling here!
                    if (!Culler.ShowEntityToClient(m_presence, e))
                    {
                        continue; // if 2 far ignore
                    }
                    double priority = m_prioritizer.GetUpdatePriority(m_presence, e);
                    NewGrpsInView.Add(e);

                    if (lastGrpsInView.Contains(e))
                    {
                        continue;
                    }

                    //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;
            lastGrpsInView.Clear();
            lastGrpsInView.UnionWith(NewGrpsInView);
            NewGrpsInView.Clear();

            // send them
            SendQueued(m_entsqueue);
        }
예제 #2
0
 public void QueuePresenceForUpdate(IScenePresence presence, PrimUpdateFlags flags)
 {
     if (Culler == null || !Culler.ShowEntityToClient(m_presence, presence))
     {
         return; // if 2 far ignore
     }
     lock (m_presenceUpdatesToSend)
     {
         EntityUpdate o = (EntityUpdate)m_presenceUpdatesToSend[presence.UUID];
         if (o == null)
         {
             o = new EntityUpdate(presence, flags);
             if (m_presence.UUID == presence.UUID)
             {
                 //Its us, set us first!
                 m_ourPresenceHasUpdate = true;
                 m_presenceUpdatesToSend.Insert(0, presence.UUID, o);
             }
             else if (m_ourPresenceHasUpdate) //If this is set, we start inserting at 1 so that our updates go first
             // We can also safely assume that 1 is fine, because there has to be 0 already there set by us
             {
                 m_presenceUpdatesToSend.Insert(1, presence.UUID, o);
             }
             else //Set us at 0, no updates from us
             {
                 m_presenceUpdatesToSend.Insert(0, presence.UUID, o);
             }
         }
         else
         {
             o.Flags = o.Flags & flags;
             m_presenceUpdatesToSend[presence.UUID] = o;
         }
     }
 }
        public EntityUpdate RemoveNext()
        {
            if (m_size == 0)
            {
                throw new InvalidOperationException("Heap is empty");
            }

            EntityUpdate item = m_items[0];

            --m_size;
            if (m_size > 0)
            {
                EntityUpdate tmp = m_items[m_size];
                tmp.PriorityQueueIndex = 0;
                m_items[0]             = tmp;
                m_items[m_size]        = null;

                BubbleDown(0);
            }
            else if (m_items.Length > 4 * minCapacity)
            {
                m_items = new EntityUpdate[minCapacity];
            }

            return(item);
        }
예제 #4
0
        private void SendQueued(HashSet <ISceneEntity> entsqueue)
        {
            //NO LOCKING REQUIRED HERE, THE PRIORITYQUEUE IS LOCAL
            //Enqueue them all
            List <ISceneEntity> sortableList = new List <ISceneEntity>(entsqueue);

            sortableList.Sort(sortPriority);
            lock (m_objectUpdatesToSendLock)
            {
                foreach (ISceneEntity t in sortableList)
                {
                    //Always send the root child first!
                    EntityUpdate update = new EntityUpdate(t.RootChild, PrimUpdateFlags.ForcedFullUpdate);
                    QueueEntityUpdate(update);
                    foreach (ISceneChildEntity child in t.ChildrenEntities().Where(child => !child.IsRoot))
                    {
                        update = new EntityUpdate(child, PrimUpdateFlags.ForcedFullUpdate);
                        QueueEntityUpdate(update);
                    }
                }
            }

            m_lastUpdatePos = (m_presence.IsChildAgent)
                                  ? m_presence.AbsolutePosition
                                  : m_presence.CameraPosition;
        }
        public void RemoveAt(int index)
        {
            if (m_size == 0)
            {
                throw new InvalidOperationException("Heap is empty");
            }
            if (index >= m_size)
            {
                throw new ArgumentOutOfRangeException("index");
            }

            --m_size;
            if (m_size > 0)
            {
                if (index != m_size)
                {
                    EntityUpdate tmp = m_items[m_size];
                    tmp.PriorityQueueIndex = index;
                    m_items[index]         = tmp;

                    m_items[m_size] = null;
                    if (!BubbleUp(index))
                    {
                        BubbleDown(index);
                    }
                }
            }
            else if (m_items.Length > 4 * minCapacity)
            {
                m_items = new EntityUpdate[minCapacity];
            }
        }
        public void UpdateFromNew(EntityUpdate newupdate, int pqueue)
        {
            m_propsFlags |= newupdate.PropsFlags;
            PrimUpdateFlags newFlags = newupdate.Flags;

            if ((newFlags & PrimUpdateFlags.UpdateProbe) != 0)
            {
                m_flags &= ~PrimUpdateFlags.UpdateProbe;
            }

            if ((newFlags & PrimUpdateFlags.CancelKill) != 0)
            {
                if ((newFlags & PrimUpdateFlags.UpdateProbe) != 0)
                {
                    m_flags = PrimUpdateFlags.UpdateProbe;
                }
                else
                {
                    newFlags = PrimUpdateFlags.FullUpdatewithAnim;
                }
            }
            else
            {
                m_flags |= newFlags;
            }

            PriorityQueue = pqueue;
        }
        public static EntityUpdate Get(ISceneEntity entity, PrimUpdateFlags flags, bool sendfam, bool sendobj)
        {
            lock (m_poollock)
            {
                if (m_poolPtr >= 0)
                {
                    EntityUpdate eu = m_pool[m_poolPtr];
                    m_pool[m_poolPtr] = null;
                    m_poolPtr--;
                    //if (m_min > m_poolPtr)
                    //    m_min = m_poolPtr;
                    eu.Entity = entity;
                    eu.Flags  = flags;
                    ObjectPropertyUpdateFlags tmp = 0;
                    if (sendfam)
                    {
                        tmp |= ObjectPropertyUpdateFlags.Family;
                    }

                    if (sendobj)
                    {
                        tmp |= ObjectPropertyUpdateFlags.Object;
                    }

                    eu.PropsFlags = tmp;
                    return(eu);
                }
            }
            return(new EntityUpdate(entity, flags, sendfam, sendobj));
        }
        /// <summary>
        /// Enqueue an item into the specified priority queue
        /// </summary>
        public bool Enqueue(int pqueue, EntityUpdate value)
        {
            ulong        entry;
            EntityUpdate existentup;

            uint localid = value.Entity.LocalId;

            if (m_lookupTable.TryGetValue(localid, out existentup))
            {
                int eqqueue = existentup.PriorityQueue;

                existentup.UpdateFromNew(value, pqueue);
                value.Free();

                if (pqueue != eqqueue)
                {
                    m_heaps[eqqueue].RemoveAt(existentup.PriorityQueueIndex);
                    m_heaps[pqueue].Add(existentup);
                }
                return(true);
            }

            entry = m_nextRequest++;
            value.Update(pqueue, entry);

            m_heaps[pqueue].Add(value);
            m_lookupTable[localid] = value;
            return(true);
        }
        //private static int m_min = int.MaxValue;
        //private static int m_max = int.MinValue;

        static EntityUpdatesPool()
        {
            for (int i = 0; i < PREALLOC; ++i)
            {
                m_pool[i] = new EntityUpdate(null, 0);
            }
            m_poolPtr = PREALLOC - 1;
        }
        /// <summary>
        /// Remove an item from one of the queues. Specifically, it removes the
        /// oldest item from the next queue in order to provide fair access to
        /// all of the queues
        /// </summary>
        public bool TryDequeue(out EntityUpdate value)
        {
            // If there is anything in immediate queues, return it first no
            // matter what else. Breaks fairness. But very useful.

            for (int iq = 0; iq < NumberOfImmediateQueues; iq++)
            {
                if (m_heaps[iq].Count > 0)
                {
                    value = m_heaps[iq].RemoveNext();
                    return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
                }
            }

            // To get the fair queing, we cycle through each of the
            // queues when finding an element to dequeue.
            // We pull (NumberOfQueues - QueueIndex) items from each queue in order
            // to give lower numbered queues a higher priority and higher percentage
            // of the bandwidth.

            PriorityMinHeap curheap = m_heaps[m_nextQueue];

            // Check for more items to be pulled from the current queue
            if (m_countFromQueue > 0 && curheap.Count > 0)
            {
                --m_countFromQueue;

                value = curheap.RemoveNext();
                return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
            }

            // Find the next non-immediate queue with updates in it
            for (int i = NumberOfImmediateQueues; i < NumberOfQueues; ++i)
            {
                m_nextQueue++;
                if (m_nextQueue >= NumberOfQueues)
                {
                    m_nextQueue = NumberOfImmediateQueues;
                }

                curheap = m_heaps[m_nextQueue];
                if (curheap.Count == 0)
                {
                    continue;
                }

                m_countFromQueue = m_queueCounts[m_nextQueue];
                --m_countFromQueue;

                value = curheap.RemoveNext();
                return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
            }

            value = null;
            return(false);
        }
예제 #11
0
        /// <summary>
        /// Add the objects to the queue for which we need to send an update to the client
        /// </summary>
        /// <param name="part"></param>
        public void QueuePartForUpdate(ISceneChildEntity part, PrimUpdateFlags flags)
        {
            if (Culler == null || !Culler.ShowEntityToClient(m_presence, part.ParentEntity))
            {
                return; // if 2 far ignore
            }
            EntityUpdate o = new EntityUpdate(part, flags);

            QueueEntityUpdate(o);
        }
        public bool Remove(EntityUpdate value)
        {
            int index = value.PriorityQueueIndex;

            if (index != -1)
            {
                RemoveAt(index);
                return(true);
            }
            return(false);
        }
 public static void Free(EntityUpdate eu)
 {
     lock (m_poollock)
     {
         if (m_poolPtr < MAXSIZE - 1)
         {
             m_poolPtr++;
             //if (m_max < m_poolPtr)
             //    m_max = m_poolPtr;
             m_pool[m_poolPtr] = eu;
         }
     }
 }
예제 #14
0
        private void AddPresenceUpdate(IScenePresence presence, PrimUpdateFlags flags)
        {
            lock (m_presenceUpdatesToSendLock)
            {
#if UseRemovingEntityUpdates
                EntityUpdate o = (EntityUpdate)m_presenceUpdatesToSend[presence.UUID];
                if (o == null)
                {
                    o = new EntityUpdate(presence, flags);
                }
                else
                {
                    if ((o.Flags & flags) == o.Flags)
                    {
                        return; //Same, leave it alone!
                    }
                    o.Flags |= flags;
                    return;//All done, its updated
                }

                if (m_presence.UUID == presence.UUID) //Its us, set us first!
                {
                    m_presenceUpdatesToSend.Insert(0, presence.UUID, o);
                }
                else //Not us, set at the end
                {
                    m_presenceUpdatesToSend.Insert(m_presenceUpdatesToSend.Count, presence.UUID, o);
                }
#elif UseDictionaryForEntityUpdates
                EntityUpdate o = null;
                if (!m_presenceUpdatesToSend.TryGetValue(presence.LocalId, out o))
                {
                    o = new EntityUpdate(presence, flags);
                }
                else
                {
                    if ((o.Flags & flags) == o.Flags)
                    {
                        return; //Same, leave it alone!
                    }
                    o.Flags |= flags;
                    return; //All done, its updated, no need to readd
                }

                m_presenceUpdatesToSend[presence.LocalId] = o;
#else
                m_presenceUpdatesToSend.Enqueue(new EntityUpdate(presence, flags));
#endif
            }
        }
        public bool TryOrderedDequeue(out EntityUpdate value)
        {
            for (int iq = 0; iq < NumberOfQueues; ++iq)
            {
                PriorityMinHeap curheap = m_heaps[iq];
                if (curheap.Count > 0)
                {
                    value = curheap.RemoveNext();
                    return(m_lookupTable.TryRemove(value.Entity.LocalId, out value));
                }
            }

            value = null;
            return(false);
        }
예제 #16
0
 private void QueueEntityUpdate(EntityUpdate update)
 {
     lock (m_objectUpdatesToSend)
     {
         EntityUpdate o = (EntityUpdate)m_objectUpdatesToSend[update.Entity.UUID];
         if (o == null)
         {
             m_objectUpdatesToSend.Insert(0, update.Entity.UUID, update);
         }
         else
         {
             o.Flags = o.Flags & update.Flags;
             m_objectUpdatesToSend[update.Entity.UUID] = o;
         }
     }
 }
        private void BubbleDown(int index)
        {
            if (m_size < 2)
            {
                return;
            }

            EntityUpdate childItem;
            EntityUpdate childItemR;
            EntityUpdate item = m_items[index];

            ulong itemEntryOrder = item.EntryOrder;
            int   current;
            int   child;
            int   childlimit = m_size - 1;

            for (current = index, child = (2 * current) + 1;
                 current < m_size / 2;
                 current = child, child = (2 * current) + 1)
            {
                childItem = m_items[child];
                if (child < childlimit)
                {
                    childItemR = m_items[child + 1];

                    if (childItem.EntryOrder > childItemR.EntryOrder)
                    {
                        childItem = childItemR;
                        ++child;
                    }
                }
                if (childItem.EntryOrder >= itemEntryOrder)
                {
                    break;
                }

                childItem.PriorityQueueIndex = current;
                m_items[current]             = childItem;
            }

            if (current != index)
            {
                item.PriorityQueueIndex = current;
                m_items[current]        = item;
            }
        }
 public static EntityUpdate Get(ISceneEntity entity, PrimUpdateFlags flags)
 {
     lock (m_poollock)
     {
         if (m_poolPtr >= 0)
         {
             EntityUpdate eu = m_pool[m_poolPtr];
             m_pool[m_poolPtr] = null;
             m_poolPtr--;
             //if (m_min > m_poolPtr)
             //    m_min = m_poolPtr;
             eu.Entity = entity;
             eu.Flags  = flags;
             return(eu);
         }
     }
     return(new EntityUpdate(entity, flags));
 }
        public void Add(EntityUpdate value)
        {
            if (m_size == m_items.Length)
            {
                int newcapacity = (int)((m_items.Length * 200L) / 100L);
                if (newcapacity < (m_items.Length + MIN_CAPACITY))
                {
                    newcapacity = m_items.Length + MIN_CAPACITY;
                }
                Array.Resize <EntityUpdate>(ref m_items, newcapacity);
            }

            value.PriorityQueueIndex = m_size;
            m_items[m_size]          = value;

            BubbleUp(m_size);
            ++m_size;
        }
예제 #20
0
        /// <summary>
        ///   NOTE: DO THE LOCKING ON YOUR OWN
        /// </summary>
        /// <param name = "update"></param>
        private void QueueEntityUpdate(EntityUpdate update)
        {
            EntityUpdate o = (EntityUpdate)m_objectUpdatesToSend[update.Entity.UUID];

            if (o == null)
            {
                o = update;
            }
            else
            {
                if (o.Flags == update.Flags)
                {
                    return; //Same, leave it alone!
                }
                m_objectUpdatesToSend.Remove(update.Entity.UUID);
                o.Flags = o.Flags | update.Flags;
            }
            m_objectUpdatesToSend.Insert(m_objectUpdatesToSend.Count, o.Entity.UUID, o);
        }
예제 #21
0
        /// <summary>
        ///   Add the objects to the queue for which we need to send an update to the client
        /// </summary>
        /// <param name = "part"></param>
        public void QueuePartForUpdate(ISceneChildEntity part, PrimUpdateFlags flags)
        {
            if (m_presence == null)
            {
                return;
            }
            if (m_culler != null && !m_culler.ShowEntityToClient(m_presence, part.ParentEntity, m_scene))
            {
                //They are out of view and they changed, we need to update them when they do come in view
                lastGrpsInView.Remove(part.ParentEntity);
                return; // if 2 far ignore
            }
            if ((!(m_presence.DrawDistance > m_presence.Scene.RegionInfo.RegionSizeX &&
                   m_presence.DrawDistance > m_presence.Scene.RegionInfo.RegionSizeY)) &&
                !lastGrpsInView.Contains(part.ParentEntity))
            {
                //This object entered our draw distance on its own, and we havn't seen it before
                flags = PrimUpdateFlags.ForcedFullUpdate;
                lock (m_objectUpdatesToSendLock)
                {
#if (!ISWIN)
                    foreach (ISceneChildEntity child in part.ParentEntity.ChildrenEntities())
                    {
                        QueueEntityUpdate(new EntityUpdate(child, flags));
                    }
#else
                    foreach (EntityUpdate update in part.ParentEntity.ChildrenEntities().Select(child => new EntityUpdate(child, flags)))
                    {
                        QueueEntityUpdate(update);
                    }
#endif
                }
                lastGrpsInView.Add(part.ParentEntity);
                return;
            }

            EntityUpdate o = new EntityUpdate(part, flags);
            lock (m_objectUpdatesToSendLock)
                QueueEntityUpdate(o);
        }
        private bool BubbleUp(int index)
        {
            EntityUpdate tmp;
            EntityUpdate item = m_items[index];
            ulong        itemEntryOrder = item.EntryOrder;
            int          current, parent;

            for (current = index, parent = (current - 1) / 2;
                 (current > 0) && m_items[parent].EntryOrder > itemEntryOrder;
                 current = parent, parent = (current - 1) / 2)
            {
                tmp = m_items[parent];
                tmp.PriorityQueueIndex = current;
                m_items[current]       = tmp;
            }

            if (current != index)
            {
                item.PriorityQueueIndex = current;
                m_items[current]        = item;
                return(true);
            }
            return(false);
        }
예제 #23
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;
        }
예제 #24
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;
        }