From bf5c81d77e492cd6df5517ecab32cd64168b01c2 Mon Sep 17 00:00:00 2001
From: unknown
Date: Wed, 12 May 2010 15:59:48 -0700
Subject: * Initial commit of the slimupdates2 rewrite. This pass maintains the
 original behavior of avatar update sending and has a simplified set of
 IClientAPI methods for sending avatar/prim updates

---
 .../Region/ClientStack/LindenUDP/LLClientView.cs   | 627 ++++++++++-----------
 .../Region/ClientStack/LindenUDP/LLUDPServer.cs    |  18 +-
 .../Region/Examples/SimpleModule/MyNpcCharacter.cs |  14 +-
 OpenSim/Region/Framework/Scenes/SceneObjectPart.cs |  36 +-
 OpenSim/Region/Framework/Scenes/ScenePresence.cs   |  29 +-
 .../Server/IRCClientView.cs                        |  34 +-
 .../Region/OptionalModules/World/NPC/NPCAvatar.cs  |  14 +-
 7 files changed, 360 insertions(+), 412 deletions(-)

(limited to 'OpenSim/Region')

diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 1f3582c..6154da4 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -50,43 +50,17 @@ using Nini.Config;
 
 namespace OpenSim.Region.ClientStack.LindenUDP
 {
-    #region Enums
-
-    /// <summary>
-    /// Specifies the fields that have been changed when sending a prim or
-    /// avatar update
-    /// </summary>
-    [Flags]
-    public enum PrimUpdateFlags : uint
+    public class EntityUpdate
     {
-        None = 0,
-        AttachmentPoint = 1 << 0,
-        Material = 1 << 1,
-        ClickAction = 1 << 2,
-        Scale = 1 << 3,
-        ParentID = 1 << 4,
-        PrimFlags = 1 << 5,
-        PrimData = 1 << 6,
-        MediaURL = 1 << 7,
-        ScratchPad = 1 << 8,
-        Textures = 1 << 9,
-        TextureAnim = 1 << 10,
-        NameValue = 1 << 11,
-        Position = 1 << 12,
-        Rotation = 1 << 13,
-        Velocity = 1 << 14,
-        Acceleration = 1 << 15,
-        AngularVelocity = 1 << 16,
-        CollisionPlane = 1 << 17,
-        Text = 1 << 18,
-        Particles = 1 << 19,
-        ExtraData = 1 << 20,
-        Sound = 1 << 21,
-        Joint = 1 << 22,
-        FullUpdate = UInt32.MaxValue
-    }
+        public ISceneEntity Entity;
+        public PrimUpdateFlags Flags;
 
-    #endregion Enums
+        public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags)
+        {
+            Entity = entity;
+            Flags = flags;
+        }
+    }
 
     public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
 
@@ -350,9 +324,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         private readonly IGroupsModule m_GroupsModule;
 
         private int m_cachedTextureSerial;
-        protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
-        private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
-        private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
+        private PriorityQueue<double, EntityUpdate> m_entityUpdates;
 
         /// <value>
         /// List used in construction of data blocks for an object update packet.  This is to stop us having to
@@ -463,9 +435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             m_scene = scene;
 
-            m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
-            m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
-            m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
+            m_entityUpdates = new PriorityQueue<double, EntityUpdate>(m_scene.Entities.Count);
             m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
             m_killRecord = new HashSet<uint>();
 
@@ -1519,7 +1489,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             kill.Header.Reliable = true;
             kill.Header.Zerocoded = true;
 
-            lock (m_primFullUpdates.SyncRoot)
+            lock (m_entityUpdates.SyncRoot)
             {
                 m_killRecord.Add(localID);
                 OutPacket(kill, ThrottleOutPacketType.State);
@@ -3419,71 +3389,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         /// <summary>
         /// Send an ObjectUpdate packet with information about an avatar
         /// </summary>
-        public void SendAvatarData(SendAvatarData data)
+        public void SendAvatarDataImmediate(ISceneEntity avatar)
         {
+            ScenePresence presence = avatar as ScenePresence;
+            if (presence == null)
+                return;
+
             ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
             objupdate.Header.Zerocoded = true;
 
-            objupdate.RegionData.RegionHandle = data.RegionHandle;
+            objupdate.RegionData.RegionHandle = presence.RegionHandle;
             objupdate.RegionData.TimeDilation = ushort.MaxValue;
 
             objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
-            objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data);
+            objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
 
             OutPacket(objupdate, ThrottleOutPacketType.Task);
         }
 
-        /// <summary>
-        /// Send a terse positional/rotation/velocity update about an avatar
-        /// to the client.  This avatar can be that of the client itself.
-        /// </summary>
-        public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
-        {
-            if (data.Priority == double.NaN)
-            {
-                m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
-                return;
-            }
-
-            Quaternion rotation = data.Rotation;
-            if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
-                rotation = Quaternion.Identity;
-
-            ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data);
-
-            lock (m_avatarTerseUpdates.SyncRoot)
-                m_avatarTerseUpdates.Enqueue(data.Priority, terseBlock, data.LocalID);
-
-            // If we received an update about our own avatar, process the avatar update priority queue immediately
-            if (data.AgentID == m_agentId)
-                ProcessAvatarTerseUpdates();
-        }
-
-        protected void ProcessAvatarTerseUpdates()
-        {
-            ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
-            terse.Header.Reliable = false;
-            terse.Header.Zerocoded = true;
-
-            //terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock();
-            terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
-            terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
-
-            lock (m_avatarTerseUpdates.SyncRoot)
-            {
-                int count = Math.Min(m_avatarTerseUpdates.Count, m_udpServer.AvatarTerseUpdatesPerPacket);
-                if (count == 0)
-                    return;
-
-                terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
-                for (int i = 0; i < count; i++)
-                    terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
-            }
-
-            // HACK: Using the task category until the tiered reprioritization code is in
-            OutPacket(terse, ThrottleOutPacketType.Task);
-        }
-
         public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
         {
             if (!IsActive) return; // We don't need to update inactive clients.
@@ -3528,172 +3451,188 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
         #region Primitive Packet/Data Sending Methods
 
-        public void SendPrimitiveToClient(SendPrimitiveData data)
+        /// <summary>
+        /// Generate one of the object update packets based on PrimUpdateFlags 
+        /// and broadcast the packet to clients
+        /// </summary>
+        public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
         {
-//            string text = data.text;
-//            if (text.IndexOf("\n") >= 0)
-//                text = text.Remove(text.IndexOf("\n"));
-//            m_log.DebugFormat(
-//                "[CLIENT]: Placing request to send full info about prim {0} text {1} to client {2}", 
-//                data.localID, text, Name);
-            
-            if (data.priority == double.NaN)
-            {
-                m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
-                return;
-            }
-
-            Quaternion rotation = data.rotation;
-            if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
-                rotation = Quaternion.Identity;
-
-            if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
-                return;
-            if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9)
-                return;
+            double priority;
 
-            ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data);
+            if (entity is SceneObjectPart)
+                priority = ((SceneObjectPart)entity).ParentGroup.GetUpdatePriority(this);
+            else if (entity is ScenePresence)
+                priority = ((ScenePresence)entity).GetUpdatePriority(this);
+            else
+                priority = 0.0d;
 
-            lock (m_primFullUpdates.SyncRoot)
-                m_primFullUpdates.Enqueue(data.priority, objectData, data.localID);
+            lock (m_entityUpdates.SyncRoot)
+                m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags), entity.LocalId);
         }
 
-        void ProcessPrimFullUpdates()
+        private void ProcessEntityUpdates(int maxUpdates)
         {
-            ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
-            outPacket.Header.Zerocoded = true;
+            Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
+            Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
+            Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
 
-            outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
-            outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
+            int updatesThisCall = 0;
 
-            lock (m_primFullUpdates.SyncRoot)
+            lock (m_entityUpdates.SyncRoot)
             {
-                int count = Math.Min(m_primFullUpdates.Count, m_udpServer.PrimFullUpdatesPerPacket);
-                if (count == 0)
-                    return;
-
-                m_fullUpdateDataBlocksBuilder.Clear();
-                                
-                for (int i = 0; i < count; i++)
+                EntityUpdate update;
+                while (m_entityUpdates.TryDequeue(out update))
                 {
-                    ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue();
+                    #region UpdateFlags to packet type conversion
+
+                    PrimUpdateFlags updateFlags = update.Flags;
 
-                    if (!m_killRecord.Contains(block.ID))
+                    bool canUseCompressed = true;
+                    bool canUseImproved = true;
+
+                    // Compressed object updates only make sense for LL primitives
+                    if (!(update.Entity is SceneObjectPart))
+                        canUseCompressed = false;
+
+                    if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
                     {
-                        m_fullUpdateDataBlocksBuilder.Add(block);
-                        
-//                    string text = Util.FieldToString(outPacket.ObjectData[i].Text);
-//                    if (text.IndexOf("\n") >= 0)
-//                        text = text.Remove(text.IndexOf("\n"));
-//                    m_log.DebugFormat(
-//                        "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", 
-//                        outPacket.ObjectData[i].ID, text, Name);
+                        canUseCompressed = false;
+                        canUseImproved = false;
+                    }
+                    else
+                    {
+                        if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Joint))
+                        {
+                            canUseCompressed = false;
+                        }
+
+                        if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Text) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Material) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
+                            updateFlags.HasFlag(PrimUpdateFlags.Joint))
+                        {
+                            canUseImproved = false;
+                        }
+                    }
+
+                    #endregion UpdateFlags to packet type conversion
+
+                    #region Block Construction
+
+                    // TODO: Remove this once we can build compressed updates
+                    canUseCompressed = false;
+
+                    if (!canUseImproved && !canUseCompressed)
+                    {
+                        if (update.Entity is ScenePresence)
+                            objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
+                        else
+                            objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
                     }
-//                    else
-//                    {
-//                        m_log.WarnFormat(
-//                            "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name);                        
-//                    }
+                    else if (!canUseImproved)
+                    {
+                        compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
+                    }
+                    else
+                    {
+                        terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
+                    }
+
+                    #endregion Block Construction
+
+                    ++updatesThisCall;
+                    if (maxUpdates > 0 && updatesThisCall >= maxUpdates)
+                        break;
                 }
+            }
 
-                outPacket.ObjectData = m_fullUpdateDataBlocksBuilder.ToArray();
-                
-                OutPacket(outPacket, ThrottleOutPacketType.State);
-            }            
-        }
+            #region Packet Sending
 
-        public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
-        {
-            if (data.Priority == double.NaN)
+            const float TIME_DILATION = 1.0f;
+            ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
+
+            if (objectUpdateBlocks.IsValueCreated)
             {
-                m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update");
-                return;
-            }
+                List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
 
-            Quaternion rotation = data.Rotation;
-            if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
-                rotation = Quaternion.Identity;
+                ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
+                packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
+                packet.RegionData.TimeDilation = timeDilation;
+                packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
 
-            if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD
-                return;
+                for (int i = 0; i < blocks.Count; i++)
+                    packet.ObjectData[i] = blocks[i];
+
+                OutPacket(packet, ThrottleOutPacketType.Task, true);
+            }
 
-            ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data);
+            if (compressedUpdateBlocks.IsValueCreated)
+            {
+                List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
 
-            lock (m_primTerseUpdates.SyncRoot)
-                m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID);
-        }
+                ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
+                packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
+                packet.RegionData.TimeDilation = timeDilation;
+                packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
 
-        void ProcessPrimTerseUpdates()
-        {
-            ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
-            outPacket.Header.Reliable = false;
-            outPacket.Header.Zerocoded = true;
+                for (int i = 0; i < blocks.Count; i++)
+                    packet.ObjectData[i] = blocks[i];
 
-            outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
-            outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
+                OutPacket(packet, ThrottleOutPacketType.Task, true);
+            }
 
-            lock (m_primTerseUpdates.SyncRoot)
+            if (terseUpdateBlocks.IsValueCreated)
             {
-                int count = Math.Min(m_primTerseUpdates.Count, m_udpServer.PrimTerseUpdatesPerPacket);
-                if (count == 0)
-                    return;
+                List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
+
+                ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
+                packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
+                packet.RegionData.TimeDilation = timeDilation;
+                packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
 
-                outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
-                for (int i = 0; i < count; i++)
-                    outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
+                for (int i = 0; i < blocks.Count; i++)
+                    packet.ObjectData[i] = blocks[i];
+
+                OutPacket(packet, ThrottleOutPacketType.Task, true);
             }
 
-            OutPacket(outPacket, ThrottleOutPacketType.State);
+            #endregion Packet Sending
         }
 
-        public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
+        public void ReprioritizeUpdates(UpdatePriorityHandler handler)
         {
-            PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler =
-                delegate(ref double priority, uint local_id)
-                {
-                    priority = handler(new UpdatePriorityData(priority, local_id));
-                    return priority != double.NaN;
-                };
-            PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
+            //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
+
+            PriorityQueue<double, EntityUpdate>.UpdatePriorityHandler update_priority_handler =
                 delegate(ref double priority, uint local_id)
                 {
                     priority = handler(new UpdatePriorityData(priority, local_id));
                     return priority != double.NaN;
                 };
 
-            if ((type & StateUpdateTypes.AvatarTerse) != 0)
-            {
-                lock (m_avatarTerseUpdates.SyncRoot)
-                    m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler);
-            }
-
-            if ((type & StateUpdateTypes.PrimitiveFull) != 0)
-            {
-                lock (m_primFullUpdates.SyncRoot)
-                    m_primFullUpdates.Reprioritize(update_priority_handler);
-            }
-
-            if ((type & StateUpdateTypes.PrimitiveTerse) != 0)
-            {
-                lock (m_primTerseUpdates.SyncRoot)
-                    m_primTerseUpdates.Reprioritize(terse_update_priority_handler);
-            }
+            lock (m_entityUpdates.SyncRoot)
+                m_entityUpdates.Reprioritize(update_priority_handler);
         }
 
         public void FlushPrimUpdates()
         {
-            while (m_primFullUpdates.Count > 0)
-            {
-                ProcessPrimFullUpdates();
-            }
-            while (m_primTerseUpdates.Count > 0)
-            {
-                ProcessPrimTerseUpdates();
-            }
-            while (m_avatarTerseUpdates.Count > 0)
-            {
-                ProcessAvatarTerseUpdates();
-            }
+            m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
+
+            while (m_entityUpdates.Count > 0)
+                ProcessEntityUpdates(-1);
         }
 
         #endregion Primitive Packet/Data Sending Methods
@@ -3726,26 +3665,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
         {
             if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
             {
-                lock (m_avatarTerseUpdates.SyncRoot)
-                {
-                    if (m_avatarTerseUpdates.Count > 0)
-                        ProcessAvatarTerseUpdates();
-                }
-            }
-
-            if ((categories & ThrottleOutPacketTypeFlags.State) != 0)
-            {
-                lock (m_primFullUpdates.SyncRoot)
-                {
-                    if (m_primFullUpdates.Count > 0)
-                        ProcessPrimFullUpdates();
-                }
-
-                lock (m_primTerseUpdates.SyncRoot)
-                {
-                    if (m_primTerseUpdates.Count > 0)
-                        ProcessPrimTerseUpdates();
-                }
+                if (m_entityUpdates.Count > 0)
+                    ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback);
             }
 
             if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
@@ -4403,22 +4324,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
         #region Helper Methods
 
-        protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data)
+        protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture)
         {
-            return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity,
-                data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
-        }
+            #region ScenePresence/SOP Handling
 
-        protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data)
-        {
-            return CreateImprovedTerseBlock(false, data.LocalID, data.AttachPoint, Vector4.Zero, data.Position, data.Velocity,
-                data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry);
-        }
+            bool avatar = (entity is ScenePresence);
+            uint localID = entity.LocalId;
+            uint attachPoint;
+            Vector4 collisionPlane;
+            Vector3 position, velocity, acceleration, angularVelocity;
+            Quaternion rotation;
+            byte[] textureEntry;
+
+            if (entity is ScenePresence)
+            {
+                ScenePresence presence = (ScenePresence)entity;
+
+                attachPoint = 0;
+                collisionPlane = presence.CollisionPlane;
+                position = presence.OffsetPosition;
+                velocity = presence.Velocity;
+                acceleration = Vector3.Zero;
+                angularVelocity = Vector3.Zero;
+                rotation = presence.Rotation;
+
+                if (sendTexture)
+                    textureEntry = presence.Appearance.Texture.GetBytes();
+                else
+                    textureEntry = null;
+            }
+            else
+            {
+                SceneObjectPart part = (SceneObjectPart)entity;
+
+                attachPoint = part.AttachmentPoint;
+                collisionPlane = Vector4.Zero;
+                position = part.RelativePosition;
+                velocity = part.Velocity;
+                acceleration = part.Acceleration;
+                angularVelocity = part.AngularVelocity;
+                rotation = part.RotationOffset;
+                textureEntry = part.Shape.TextureEntry;
+            }
+
+            #endregion ScenePresence/SOP Handling
 
-        protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, int attachPoint,
-            Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
-            Vector3 angularVelocity, byte[] textureEntry)
-        {
             int pos = 0;
             byte[] data = new byte[(avatar ? 60 : 44)];
 
@@ -4490,12 +4440,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             return block;
         }
 
-        protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data)
+        protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
         {
             byte[] objectData = new byte[76];
 
-            Vector4.UnitW.ToBytes(objectData, 0); // TODO: Collision plane support
-            data.Position.ToBytes(objectData, 16);
+            data.CollisionPlane.ToBytes(objectData, 0);
+            data.OffsetPosition.ToBytes(objectData, 16);
             //data.Velocity.ToBytes(objectData, 28);
             //data.Acceleration.ToBytes(objectData, 40);
             data.Rotation.ToBytes(objectData, 52);
@@ -4505,12 +4455,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
             update.Data = Utils.EmptyBytes;
             update.ExtraParams = new byte[1];
-            update.FullID = data.AvatarID;
-            update.ID = data.AvatarLocalID;
+            update.FullID = data.UUID;
+            update.ID = data.LocalId;
             update.Material = (byte)Material.Flesh;
             update.MediaURL = Utils.EmptyBytes;
-            update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " +
-                data.LastName + "\nTitle STRING RW SV " + data.GroupTitle);
+            update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
+                data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
             update.ObjectData = objectData;
             update.ParentID = data.ParentID;
             update.PathCurve = 16;
@@ -4519,102 +4469,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             update.PCode = (byte)PCode.Avatar;
             update.ProfileCurve = 1;
             update.PSBlock = Utils.EmptyBytes;
-            update.Scale = new Vector3(0.45f,0.6f,1.9f);
+            update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
             update.Text = Utils.EmptyBytes;
             update.TextColor = new byte[4];
             update.TextureAnim = Utils.EmptyBytes;
-            update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes;
-            update.UpdateFlags = (uint)(PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | PrimFlags.ObjectOwnerModify);//61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags
+            update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
+            update.UpdateFlags = (uint)(
+                PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
+                PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
+                PrimFlags.ObjectOwnerModify);
 
             return update;
         }
 
-        protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data)
+        protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
         {
             byte[] objectData = new byte[60];
-            data.pos.ToBytes(objectData, 0);
-            data.vel.ToBytes(objectData, 12);
-            data.acc.ToBytes(objectData, 24);
-            data.rotation.ToBytes(objectData, 36);
-            data.rvel.ToBytes(objectData, 48);
+            data.RelativePosition.ToBytes(objectData, 0);
+            data.Velocity.ToBytes(objectData, 12);
+            data.Acceleration.ToBytes(objectData, 24);
+            data.RotationOffset.ToBytes(objectData, 36);
+            data.AngularVelocity.ToBytes(objectData, 48);
 
             ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
-            update.ClickAction = (byte)data.clickAction;
+            update.ClickAction = (byte)data.ClickAction;
             update.CRC = 0;
-            update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes;
-            update.FullID = data.objectID;
-            update.ID = data.localID;
+            update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes;
+            update.FullID = data.UUID;
+            update.ID = data.LocalId;
             //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
             //update.JointPivot = Vector3.Zero;
             //update.JointType = 0;
-            update.Material = data.material;
+            update.Material = data.Material;
             update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
-            if (data.attachment)
+            if (data.IsAttachment)
             {
-                update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId);
-                update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16));
+                update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
+                update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16));
             }
             else
             {
                 update.NameValue = Utils.EmptyBytes;
-                update.State = data.primShape.State;
+                update.State = data.Shape.State;
             }
+
             update.ObjectData = objectData;
-            update.ParentID = data.parentID;
-            update.PathBegin = data.primShape.PathBegin;
-            update.PathCurve = data.primShape.PathCurve;
-            update.PathEnd = data.primShape.PathEnd;
-            update.PathRadiusOffset = data.primShape.PathRadiusOffset;
-            update.PathRevolutions = data.primShape.PathRevolutions;
-            update.PathScaleX = data.primShape.PathScaleX;
-            update.PathScaleY = data.primShape.PathScaleY;
-            update.PathShearX = data.primShape.PathShearX;
-            update.PathShearY = data.primShape.PathShearY;
-            update.PathSkew = data.primShape.PathSkew;
-            update.PathTaperX = data.primShape.PathTaperX;
-            update.PathTaperY = data.primShape.PathTaperY;
-            update.PathTwist = data.primShape.PathTwist;
-            update.PathTwistBegin = data.primShape.PathTwistBegin;
-            update.PCode = data.primShape.PCode;
-            update.ProfileBegin = data.primShape.ProfileBegin;
-            update.ProfileCurve = data.primShape.ProfileCurve;
-            update.ProfileEnd = data.primShape.ProfileEnd;
-            update.ProfileHollow = data.primShape.ProfileHollow;
-            update.PSBlock = data.particleSystem ?? Utils.EmptyBytes;
-            update.TextColor = data.color ?? Color4.Black.GetBytes(true);
-            update.TextureAnim = data.textureanim ?? Utils.EmptyBytes;
-            update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes;
-            update.Scale = data.primShape.Scale;
-            update.Text = Util.StringToBytes256(data.text);
-            update.UpdateFlags = (uint)data.flags;
-
-            if (data.SoundId != UUID.Zero)
-            {
-                update.Sound = data.SoundId;
-                update.OwnerID = data.ownerID;
-                update.Gain = (float)data.SoundVolume;
+            update.ParentID = data.ParentID;
+            update.PathBegin = data.Shape.PathBegin;
+            update.PathCurve = data.Shape.PathCurve;
+            update.PathEnd = data.Shape.PathEnd;
+            update.PathRadiusOffset = data.Shape.PathRadiusOffset;
+            update.PathRevolutions = data.Shape.PathRevolutions;
+            update.PathScaleX = data.Shape.PathScaleX;
+            update.PathScaleY = data.Shape.PathScaleY;
+            update.PathShearX = data.Shape.PathShearX;
+            update.PathShearY = data.Shape.PathShearY;
+            update.PathSkew = data.Shape.PathSkew;
+            update.PathTaperX = data.Shape.PathTaperX;
+            update.PathTaperY = data.Shape.PathTaperY;
+            update.PathTwist = data.Shape.PathTwist;
+            update.PathTwistBegin = data.Shape.PathTwistBegin;
+            update.PCode = data.Shape.PCode;
+            update.ProfileBegin = data.Shape.ProfileBegin;
+            update.ProfileCurve = data.Shape.ProfileCurve;
+            update.ProfileEnd = data.Shape.ProfileEnd;
+            update.ProfileHollow = data.Shape.ProfileHollow;
+            update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes;
+            update.TextColor = data.GetTextColor().GetBytes(false);
+            update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes;
+            update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
+            update.Scale = data.Shape.Scale;
+            update.Text = Util.StringToBytes256(data.Text);
+
+            #region PrimFlags
+
+            PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID);
+
+            // Don't send the CreateSelected flag to everyone
+            flags &= ~PrimFlags.CreateSelected;
+
+            if (recipientID == data.OwnerID)
+            {
+                if ((data.Flags & PrimFlags.CreateSelected) != 0)
+                {
+                    // Only send this flag once, then unset it
+                    flags |= PrimFlags.CreateSelected;
+                    data.Flags &= ~PrimFlags.CreateSelected;
+                }
+            }
+
+            update.UpdateFlags = (uint)flags;
+
+            #endregion PrimFlags
+
+            if (data.Sound != UUID.Zero)
+            {
+                update.Sound = data.Sound;
+                update.OwnerID = data.OwnerID;
+                update.Gain = (float)data.SoundGain;
                 update.Radius = (float)data.SoundRadius;
                 update.Flags = data.SoundFlags;
             }
 
-            switch ((PCode)data.primShape.PCode)
+            switch ((PCode)data.Shape.PCode)
             {
                 case PCode.Grass:
                 case PCode.Tree:
                 case PCode.NewTree:
-                    update.Data = new byte[] { data.primShape.State };
+                    update.Data = new byte[] { data.Shape.State };
                     break;
                 default:
-                    // TODO: Support ScratchPad
-                    //if (prim.ScratchPad != null)
-                    //{
-                    //    update.Data = new byte[prim.ScratchPad.Length];
-                    //    Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length);
-                    //}
-                    //else
-                    //{
-                    //    update.Data = Utils.EmptyBytes;
-                    //}
                     update.Data = Utils.EmptyBytes;
                     break;
             }
@@ -4622,6 +4586,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             return update;
         }
 
+        protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
+        {
+            // TODO: Implement this
+            return null;
+        }
+
         public void SendNameReply(UUID profileId, string firstname, string lastname)
         {
             UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
@@ -11644,7 +11614,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
             }
 
-            internal TValue Dequeue()
+            internal bool TryDequeue(out TValue value)
             {
                 for (int i = 0; i < m_heaps.Length; ++i)
                 {
@@ -11652,10 +11622,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                     {
                         MinHeapItem item = m_heaps[i].RemoveMin();
                         m_lookupTable.Remove(item.LocalID);
-                        return item.Value;
+                        value = item.Value;
+                        return true;
                     }
                 }
-                throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
+
+                value = default(TValue);
+                return false;
             }
 
             internal void Reprioritize(UpdatePriorityHandler handler)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 41e41e4..1b81105 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -99,15 +99,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
 
         /// <summary>The measured resolution of Environment.TickCount</summary>
         public readonly float TickCountResolution;
-        /// <summary>Number of terse prim updates to put on the queue each time the
+        /// <summary>Number of prim updates to put on the queue each time the 
         /// OnQueueEmpty event is triggered for updates</summary>
-        public readonly int PrimTerseUpdatesPerPacket;
-        /// <summary>Number of terse avatar updates to put on the queue each time the
-        /// OnQueueEmpty event is triggered for updates</summary>
-        public readonly int AvatarTerseUpdatesPerPacket;
-        /// <summary>Number of full prim updates to put on the queue each time the
-        /// OnQueueEmpty event is triggered for updates</summary>
-        public readonly int PrimFullUpdatesPerPacket;
+        public readonly int PrimUpdatesPerCallback;
         /// <summary>Number of texture packets to put on the queue each time the
         /// OnQueueEmpty event is triggered for textures</summary>
         public readonly int TextureSendLimit;
@@ -191,9 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
                 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
                 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
 
-                PrimTerseUpdatesPerPacket = config.GetInt("PrimTerseUpdatesPerPacket", 25);
-                AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10);
-                PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100);
+                PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
                 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
 
                 m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -201,9 +193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
             }
             else
             {
-                PrimTerseUpdatesPerPacket = 25;
-                AvatarTerseUpdatesPerPacket = 10;
-                PrimFullUpdatesPerPacket = 100;
+                PrimUpdatesPerCallback = 100;
                 TextureSendLimit = 20;
             }
 
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 09611af..aac47d1 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -528,14 +528,6 @@ namespace OpenSim.Region.Examples.SimpleModule
         {
         }
 
-        public virtual void SendAvatarData(SendAvatarData data)
-        {
-        }
-
-        public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
-        {
-        }
-
         public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
         {
         }
@@ -548,15 +540,15 @@ namespace OpenSim.Region.Examples.SimpleModule
         {
         }
 
-        public virtual void SendPrimitiveToClient(SendPrimitiveData data)
+        public void SendAvatarDataImmediate(ISceneEntity avatar)
         {
         }
 
-        public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
+        public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
         {
         }
 
-        public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
+        public void ReprioritizeUpdates(UpdatePriorityHandler handler)
         {
         }
 
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 46eadee..71c8018 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -104,7 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
 
     #endregion Enumerations
 
-    public class SceneObjectPart : IScriptHost
+    public class SceneObjectPart : IScriptHost, ISceneEntity
     {
         /// <value>
         /// Denote all sides of the prim
@@ -712,6 +712,24 @@ namespace OpenSim.Region.Framework.Scenes
             }
         }
 
+        public Vector3 RelativePosition
+        {
+            get
+            {
+                if (IsRoot)
+                {
+                    if (IsAttachment)
+                        return AttachedPos;
+                    else
+                        return AbsolutePosition;
+                }
+                else
+                {
+                    return OffsetPosition;
+                }
+            }
+        }
+
         public Quaternion RotationOffset
         {
             get
@@ -973,7 +991,6 @@ namespace OpenSim.Region.Framework.Scenes
             get { return AggregateScriptEvents; }
         }
 
-
         public Quaternion SitTargetOrientation
         {
             get { return m_sitTargetOrientation; }
@@ -2925,11 +2942,7 @@ namespace OpenSim.Region.Framework.Scenes
             //if (LocalId != ParentGroup.RootPart.LocalId)
                 //isattachment = ParentGroup.RootPart.IsAttachment;
 
-            byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A};
-            remoteClient.SendPrimitiveToClient(new SendPrimitiveData(m_regionHandle, m_parentGroup.GetTimeDilation(), LocalId, m_shape,
-                                               lPos, Velocity, Acceleration, RotationOffset, AngularVelocity, clientFlags, m_uuid, _ownerID,
-                                               m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment,
-                                               AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, ParentGroup.GetUpdatePriority(remoteClient)));
+            remoteClient.SendPrimUpdate(this, PrimUpdateFlags.FullUpdate);
         }
 
         /// <summary>
@@ -4640,11 +4653,7 @@ namespace OpenSim.Region.Framework.Scenes
             
             // Causes this thread to dig into the Client Thread Data.
             // Remember your locking here!
-            remoteClient.SendPrimTerseUpdate(new SendPrimitiveTerseData(m_regionHandle,
-                    m_parentGroup.GetTimeDilation(), LocalId, lPos,
-                    RotationOffset, Velocity, Acceleration,
-                    AngularVelocity, FromItemID,
-                    OwnerID, (int)AttachmentPoint, null, ParentGroup.GetUpdatePriority(remoteClient)));
+            remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
         }
                 
         public void AddScriptLPS(int count)
@@ -4694,7 +4703,8 @@ namespace OpenSim.Region.Framework.Scenes
 
         public Color4 GetTextColor()
         {
-            return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A));
+            Color color = Color;
+            return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
         }
     }
 }
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 30eafd7..ee0eb07 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Scenes
 
     public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence);
 
-    public class ScenePresence : EntityBase
+    public class ScenePresence : EntityBase, ISceneEntity
     {
 //        ~ScenePresence()
 //        {
@@ -478,6 +478,12 @@ namespace OpenSim.Region.Framework.Scenes
             }
         }
 
+        public Vector3 OffsetPosition
+        {
+            get { return m_pos; }
+            set { m_pos = value; }
+        }
+
         /// <summary>
         /// Current velocity of the avatar.
         /// </summary>
@@ -1036,8 +1042,9 @@ namespace OpenSim.Region.Framework.Scenes
                 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
             }
 
-            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)));
+            ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position);
+            //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)));
         }
 
         public void AddNeighbourRegion(ulong regionHandle, string cap)
@@ -2360,8 +2367,7 @@ namespace OpenSim.Region.Framework.Scenes
 
                 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
 
-                remoteClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
-                    pos, velocity, Vector3.Zero, m_bodyRot, CollisionPlane, m_uuid, null, GetUpdatePriority(remoteClient)));
+                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);
@@ -2457,9 +2463,7 @@ namespace OpenSim.Region.Framework.Scenes
             Vector3 pos = m_pos;
             pos.Z += m_appearance.HipOffset;
 
-            remoteAvatar.m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid,
-                                                            LocalId, pos, m_appearance.Texture.GetBytes(),
-                                                            m_parentID, m_bodyRot));
+            remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
             m_scene.StatsReporter.AddAgentUpdates(1);
         }
 
@@ -2527,8 +2531,7 @@ namespace OpenSim.Region.Framework.Scenes
             Vector3 pos = m_pos;
             pos.Z += m_appearance.HipOffset;
 
-            m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
-                                               pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
+            m_controllingClient.SendAvatarDataImmediate(this);
 
             SendInitialFullUpdateToAllClients();
             SendAppearanceToAllOtherAgents();
@@ -2638,9 +2641,7 @@ namespace OpenSim.Region.Framework.Scenes
             Vector3 pos = m_pos;
             pos.Z += m_appearance.HipOffset;
 
-            m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
-                pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
-
+            m_controllingClient.SendAvatarDataImmediate(this);
         }
 
         public void SetWearable(int wearableId, AvatarWearable wearable)
@@ -3906,7 +3907,7 @@ namespace OpenSim.Region.Framework.Scenes
 
         private void Reprioritize(object sender, ElapsedEventArgs e)
         {
-            m_controllingClient.ReprioritizeUpdates(StateUpdateTypes.All, UpdatePriority);
+            m_controllingClient.ReprioritizeUpdates(UpdatePriority);
 
             lock (m_reprioritization_timer)
             {
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 69e78b3..84faac0 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1045,16 +1045,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
             
         }
 
-        public void SendAvatarData(SendAvatarData data)
-        {
-            
-        }
-
-        public void SendAvatarTerseUpdate(SendAvatarTerseData data)
-        {
-            
-        }
-
         public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
         {
             
@@ -1065,32 +1055,27 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
             
         }
 
-        public void SetChildAgentThrottle(byte[] throttle)
+        public void SendAvatarDataImmediate(ISceneEntity avatar)
         {
-            
-        }
 
-        public void SendPrimitiveToClient(SendPrimitiveData data)
-        {
-            
         }
 
-        public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
+        public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
         {
-            
+
         }
 
-        public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
+        public void ReprioritizeUpdates(UpdatePriorityHandler handler)
         {
 
         }
 
-        public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems)
+        public void FlushPrimUpdates()
         {
-            
+
         }
 
-        public void FlushPrimUpdates()
+        public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems)
         {
             
         }
@@ -1420,6 +1405,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
             
         }
 
+        public virtual void SetChildAgentThrottle(byte[] throttle)
+        {
+
+        }
+
         public byte[] GetThrottlesPacked(float multiplier)
         {
             return new byte[0];
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 6360c99..9066691 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -618,14 +618,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
         {
         }
 
-        public virtual void SendAvatarData(SendAvatarData data)
-        {
-        }
-
-        public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
-        {
-        }
-
         public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
         {
         }
@@ -638,15 +630,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
         {
         }
 
-        public virtual void SendPrimitiveToClient(SendPrimitiveData data)
+        public void SendAvatarDataImmediate(ISceneEntity avatar)
         {
         }
 
-        public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
+        public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
         {
         }
 
-        public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
+        public void ReprioritizeUpdates(UpdatePriorityHandler handler)
         {
         }
 
-- 
cgit v1.1