aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs566
1 files changed, 244 insertions, 322 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 34d72ac..1f7e66d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -49,6 +49,8 @@ using Timer = System.Timers.Timer;
49using AssetLandmark = OpenSim.Framework.AssetLandmark; 49using AssetLandmark = OpenSim.Framework.AssetLandmark;
50using Nini.Config; 50using Nini.Config;
51 51
52using System.IO;
53
52namespace OpenSim.Region.ClientStack.LindenUDP 54namespace OpenSim.Region.ClientStack.LindenUDP
53{ 55{
54 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 56 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
@@ -313,6 +315,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
313 315
314 private int m_cachedTextureSerial; 316 private int m_cachedTextureSerial;
315 private PriorityQueue m_entityUpdates; 317 private PriorityQueue m_entityUpdates;
318 private PriorityQueue m_entityProps;
316 private Prioritizer m_prioritizer; 319 private Prioritizer m_prioritizer;
317 private bool m_disableFacelights = false; 320 private bool m_disableFacelights = false;
318 321
@@ -360,9 +363,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
360 protected IAssetService m_assetService; 363 protected IAssetService m_assetService;
361 private const bool m_checkPackets = true; 364 private const bool m_checkPackets = true;
362 365
363 private Timer m_propertiesPacketTimer;
364 private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>();
365
366 #endregion Class Members 366 #endregion Class Members
367 367
368 #region Properties 368 #region Properties
@@ -438,6 +438,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
438 m_scene = scene; 438 m_scene = scene;
439 439
440 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 440 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
441 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
441 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 442 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
442 m_killRecord = new HashSet<uint>(); 443 m_killRecord = new HashSet<uint>();
443// m_attachmentsSent = new HashSet<uint>(); 444// m_attachmentsSent = new HashSet<uint>();
@@ -461,9 +462,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
461 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 462 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
462 m_udpClient.OnPacketStats += PopulateStats; 463 m_udpClient.OnPacketStats += PopulateStats;
463 464
464 m_propertiesPacketTimer = new Timer(100);
465 m_propertiesPacketTimer.Elapsed += ProcessObjectPropertiesPacket;
466
467 m_prioritizer = new Prioritizer(m_scene); 465 m_prioritizer = new Prioritizer(m_scene);
468 466
469 RegisterLocalPacketHandlers(); 467 RegisterLocalPacketHandlers();
@@ -1537,7 +1535,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1537 } 1535 }
1538 else 1536 else
1539 { 1537 {
1540 OutPacket(kill, ThrottleOutPacketType.State); 1538 // OutPacket(kill, ThrottleOutPacketType.State);
1539 OutPacket(kill, ThrottleOutPacketType.Task);
1541 } 1540 }
1542 } 1541 }
1543 1542
@@ -2367,7 +2366,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2367 2366
2368 packet.Effect = effectBlocks; 2367 packet.Effect = effectBlocks;
2369 2368
2370 OutPacket(packet, ThrottleOutPacketType.State); 2369 // OutPacket(packet, ThrottleOutPacketType.State);
2370 OutPacket(packet, ThrottleOutPacketType.Task);
2371 } 2371 }
2372 2372
2373 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, 2373 public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember,
@@ -3547,16 +3547,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3547 3547
3548 #region Primitive Packet/Data Sending Methods 3548 #region Primitive Packet/Data Sending Methods
3549 3549
3550
3550 /// <summary> 3551 /// <summary>
3551 /// Generate one of the object update packets based on PrimUpdateFlags 3552 /// Generate one of the object update packets based on PrimUpdateFlags
3552 /// and broadcast the packet to clients 3553 /// and broadcast the packet to clients
3553 /// </summary> 3554 /// </summary>
3554 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3555 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3555 { 3556 {
3556 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3557 //double priority = m_prioritizer.GetUpdatePriority(this, entity);
3558 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3557 3559
3558 lock (m_entityUpdates.SyncRoot) 3560 lock (m_entityUpdates.SyncRoot)
3559 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation), entity.LocalId); 3561 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3560 } 3562 }
3561 3563
3562 private void ProcessEntityUpdates(int maxUpdates) 3564 private void ProcessEntityUpdates(int maxUpdates)
@@ -3566,7 +3568,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3566 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3568 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3567 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); 3569 OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3568 3570
3569 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3571 // Check to see if this is a flush
3572 if (maxUpdates <= 0)
3573 {
3574 maxUpdates = Int32.MaxValue;
3575 }
3576
3570 int updatesThisCall = 0; 3577 int updatesThisCall = 0;
3571 3578
3572 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3579 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
@@ -3574,12 +3581,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3574 lock (m_killRecord) 3581 lock (m_killRecord)
3575 { 3582 {
3576 float avgTimeDilation = 1.0f; 3583 float avgTimeDilation = 1.0f;
3577 EntityUpdate update; 3584 IEntityUpdate iupdate;
3585 Int32 timeinqueue; // this is just debugging code & can be dropped later
3586
3578 while (updatesThisCall < maxUpdates) 3587 while (updatesThisCall < maxUpdates)
3579 { 3588 {
3580 lock (m_entityUpdates.SyncRoot) 3589 lock (m_entityUpdates.SyncRoot)
3581 if (!m_entityUpdates.TryDequeue(out update)) 3590 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3582 break; 3591 break;
3592
3593 EntityUpdate update = (EntityUpdate)iupdate;
3594
3583 avgTimeDilation += update.TimeDilation; 3595 avgTimeDilation += update.TimeDilation;
3584 avgTimeDilation *= 0.5f; 3596 avgTimeDilation *= 0.5f;
3585 3597
@@ -3619,7 +3631,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3619 3631
3620 #region UpdateFlags to packet type conversion 3632 #region UpdateFlags to packet type conversion
3621 3633
3622 PrimUpdateFlags updateFlags = update.Flags; 3634 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3623 3635
3624 bool canUseCompressed = true; 3636 bool canUseCompressed = true;
3625 bool canUseImproved = true; 3637 bool canUseImproved = true;
@@ -3679,36 +3691,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3679 } 3691 }
3680 else 3692 else
3681 { 3693 {
3682 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment) 3694 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3683 // {
3684 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3685 // string text = sop.Text;
3686 // if (text.IndexOf("\n") >= 0)
3687 // text = text.Remove(text.IndexOf("\n"));
3688 //
3689 // if (m_attachmentsSent.Contains(sop.ParentID))
3690 // {
3691 //// m_log.DebugFormat(
3692 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3693 //// sop.LocalId, text);
3694 //
3695 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3696 //
3697 // m_attachmentsSent.Add(sop.LocalId);
3698 // }
3699 // else
3700 // {
3701 // m_log.DebugFormat(
3702 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3703 // sop.LocalId, text, sop.ParentID);
3704 //
3705 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3706 // }
3707 // }
3708 // else
3709 // {
3710 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3711 // }
3712 } 3695 }
3713 } 3696 }
3714 else if (!canUseImproved) 3697 else if (!canUseImproved)
@@ -3727,6 +3710,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3727 3710
3728 #endregion Block Construction 3711 #endregion Block Construction
3729 } 3712 }
3713
3730 3714
3731 #region Packet Sending 3715 #region Packet Sending
3732 3716
@@ -3802,26 +3786,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3802 3786
3803 public void ReprioritizeUpdates() 3787 public void ReprioritizeUpdates()
3804 { 3788 {
3805 //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName);
3806
3807 lock (m_entityUpdates.SyncRoot) 3789 lock (m_entityUpdates.SyncRoot)
3808 m_entityUpdates.Reprioritize(UpdatePriorityHandler); 3790 m_entityUpdates.Reprioritize(UpdatePriorityHandler);
3809 } 3791 }
3810 3792
3811 private bool UpdatePriorityHandler(ref double priority, uint localID) 3793 private bool UpdatePriorityHandler(ref uint priority, ISceneEntity entity)
3812 { 3794 {
3813 EntityBase entity; 3795 if (entity != null)
3814 if (m_scene.Entities.TryGetValue(localID, out entity))
3815 { 3796 {
3816 priority = m_prioritizer.GetUpdatePriority(this, entity); 3797 priority = m_prioritizer.GetUpdatePriority(this, entity);
3798 return true;
3817 } 3799 }
3818 3800
3819 return priority != double.NaN; 3801 return false;
3820 } 3802 }
3821 3803
3822 public void FlushPrimUpdates() 3804 public void FlushPrimUpdates()
3823 { 3805 {
3824 m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName); 3806 m_log.WarnFormat("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName);
3825 3807
3826 while (m_entityUpdates.Count > 0) 3808 while (m_entityUpdates.Count > 0)
3827 ProcessEntityUpdates(-1); 3809 ProcessEntityUpdates(-1);
@@ -3829,12 +3811,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3829 3811
3830 #endregion Primitive Packet/Data Sending Methods 3812 #endregion Primitive Packet/Data Sending Methods
3831 3813
3814 // These are used to implement an adaptive backoff in the number
3815 // of updates converted to packets. Since we don't want packets
3816 // to sit in the queue with old data, only convert enough updates
3817 // to packets that can be sent in 200ms.
3818 private Int32 m_LastQueueFill = 0;
3819 private Int32 m_maxUpdates = 0;
3820
3832 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 3821 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
3833 { 3822 {
3834 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 3823 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
3835 { 3824 {
3825 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
3826 {
3827 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
3828 }
3829 else
3830 {
3831 if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200)
3832 m_maxUpdates += 5;
3833 else
3834 m_maxUpdates = m_maxUpdates >> 1;
3835 }
3836 m_maxUpdates = Util.Clamp<Int32>(m_maxUpdates,10,500);
3837 m_LastQueueFill = Util.EnvironmentTickCount();
3838
3836 if (m_entityUpdates.Count > 0) 3839 if (m_entityUpdates.Count > 0)
3837 ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback); 3840 ProcessEntityUpdates(m_maxUpdates);
3841
3842 if (m_entityProps.Count > 0)
3843 ProcessEntityPropertyRequests(m_maxUpdates);
3838 } 3844 }
3839 3845
3840 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) 3846 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
@@ -3948,132 +3954,206 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3948 OutPacket(pack, ThrottleOutPacketType.Task); 3954 OutPacket(pack, ThrottleOutPacketType.Task);
3949 } 3955 }
3950 3956
3951 public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, 3957 private class ObjectPropertyUpdate : IEntityUpdate
3952 uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask,
3953 uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category,
3954 UUID LastOwnerID, string ObjectName, string Description)
3955 { 3958 {
3956 ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); 3959 internal bool SendFamilyProps;
3957 // TODO: don't create new blocks if recycling an old packet 3960 internal bool SendObjectProps;
3958 3961
3959 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); 3962 public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj)
3960 objPropDB.RequestFlags = RequestFlags; 3963 : base(entity,flags)
3961 objPropDB.ObjectID = ObjectUUID; 3964 {
3962 if (OwnerID == GroupID) 3965 SendFamilyProps = sendfam;
3963 objPropDB.OwnerID = UUID.Zero; 3966 SendObjectProps = sendobj;
3964 else 3967 }
3965 objPropDB.OwnerID = OwnerID; 3968 public void Update(ObjectPropertyUpdate update)
3966 objPropDB.GroupID = GroupID; 3969 {
3967 objPropDB.BaseMask = BaseMask; 3970 SendFamilyProps = SendFamilyProps || update.SendFamilyProps;
3968 objPropDB.OwnerMask = OwnerMask; 3971 SendObjectProps = SendObjectProps || update.SendObjectProps;
3969 objPropDB.GroupMask = GroupMask; 3972 Flags |= update.Flags;
3970 objPropDB.EveryoneMask = EveryoneMask; 3973 }
3971 objPropDB.NextOwnerMask = NextOwnerMask; 3974 }
3975
3976 public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags)
3977 {
3978 uint priority = 0; // time based ordering only
3979 lock (m_entityProps.SyncRoot)
3980 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false));
3981 }
3972 3982
3973 // TODO: More properties are needed in SceneObjectPart! 3983 public void SendObjectPropertiesReply(ISceneEntity entity)
3974 objPropDB.OwnershipCost = OwnershipCost;
3975 objPropDB.SaleType = SaleType;
3976 objPropDB.SalePrice = SalePrice;
3977 objPropDB.Category = Category;
3978 objPropDB.LastOwnerID = LastOwnerID;
3979 objPropDB.Name = Util.StringToBytes256(ObjectName);
3980 objPropDB.Description = Util.StringToBytes256(Description);
3981 objPropFamilyPack.ObjectData = objPropDB;
3982 objPropFamilyPack.Header.Zerocoded = true;
3983 OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task);
3984 }
3985
3986 public void SendObjectPropertiesReply(
3987 UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID,
3988 UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID,
3989 UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName,
3990 string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask,
3991 uint BaseMask, byte saleType, int salePrice)
3992 { 3984 {
3993 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 3985 uint priority = 0; // time based ordering only
3994 // TODO: don't create new blocks if recycling an old packet 3986 lock (m_entityProps.SyncRoot)
3987 m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true));
3988 }
3995 3989
3996 ObjectPropertiesPacket.ObjectDataBlock block = 3990 private void ProcessEntityPropertyRequests(int maxUpdates)
3997 new ObjectPropertiesPacket.ObjectDataBlock(); 3991 {
3992 OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks =
3993 new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>();
3998 3994
3999 block.ItemID = ItemID; 3995 OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks =
4000 block.CreationDate = CreationDate; 3996 new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>();
4001 block.CreatorID = CreatorUUID;
4002 block.FolderID = FolderUUID;
4003 block.FromTaskID = FromTaskUUID;
4004 block.GroupID = GroupUUID;
4005 block.InventorySerial = InventorySerial;
4006 3997
4007 block.LastOwnerID = LastOwnerUUID; 3998 IEntityUpdate iupdate;
4008 // proper.ObjectData[0].LastOwnerID = UUID.Zero; 3999 Int32 timeinqueue; // this is just debugging code & can be dropped later
4009 4000
4010 block.ObjectID = ObjectUUID; 4001 int updatesThisCall = 0;
4011 if (OwnerUUID == GroupUUID) 4002 while (updatesThisCall < m_maxUpdates)
4012 block.OwnerID = UUID.Zero;
4013 else
4014 block.OwnerID = OwnerUUID;
4015 block.TouchName = Util.StringToBytes256(TouchTitle);
4016 block.TextureID = TextureID;
4017 block.SitName = Util.StringToBytes256(SitTitle);
4018 block.Name = Util.StringToBytes256(ItemName);
4019 block.Description = Util.StringToBytes256(ItemDescription);
4020 block.OwnerMask = OwnerMask;
4021 block.NextOwnerMask = NextOwnerMask;
4022 block.GroupMask = GroupMask;
4023 block.EveryoneMask = EveryoneMask;
4024 block.BaseMask = BaseMask;
4025 // proper.ObjectData[0].AggregatePerms = 53;
4026 // proper.ObjectData[0].AggregatePermTextures = 0;
4027 // proper.ObjectData[0].AggregatePermTexturesOwner = 0;
4028 block.SaleType = saleType;
4029 block.SalePrice = salePrice;
4030
4031 lock (m_propertiesPacketTimer)
4032 { 4003 {
4033 m_propertiesBlocks.Add(block); 4004 lock (m_entityProps.SyncRoot)
4005 if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue))
4006 break;
4034 4007
4035 int length = 0; 4008 ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate;
4036 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) 4009 if (update.SendFamilyProps)
4037 { 4010 {
4038 length += b.Length; 4011 if (update.Entity is SceneObjectPart)
4012 {
4013 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4014 ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags);
4015 objectFamilyBlocks.Value.Add(objPropDB);
4016 }
4039 } 4017 }
4040 if (length > 1100) // FIXME: use real MTU 4018
4019 if (update.SendObjectProps)
4041 { 4020 {
4042 ProcessObjectPropertiesPacket(null, null); 4021 if (update.Entity is SceneObjectPart)
4043 m_propertiesPacketTimer.Stop(); 4022 {
4044 return; 4023 SceneObjectPart sop = (SceneObjectPart)update.Entity;
4024 ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop);
4025 objectPropertiesBlocks.Value.Add(objPropDB);
4026 }
4045 } 4027 }
4046 4028
4047 m_propertiesPacketTimer.Stop(); 4029 updatesThisCall++;
4048 m_propertiesPacketTimer.Start();
4049 } 4030 }
4031
4050 4032
4051 //proper.Header.Zerocoded = true; 4033 Int32 ppcnt = 0;
4052 //OutPacket(proper, ThrottleOutPacketType.Task); 4034 Int32 pbcnt = 0;
4053 } 4035
4036 if (objectPropertiesBlocks.IsValueCreated)
4037 {
4038 List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value;
4054 4039
4055 private void ProcessObjectPropertiesPacket(Object sender, ElapsedEventArgs e) 4040 ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4056 { 4041 packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count];
4057 ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); 4042 for (int i = 0; i < blocks.Count; i++)
4043 packet.ObjectData[i] = blocks[i];
4058 4044
4059 lock (m_propertiesPacketTimer) 4045 packet.Header.Zerocoded = true;
4060 { 4046 OutPacket(packet, ThrottleOutPacketType.Task, true);
4061 m_propertiesPacketTimer.Stop();
4062 4047
4063 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4048 pbcnt += blocks.Count;
4049 ppcnt++;
4050 }
4051
4052 Int32 fpcnt = 0;
4053 Int32 fbcnt = 0;
4054
4055 if (objectFamilyBlocks.IsValueCreated)
4056 {
4057 List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value;
4064 4058
4065 int index = 0; 4059 // ObjectPropertiesFamilyPacket objPropFamilyPack =
4060 // (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4061 //
4062 // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count];
4063 // for (int i = 0; i < blocks.Count; i++)
4064 // objPropFamilyPack.ObjectData[i] = blocks[i];
4065 //
4066 // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true);
4066 4067
4067 foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) 4068 // one packet per object block... uggh...
4069 for (int i = 0; i < blocks.Count; i++)
4068 { 4070 {
4069 proper.ObjectData[index++] = b; 4071 ObjectPropertiesFamilyPacket packet =
4070 } 4072 (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily);
4073
4074 packet.ObjectData = blocks[i];
4075 packet.Header.Zerocoded = true;
4076 OutPacket(packet, ThrottleOutPacketType.Task);
4071 4077
4072 m_propertiesBlocks.Clear(); 4078 fpcnt++;
4079 fbcnt++;
4080 }
4081
4073 } 4082 }
4083
4084 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt);
4085 // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt);
4086 }
4087
4088 private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags)
4089 {
4090 ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock();
4074 4091
4075 proper.Header.Zerocoded = true; 4092 block.RequestFlags = requestFlags;
4076 OutPacket(proper, ThrottleOutPacketType.Task); 4093 block.ObjectID = sop.UUID;
4094 if (sop.OwnerID == sop.GroupID)
4095 block.OwnerID = UUID.Zero;
4096 else
4097 block.OwnerID = sop.OwnerID;
4098 block.GroupID = sop.GroupID;
4099 block.BaseMask = sop.BaseMask;
4100 block.OwnerMask = sop.OwnerMask;
4101 block.GroupMask = sop.GroupMask;
4102 block.EveryoneMask = sop.EveryoneMask;
4103 block.NextOwnerMask = sop.NextOwnerMask;
4104
4105 // TODO: More properties are needed in SceneObjectPart!
4106 block.OwnershipCost = sop.OwnershipCost;
4107 block.SaleType = sop.ObjectSaleType;
4108 block.SalePrice = sop.SalePrice;
4109 block.Category = sop.Category;
4110 block.LastOwnerID = sop.CreatorID; // copied from old SOG call... is this right?
4111 block.Name = Util.StringToBytes256(sop.Name);
4112 block.Description = Util.StringToBytes256(sop.Description);
4113
4114 return block;
4115 }
4116
4117 private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop)
4118 {
4119 //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties);
4120 // TODO: don't create new blocks if recycling an old packet
4121
4122 ObjectPropertiesPacket.ObjectDataBlock block =
4123 new ObjectPropertiesPacket.ObjectDataBlock();
4124
4125 block.ObjectID = sop.UUID;
4126 block.Name = Util.StringToBytes256(sop.Name);
4127 block.Description = Util.StringToBytes256(sop.Description);
4128
4129 block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds
4130 block.CreatorID = sop.CreatorID;
4131 block.GroupID = sop.GroupID;
4132 block.LastOwnerID = sop.LastOwnerID;
4133 if (sop.OwnerID == sop.GroupID)
4134 block.OwnerID = UUID.Zero;
4135 else
4136 block.OwnerID = sop.OwnerID;
4137
4138 block.ItemID = sop.FromUserInventoryItemID;
4139 block.FolderID = UUID.Zero; // sop.FromFolderID ??
4140 block.FromTaskID = UUID.Zero; // ???
4141 block.InventorySerial = (short)sop.InventorySerial;
4142
4143 SceneObjectPart root = sop.ParentGroup.RootPart;
4144
4145 block.TouchName = Util.StringToBytes256(root.TouchName);
4146 block.TextureID = new byte[0]; // TextureID ???
4147 block.SitName = Util.StringToBytes256(root.SitName);
4148 block.OwnerMask = root.OwnerMask;
4149 block.NextOwnerMask = root.NextOwnerMask;
4150 block.GroupMask = root.GroupMask;
4151 block.EveryoneMask = root.EveryoneMask;
4152 block.BaseMask = root.BaseMask;
4153 block.SaleType = root.ObjectSaleType;
4154 block.SalePrice = root.SalePrice;
4155
4156 return block;
4077 } 4157 }
4078 4158
4079 #region Estate Data Sending Methods 4159 #region Estate Data Sending Methods
@@ -4217,6 +4297,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4217 4297
4218 public void SendEstateCovenantInformation(UUID covenant) 4298 public void SendEstateCovenantInformation(UUID covenant)
4219 { 4299 {
4300// m_log.DebugFormat("[LLCLIENTVIEW]: Sending estate covenant asset id of {0} to {1}", covenant, Name);
4301
4220 EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket(); 4302 EstateCovenantReplyPacket einfopack = new EstateCovenantReplyPacket();
4221 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock(); 4303 EstateCovenantReplyPacket.DataBlock edata = new EstateCovenantReplyPacket.DataBlock();
4222 edata.CovenantID = covenant; 4304 edata.CovenantID = covenant;
@@ -4227,8 +4309,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4227 OutPacket(einfopack, ThrottleOutPacketType.Task); 4309 OutPacket(einfopack, ThrottleOutPacketType.Task);
4228 } 4310 }
4229 4311
4230 public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) 4312 public void SendDetailedEstateData(
4313 UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition,
4314 UUID covenant, string abuseEmail, UUID estateOwner)
4231 { 4315 {
4316// m_log.DebugFormat(
4317// "[LLCLIENTVIEW]: Sending detailed estate data to {0} with covenant asset id {1}", Name, covenant);
4318
4232 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); 4319 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4233 packet.MethodData.Invoice = invoice; 4320 packet.MethodData.Invoice = invoice;
4234 packet.AgentData.TransactionID = UUID.Random(); 4321 packet.AgentData.TransactionID = UUID.Random();
@@ -4407,6 +4494,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4407 4494
4408 public void SendForceClientSelectObjects(List<uint> ObjectIDs) 4495 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4409 { 4496 {
4497 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4498
4410 bool firstCall = true; 4499 bool firstCall = true;
4411 const int MAX_OBJECTS_PER_PACKET = 251; 4500 const int MAX_OBJECTS_PER_PACKET = 251;
4412 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); 4501 ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect);
@@ -11298,7 +11387,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11298 if (logPacket) 11387 if (logPacket)
11299 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); 11388 m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type);
11300 } 11389 }
11301 11390
11302 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); 11391 m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting);
11303 } 11392 }
11304 11393
@@ -11726,171 +11815,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11726 OutPacket(pack, ThrottleOutPacketType.Task); 11815 OutPacket(pack, ThrottleOutPacketType.Task);
11727 } 11816 }
11728 11817
11729 #region PriorityQueue
11730 public class PriorityQueue
11731 {
11732 internal delegate bool UpdatePriorityHandler(ref double priority, uint local_id);
11733
11734 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
11735 private Dictionary<uint, LookupItem> m_lookupTable;
11736 private Comparison<double> m_comparison;
11737 private object m_syncRoot = new object();
11738
11739 internal PriorityQueue() :
11740 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<double>.Default) { }
11741 internal PriorityQueue(int capacity) :
11742 this(capacity, Comparer<double>.Default) { }
11743 internal PriorityQueue(IComparer<double> comparer) :
11744 this(new Comparison<double>(comparer.Compare)) { }
11745 internal PriorityQueue(Comparison<double> comparison) :
11746 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
11747 internal PriorityQueue(int capacity, IComparer<double> comparer) :
11748 this(capacity, new Comparison<double>(comparer.Compare)) { }
11749 internal PriorityQueue(int capacity, Comparison<double> comparison)
11750 {
11751 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
11752
11753 for (int i = 0; i < m_heaps.Length; ++i)
11754 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
11755 this.m_comparison = comparison;
11756 }
11757
11758 public object SyncRoot { get { return this.m_syncRoot; } }
11759 internal int Count
11760 {
11761 get
11762 {
11763 int count = 0;
11764 for (int i = 0; i < m_heaps.Length; ++i)
11765 count = m_heaps[i].Count;
11766 return count;
11767 }
11768 }
11769
11770 public bool Enqueue(double priority, EntityUpdate value, uint local_id)
11771 {
11772 LookupItem item;
11773
11774 if (m_lookupTable.TryGetValue(local_id, out item))
11775 {
11776 // Combine flags
11777 value.Flags |= item.Heap[item.Handle].Value.Flags;
11778
11779 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
11780 return false;
11781 }
11782 else
11783 {
11784 item.Heap = m_heaps[0];
11785 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
11786 m_lookupTable.Add(local_id, item);
11787 return true;
11788 }
11789 }
11790
11791 internal EntityUpdate Peek()
11792 {
11793 for (int i = 0; i < m_heaps.Length; ++i)
11794 if (m_heaps[i].Count > 0)
11795 return m_heaps[i].Min().Value;
11796 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
11797 }
11798
11799 internal bool TryDequeue(out EntityUpdate value)
11800 {
11801 for (int i = 0; i < m_heaps.Length; ++i)
11802 {
11803 if (m_heaps[i].Count > 0)
11804 {
11805 MinHeapItem item = m_heaps[i].RemoveMin();
11806 m_lookupTable.Remove(item.LocalID);
11807 value = item.Value;
11808 return true;
11809 }
11810 }
11811
11812 value = default(EntityUpdate);
11813 return false;
11814 }
11815
11816 internal void Reprioritize(UpdatePriorityHandler handler)
11817 {
11818 MinHeapItem item;
11819 double priority;
11820
11821 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
11822 {
11823 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
11824 {
11825 priority = item.Priority;
11826 if (handler(ref priority, item.LocalID))
11827 {
11828 if (lookup.Heap.ContainsHandle(lookup.Handle))
11829 lookup.Heap[lookup.Handle] =
11830 new MinHeapItem(priority, item.Value, item.LocalID, this.m_comparison);
11831 }
11832 else
11833 {
11834 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
11835 lookup.Heap.Remove(lookup.Handle);
11836 this.m_lookupTable.Remove(item.LocalID);
11837 }
11838 }
11839 }
11840 }
11841
11842 #region MinHeapItem
11843 private struct MinHeapItem : IComparable<MinHeapItem>
11844 {
11845 private double priority;
11846 private EntityUpdate value;
11847 private uint local_id;
11848 private Comparison<double> comparison;
11849
11850 internal MinHeapItem(double priority, EntityUpdate value, uint local_id) :
11851 this(priority, value, local_id, Comparer<double>.Default) { }
11852 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, IComparer<double> comparer) :
11853 this(priority, value, local_id, new Comparison<double>(comparer.Compare)) { }
11854 internal MinHeapItem(double priority, EntityUpdate value, uint local_id, Comparison<double> comparison)
11855 {
11856 this.priority = priority;
11857 this.value = value;
11858 this.local_id = local_id;
11859 this.comparison = comparison;
11860 }
11861
11862 internal double Priority { get { return this.priority; } }
11863 internal EntityUpdate Value { get { return this.value; } }
11864 internal uint LocalID { get { return this.local_id; } }
11865
11866 public override string ToString()
11867 {
11868 StringBuilder sb = new StringBuilder();
11869 sb.Append("[");
11870 sb.Append(this.priority.ToString());
11871 sb.Append(",");
11872 if (this.value != null)
11873 sb.Append(this.value.ToString());
11874 sb.Append("]");
11875 return sb.ToString();
11876 }
11877
11878 public int CompareTo(MinHeapItem other)
11879 {
11880 return this.comparison(this.priority, other.priority);
11881 }
11882 }
11883 #endregion
11884
11885 #region LookupItem
11886 private struct LookupItem
11887 {
11888 internal MinHeap<MinHeapItem> Heap;
11889 internal IHandle Handle;
11890 }
11891 #endregion
11892 }
11893
11894 public struct PacketProcessor 11818 public struct PacketProcessor
11895 { 11819 {
11896 public PacketMethod method; 11820 public PacketMethod method;
@@ -11911,8 +11835,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11911 } 11835 }
11912 } 11836 }
11913 11837
11914 #endregion
11915
11916 public static OSD BuildEvent(string eventName, OSD eventBody) 11838 public static OSD BuildEvent(string eventName, OSD eventBody)
11917 { 11839 {
11918 OSDMap osdEvent = new OSDMap(2); 11840 OSDMap osdEvent = new OSDMap(2);