diff options
Diffstat (limited to '')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 428 |
1 files changed, 217 insertions, 211 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 1c3ecb2..803114f 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -301,77 +301,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
301 | /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary> | 301 | /// <summary>Used to adjust Sun Orbit values so Linden based viewers properly position sun</summary> |
302 | private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; | 302 | private const float m_sunPainDaHalfOrbitalCutoff = 4.712388980384689858f; |
303 | 303 | ||
304 | // First log file or time has expired, start writing to a new log file | ||
305 | //<MIC> | ||
306 | // ----------------------------------------------------------------- | ||
307 | // ----------------------------------------------------------------- | ||
308 | // THIS IS DEBUGGING CODE & SHOULD BE REMOVED | ||
309 | // ----------------------------------------------------------------- | ||
310 | // ----------------------------------------------------------------- | ||
311 | public class QueueLogger | ||
312 | { | ||
313 | public Int32 start = 0; | ||
314 | public StreamWriter Log = null; | ||
315 | private Dictionary<UUID,int> m_idMap = new Dictionary<UUID,int>(); | ||
316 | |||
317 | public QueueLogger() | ||
318 | { | ||
319 | DateTime now = DateTime.Now; | ||
320 | String fname = String.Format("queue-{0}.log", now.ToString("yyyyMMddHHmmss")); | ||
321 | Log = new StreamWriter(fname); | ||
322 | |||
323 | start = Util.EnvironmentTickCount(); | ||
324 | } | ||
325 | |||
326 | public int LookupID(UUID uuid) | ||
327 | { | ||
328 | int localid; | ||
329 | if (! m_idMap.TryGetValue(uuid,out localid)) | ||
330 | { | ||
331 | localid = m_idMap.Count + 1; | ||
332 | m_idMap[uuid] = localid; | ||
333 | } | ||
334 | |||
335 | return localid; | ||
336 | } | ||
337 | } | ||
338 | |||
339 | public static QueueLogger QueueLog = null; | ||
340 | |||
341 | // ----------------------------------------------------------------- | ||
342 | public void LogAvatarUpdateEvent(UUID client, UUID avatar, Int32 timeinqueue) | ||
343 | { | ||
344 | if (QueueLog == null) | ||
345 | QueueLog = new QueueLogger(); | ||
346 | |||
347 | Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start); | ||
348 | lock(QueueLog) | ||
349 | { | ||
350 | int cid = QueueLog.LookupID(client); | ||
351 | int aid = QueueLog.LookupID(avatar); | ||
352 | QueueLog.Log.WriteLine("{0},AU,AV{1:D4},AV{2:D4},{3}",ticks,cid,aid,timeinqueue); | ||
353 | } | ||
354 | } | ||
355 | |||
356 | // ----------------------------------------------------------------- | ||
357 | public void LogQueueProcessEvent(UUID client, PriorityQueue queue, uint maxup) | ||
358 | { | ||
359 | if (QueueLog == null) | ||
360 | QueueLog = new QueueLogger(); | ||
361 | |||
362 | Int32 ticks = Util.EnvironmentTickCountSubtract(QueueLog.start); | ||
363 | lock(QueueLog) | ||
364 | { | ||
365 | int cid = QueueLog.LookupID(client); | ||
366 | QueueLog.Log.WriteLine("{0},PQ,AV{1:D4},{2},{3}",ticks,cid,maxup,queue.ToString()); | ||
367 | } | ||
368 | } | ||
369 | // ----------------------------------------------------------------- | ||
370 | // ----------------------------------------------------------------- | ||
371 | // ----------------------------------------------------------------- | ||
372 | // ----------------------------------------------------------------- | ||
373 | //</MIC> | ||
374 | |||
375 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 304 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
376 | protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients | 305 | protected static Dictionary<PacketType, PacketMethod> PacketHandlers = new Dictionary<PacketType, PacketMethod>(); //Global/static handlers for all clients |
377 | 306 | ||
@@ -387,6 +316,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
387 | 316 | ||
388 | private int m_cachedTextureSerial; | 317 | private int m_cachedTextureSerial; |
389 | private PriorityQueue m_entityUpdates; | 318 | private PriorityQueue m_entityUpdates; |
319 | private PriorityQueue m_entityProps; | ||
390 | private Prioritizer m_prioritizer; | 320 | private Prioritizer m_prioritizer; |
391 | private bool m_disableFacelights = false; | 321 | private bool m_disableFacelights = false; |
392 | 322 | ||
@@ -435,9 +365,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
435 | protected IAssetService m_assetService; | 365 | protected IAssetService m_assetService; |
436 | private const bool m_checkPackets = true; | 366 | private const bool m_checkPackets = true; |
437 | 367 | ||
438 | private Timer m_propertiesPacketTimer; | ||
439 | private List<ObjectPropertiesPacket.ObjectDataBlock> m_propertiesBlocks = new List<ObjectPropertiesPacket.ObjectDataBlock>(); | ||
440 | |||
441 | #endregion Class Members | 368 | #endregion Class Members |
442 | 369 | ||
443 | #region Properties | 370 | #region Properties |
@@ -521,6 +448,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
521 | m_scene = scene; | 448 | m_scene = scene; |
522 | 449 | ||
523 | m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); | 450 | m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); |
451 | m_entityProps = new PriorityQueue(m_scene.Entities.Count); | ||
524 | m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); | 452 | m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); |
525 | m_killRecord = new HashSet<uint>(); | 453 | m_killRecord = new HashSet<uint>(); |
526 | // m_attachmentsSent = new HashSet<uint>(); | 454 | // m_attachmentsSent = new HashSet<uint>(); |
@@ -544,9 +472,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
544 | m_udpClient.OnQueueEmpty += HandleQueueEmpty; | 472 | m_udpClient.OnQueueEmpty += HandleQueueEmpty; |
545 | m_udpClient.OnPacketStats += PopulateStats; | 473 | m_udpClient.OnPacketStats += PopulateStats; |
546 | 474 | ||
547 | m_propertiesPacketTimer = new Timer(100); | ||
548 | m_propertiesPacketTimer.Elapsed += ProcessObjectPropertiesPacket; | ||
549 | |||
550 | m_prioritizer = new Prioritizer(m_scene); | 475 | m_prioritizer = new Prioritizer(m_scene); |
551 | 476 | ||
552 | RegisterLocalPacketHandlers(); | 477 | RegisterLocalPacketHandlers(); |
@@ -2468,7 +2393,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
2468 | 2393 | ||
2469 | packet.Effect = effectBlocks; | 2394 | packet.Effect = effectBlocks; |
2470 | 2395 | ||
2471 | OutPacket(packet, ThrottleOutPacketType.State); | 2396 | // OutPacket(packet, ThrottleOutPacketType.State); |
2397 | OutPacket(packet, ThrottleOutPacketType.Task); | ||
2472 | } | 2398 | } |
2473 | 2399 | ||
2474 | public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, | 2400 | public void SendAvatarProperties(UUID avatarID, string aboutText, string bornOn, Byte[] charterMember, |
@@ -3670,9 +3596,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3670 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); | 3596 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); |
3671 | } | 3597 | } |
3672 | 3598 | ||
3673 | private Int32 m_LastQueueFill = 0; | ||
3674 | private uint m_maxUpdates = 0; | ||
3675 | |||
3676 | private void ProcessEntityUpdates(int maxUpdates) | 3599 | private void ProcessEntityUpdates(int maxUpdates) |
3677 | { | 3600 | { |
3678 | OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); | 3601 | OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); |
@@ -3680,41 +3603,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3680 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | 3603 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); |
3681 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | 3604 | OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); |
3682 | 3605 | ||
3606 | // Check to see if this is a flush | ||
3683 | if (maxUpdates <= 0) | 3607 | if (maxUpdates <= 0) |
3684 | { | 3608 | { |
3685 | m_maxUpdates = Int32.MaxValue; | 3609 | maxUpdates = Int32.MaxValue; |
3686 | } | ||
3687 | else | ||
3688 | { | ||
3689 | if (m_maxUpdates == 0 || m_LastQueueFill == 0) | ||
3690 | { | ||
3691 | m_maxUpdates = (uint)maxUpdates; | ||
3692 | } | ||
3693 | else | ||
3694 | { | ||
3695 | if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200) | ||
3696 | m_maxUpdates += 5; | ||
3697 | else | ||
3698 | m_maxUpdates = m_maxUpdates >> 1; | ||
3699 | } | ||
3700 | m_maxUpdates = Util.Clamp<uint>(m_maxUpdates,10,500); | ||
3701 | } | 3610 | } |
3702 | m_LastQueueFill = Util.EnvironmentTickCount(); | 3611 | |
3703 | |||
3704 | int updatesThisCall = 0; | 3612 | int updatesThisCall = 0; |
3705 | 3613 | ||
3706 | // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race | 3614 | // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race |
3707 | // condition where a kill can be processed before an out-of-date update for the same object. | 3615 | // condition where a kill can be processed before an out-of-date update for the same object. |
3708 | float avgTimeDilation = 1.0f; | 3616 | float avgTimeDilation = 1.0f; |
3709 | 3617 | IEntityUpdate iupdate; | |
3710 | EntityUpdate update; | ||
3711 | Int32 timeinqueue; // this is just debugging code & can be dropped later | 3618 | Int32 timeinqueue; // this is just debugging code & can be dropped later |
3712 | 3619 | ||
3713 | while (updatesThisCall < m_maxUpdates) | 3620 | while (updatesThisCall < maxUpdates) |
3714 | { | 3621 | { |
3715 | lock (m_entityUpdates.SyncRoot) | 3622 | lock (m_entityUpdates.SyncRoot) |
3716 | if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) | 3623 | if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue)) |
3717 | break; | 3624 | break; |
3625 | |||
3626 | EntityUpdate update = (EntityUpdate)iupdate; | ||
3627 | |||
3718 | avgTimeDilation += update.TimeDilation; | 3628 | avgTimeDilation += update.TimeDilation; |
3719 | avgTimeDilation *= 0.5f; | 3629 | avgTimeDilation *= 0.5f; |
3720 | 3630 | ||
@@ -3770,7 +3680,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3770 | if (!found) | 3680 | if (!found) |
3771 | continue; | 3681 | continue; |
3772 | } | 3682 | } |
3773 | |||
3774 | if (part.ParentGroup.IsAttachment && m_disableFacelights) | 3683 | if (part.ParentGroup.IsAttachment && m_disableFacelights) |
3775 | { | 3684 | { |
3776 | if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && | 3685 | if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && |
@@ -3785,7 +3694,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3785 | 3694 | ||
3786 | #region UpdateFlags to packet type conversion | 3695 | #region UpdateFlags to packet type conversion |
3787 | 3696 | ||
3788 | PrimUpdateFlags updateFlags = update.Flags; | 3697 | PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; |
3789 | 3698 | ||
3790 | bool canUseCompressed = true; | 3699 | bool canUseCompressed = true; |
3791 | bool canUseImproved = true; | 3700 | bool canUseImproved = true; |
@@ -3960,12 +3869,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3960 | 3869 | ||
3961 | #endregion Primitive Packet/Data Sending Methods | 3870 | #endregion Primitive Packet/Data Sending Methods |
3962 | 3871 | ||
3872 | // These are used to implement an adaptive backoff in the number | ||
3873 | // of updates converted to packets. Since we don't want packets | ||
3874 | // to sit in the queue with old data, only convert enough updates | ||
3875 | // to packets that can be sent in 200ms. | ||
3876 | private Int32 m_LastQueueFill = 0; | ||
3877 | private Int32 m_maxUpdates = 0; | ||
3878 | |||
3963 | void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) | 3879 | void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) |
3964 | { | 3880 | { |
3965 | if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) | 3881 | if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) |
3966 | { | 3882 | { |
3883 | if (m_maxUpdates == 0 || m_LastQueueFill == 0) | ||
3884 | { | ||
3885 | m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; | ||
3886 | } | ||
3887 | else | ||
3888 | { | ||
3889 | if (Util.EnvironmentTickCountSubtract(m_LastQueueFill) < 200) | ||
3890 | m_maxUpdates += 5; | ||
3891 | else | ||
3892 | m_maxUpdates = m_maxUpdates >> 1; | ||
3893 | } | ||
3894 | m_maxUpdates = Util.Clamp<Int32>(m_maxUpdates,10,500); | ||
3895 | m_LastQueueFill = Util.EnvironmentTickCount(); | ||
3896 | |||
3967 | if (m_entityUpdates.Count > 0) | 3897 | if (m_entityUpdates.Count > 0) |
3968 | ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback); | 3898 | ProcessEntityUpdates(m_maxUpdates); |
3899 | |||
3900 | if (m_entityProps.Count > 0) | ||
3901 | ProcessEntityPropertyRequests(m_maxUpdates); | ||
3969 | } | 3902 | } |
3970 | 3903 | ||
3971 | if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) | 3904 | if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) |
@@ -4079,135 +4012,206 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4079 | OutPacket(pack, ThrottleOutPacketType.Task); | 4012 | OutPacket(pack, ThrottleOutPacketType.Task); |
4080 | } | 4013 | } |
4081 | 4014 | ||
4082 | public void SendObjectPropertiesFamilyData(uint RequestFlags, UUID ObjectUUID, UUID OwnerID, UUID GroupID, | 4015 | private class ObjectPropertyUpdate : IEntityUpdate |
4083 | uint BaseMask, uint OwnerMask, uint GroupMask, uint EveryoneMask, | ||
4084 | uint NextOwnerMask, int OwnershipCost, byte SaleType, int SalePrice, uint Category, | ||
4085 | UUID LastOwnerID, string ObjectName, string Description) | ||
4086 | { | 4016 | { |
4087 | ObjectPropertiesFamilyPacket objPropFamilyPack = (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); | 4017 | internal bool SendFamilyProps; |
4088 | // TODO: don't create new blocks if recycling an old packet | 4018 | internal bool SendObjectProps; |
4089 | 4019 | ||
4090 | ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); | 4020 | public ObjectPropertyUpdate(ISceneEntity entity, uint flags, bool sendfam, bool sendobj) |
4091 | objPropDB.RequestFlags = RequestFlags; | 4021 | : base(entity,flags) |
4092 | objPropDB.ObjectID = ObjectUUID; | 4022 | { |
4093 | if (OwnerID == GroupID) | 4023 | SendFamilyProps = sendfam; |
4094 | objPropDB.OwnerID = UUID.Zero; | 4024 | SendObjectProps = sendobj; |
4095 | else | 4025 | } |
4096 | objPropDB.OwnerID = OwnerID; | 4026 | public void Update(ObjectPropertyUpdate update) |
4097 | objPropDB.GroupID = GroupID; | 4027 | { |
4098 | objPropDB.BaseMask = BaseMask; | 4028 | SendFamilyProps = SendFamilyProps || update.SendFamilyProps; |
4099 | objPropDB.OwnerMask = OwnerMask; | 4029 | SendObjectProps = SendObjectProps || update.SendObjectProps; |
4100 | objPropDB.GroupMask = GroupMask; | 4030 | Flags |= update.Flags; |
4101 | objPropDB.EveryoneMask = EveryoneMask; | 4031 | } |
4102 | objPropDB.NextOwnerMask = NextOwnerMask; | 4032 | } |
4103 | 4033 | ||
4104 | // TODO: More properties are needed in SceneObjectPart! | 4034 | public void SendObjectPropertiesFamilyData(ISceneEntity entity, uint requestFlags) |
4105 | objPropDB.OwnershipCost = OwnershipCost; | ||
4106 | objPropDB.SaleType = SaleType; | ||
4107 | objPropDB.SalePrice = SalePrice; | ||
4108 | objPropDB.Category = Category; | ||
4109 | objPropDB.LastOwnerID = LastOwnerID; | ||
4110 | objPropDB.Name = Util.StringToBytes256(ObjectName); | ||
4111 | objPropDB.Description = Util.StringToBytes256(Description); | ||
4112 | objPropFamilyPack.ObjectData = objPropDB; | ||
4113 | objPropFamilyPack.Header.Zerocoded = true; | ||
4114 | OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task); | ||
4115 | } | ||
4116 | |||
4117 | public void SendObjectPropertiesReply( | ||
4118 | UUID ItemID, ulong CreationDate, UUID CreatorUUID, UUID FolderUUID, UUID FromTaskUUID, | ||
4119 | UUID GroupUUID, short InventorySerial, UUID LastOwnerUUID, UUID ObjectUUID, | ||
4120 | UUID OwnerUUID, string TouchTitle, byte[] TextureID, string SitTitle, string ItemName, | ||
4121 | string ItemDescription, uint OwnerMask, uint NextOwnerMask, uint GroupMask, uint EveryoneMask, | ||
4122 | uint BaseMask, byte saleType, int salePrice) | ||
4123 | { | 4035 | { |
4124 | //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | 4036 | uint priority = 0; // time based ordering only |
4125 | // TODO: don't create new blocks if recycling an old packet | 4037 | lock (m_entityProps.SyncRoot) |
4038 | m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,requestFlags,true,false)); | ||
4039 | } | ||
4126 | 4040 | ||
4127 | ObjectPropertiesPacket.ObjectDataBlock block = | 4041 | public void SendObjectPropertiesReply(ISceneEntity entity) |
4128 | new ObjectPropertiesPacket.ObjectDataBlock(); | 4042 | { |
4043 | uint priority = 0; // time based ordering only | ||
4044 | lock (m_entityProps.SyncRoot) | ||
4045 | m_entityProps.Enqueue(priority, new ObjectPropertyUpdate(entity,0,false,true)); | ||
4046 | } | ||
4129 | 4047 | ||
4130 | block.ItemID = ItemID; | 4048 | private void ProcessEntityPropertyRequests(int maxUpdates) |
4131 | block.CreationDate = CreationDate; | 4049 | { |
4132 | block.CreatorID = CreatorUUID; | 4050 | OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>> objectFamilyBlocks = |
4133 | block.FolderID = FolderUUID; | 4051 | new OpenSim.Framework.Lazy<List<ObjectPropertiesFamilyPacket.ObjectDataBlock>>(); |
4134 | block.FromTaskID = FromTaskUUID; | ||
4135 | block.GroupID = GroupUUID; | ||
4136 | block.InventorySerial = InventorySerial; | ||
4137 | 4052 | ||
4138 | block.LastOwnerID = LastOwnerUUID; | 4053 | OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>> objectPropertiesBlocks = |
4139 | // proper.ObjectData[0].LastOwnerID = UUID.Zero; | 4054 | new OpenSim.Framework.Lazy<List<ObjectPropertiesPacket.ObjectDataBlock>>(); |
4140 | 4055 | ||
4141 | block.ObjectID = ObjectUUID; | 4056 | IEntityUpdate iupdate; |
4142 | if (OwnerUUID == GroupUUID) | 4057 | Int32 timeinqueue; // this is just debugging code & can be dropped later |
4143 | block.OwnerID = UUID.Zero; | ||
4144 | else | ||
4145 | block.OwnerID = OwnerUUID; | ||
4146 | block.TouchName = Util.StringToBytes256(TouchTitle); | ||
4147 | block.TextureID = TextureID; | ||
4148 | block.SitName = Util.StringToBytes256(SitTitle); | ||
4149 | block.Name = Util.StringToBytes256(ItemName); | ||
4150 | block.Description = Util.StringToBytes256(ItemDescription); | ||
4151 | block.OwnerMask = OwnerMask; | ||
4152 | block.NextOwnerMask = NextOwnerMask; | ||
4153 | block.GroupMask = GroupMask; | ||
4154 | block.EveryoneMask = EveryoneMask; | ||
4155 | block.BaseMask = BaseMask; | ||
4156 | // proper.ObjectData[0].AggregatePerms = 53; | ||
4157 | // proper.ObjectData[0].AggregatePermTextures = 0; | ||
4158 | // proper.ObjectData[0].AggregatePermTexturesOwner = 0; | ||
4159 | block.SaleType = saleType; | ||
4160 | block.SalePrice = salePrice; | ||
4161 | 4058 | ||
4162 | lock (m_propertiesPacketTimer) | 4059 | int updatesThisCall = 0; |
4060 | while (updatesThisCall < m_maxUpdates) | ||
4163 | { | 4061 | { |
4164 | m_propertiesBlocks.Add(block); | 4062 | lock (m_entityProps.SyncRoot) |
4063 | if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) | ||
4064 | break; | ||
4165 | 4065 | ||
4166 | int length = 0; | 4066 | ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; |
4167 | foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) | 4067 | if (update.SendFamilyProps) |
4168 | { | 4068 | { |
4169 | length += b.Length; | 4069 | if (update.Entity is SceneObjectPart) |
4070 | { | ||
4071 | SceneObjectPart sop = (SceneObjectPart)update.Entity; | ||
4072 | ObjectPropertiesFamilyPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesFamilyBlock(sop,update.Flags); | ||
4073 | objectFamilyBlocks.Value.Add(objPropDB); | ||
4074 | } | ||
4170 | } | 4075 | } |
4171 | if (length > 1100) // FIXME: use real MTU | 4076 | |
4077 | if (update.SendObjectProps) | ||
4172 | { | 4078 | { |
4173 | ProcessObjectPropertiesPacket(null, null); | 4079 | if (update.Entity is SceneObjectPart) |
4174 | m_propertiesPacketTimer.Stop(); | 4080 | { |
4175 | return; | 4081 | SceneObjectPart sop = (SceneObjectPart)update.Entity; |
4082 | ObjectPropertiesPacket.ObjectDataBlock objPropDB = CreateObjectPropertiesBlock(sop); | ||
4083 | objectPropertiesBlocks.Value.Add(objPropDB); | ||
4084 | } | ||
4176 | } | 4085 | } |
4177 | 4086 | ||
4178 | m_propertiesPacketTimer.Stop(); | 4087 | updatesThisCall++; |
4179 | m_propertiesPacketTimer.Start(); | ||
4180 | } | 4088 | } |
4089 | |||
4181 | 4090 | ||
4182 | //proper.Header.Zerocoded = true; | 4091 | Int32 ppcnt = 0; |
4183 | //OutPacket(proper, ThrottleOutPacketType.Task); | 4092 | Int32 pbcnt = 0; |
4184 | } | 4093 | |
4094 | if (objectPropertiesBlocks.IsValueCreated) | ||
4095 | { | ||
4096 | List<ObjectPropertiesPacket.ObjectDataBlock> blocks = objectPropertiesBlocks.Value; | ||
4185 | 4097 | ||
4186 | private void ProcessObjectPropertiesPacket(Object sender, ElapsedEventArgs e) | 4098 | ObjectPropertiesPacket packet = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); |
4187 | { | 4099 | packet.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[blocks.Count]; |
4188 | ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | 4100 | for (int i = 0; i < blocks.Count; i++) |
4101 | packet.ObjectData[i] = blocks[i]; | ||
4189 | 4102 | ||
4190 | lock (m_propertiesPacketTimer) | 4103 | packet.Header.Zerocoded = true; |
4104 | OutPacket(packet, ThrottleOutPacketType.Task, true); | ||
4105 | |||
4106 | pbcnt += blocks.Count; | ||
4107 | ppcnt++; | ||
4108 | } | ||
4109 | |||
4110 | Int32 fpcnt = 0; | ||
4111 | Int32 fbcnt = 0; | ||
4112 | |||
4113 | if (objectFamilyBlocks.IsValueCreated) | ||
4191 | { | 4114 | { |
4192 | m_propertiesPacketTimer.Stop(); | 4115 | List<ObjectPropertiesFamilyPacket.ObjectDataBlock> blocks = objectFamilyBlocks.Value; |
4193 | 4116 | ||
4194 | if (m_propertiesBlocks.Count == 0) | 4117 | // ObjectPropertiesFamilyPacket objPropFamilyPack = |
4195 | return; | 4118 | // (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); |
4119 | // | ||
4120 | // objPropFamilyPack.ObjectData = new ObjectPropertiesFamilyPacket.ObjectDataBlock[blocks.Count]; | ||
4121 | // for (int i = 0; i < blocks.Count; i++) | ||
4122 | // objPropFamilyPack.ObjectData[i] = blocks[i]; | ||
4123 | // | ||
4124 | // OutPacket(objPropFamilyPack, ThrottleOutPacketType.Task, true); | ||
4196 | 4125 | ||
4197 | proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; | 4126 | // one packet per object block... uggh... |
4127 | for (int i = 0; i < blocks.Count; i++) | ||
4128 | { | ||
4129 | ObjectPropertiesFamilyPacket packet = | ||
4130 | (ObjectPropertiesFamilyPacket)PacketPool.Instance.GetPacket(PacketType.ObjectPropertiesFamily); | ||
4198 | 4131 | ||
4199 | int index = 0; | 4132 | packet.ObjectData = blocks[i]; |
4133 | packet.Header.Zerocoded = true; | ||
4134 | OutPacket(packet, ThrottleOutPacketType.Task); | ||
4200 | 4135 | ||
4201 | foreach (ObjectPropertiesPacket.ObjectDataBlock b in m_propertiesBlocks) | 4136 | fpcnt++; |
4202 | { | 4137 | fbcnt++; |
4203 | proper.ObjectData[index++] = b; | ||
4204 | } | 4138 | } |
4205 | 4139 | ||
4206 | m_propertiesBlocks.Clear(); | ||
4207 | } | 4140 | } |
4141 | |||
4142 | // m_log.WarnFormat("[PACKETCOUNTS] queued {0} property packets with {1} blocks",ppcnt,pbcnt); | ||
4143 | // m_log.WarnFormat("[PACKETCOUNTS] queued {0} family property packets with {1} blocks",fpcnt,fbcnt); | ||
4144 | } | ||
4145 | |||
4146 | private ObjectPropertiesFamilyPacket.ObjectDataBlock CreateObjectPropertiesFamilyBlock(SceneObjectPart sop, uint requestFlags) | ||
4147 | { | ||
4148 | ObjectPropertiesFamilyPacket.ObjectDataBlock block = new ObjectPropertiesFamilyPacket.ObjectDataBlock(); | ||
4208 | 4149 | ||
4209 | proper.Header.Zerocoded = true; | 4150 | block.RequestFlags = requestFlags; |
4210 | OutPacket(proper, ThrottleOutPacketType.Task); | 4151 | block.ObjectID = sop.UUID; |
4152 | if (sop.OwnerID == sop.GroupID) | ||
4153 | block.OwnerID = UUID.Zero; | ||
4154 | else | ||
4155 | block.OwnerID = sop.OwnerID; | ||
4156 | block.GroupID = sop.GroupID; | ||
4157 | block.BaseMask = sop.BaseMask; | ||
4158 | block.OwnerMask = sop.OwnerMask; | ||
4159 | block.GroupMask = sop.GroupMask; | ||
4160 | block.EveryoneMask = sop.EveryoneMask; | ||
4161 | block.NextOwnerMask = sop.NextOwnerMask; | ||
4162 | |||
4163 | // TODO: More properties are needed in SceneObjectPart! | ||
4164 | block.OwnershipCost = sop.OwnershipCost; | ||
4165 | block.SaleType = sop.ObjectSaleType; | ||
4166 | block.SalePrice = sop.SalePrice; | ||
4167 | block.Category = sop.Category; | ||
4168 | block.LastOwnerID = sop.CreatorID; // copied from old SOG call... is this right? | ||
4169 | block.Name = Util.StringToBytes256(sop.Name); | ||
4170 | block.Description = Util.StringToBytes256(sop.Description); | ||
4171 | |||
4172 | return block; | ||
4173 | } | ||
4174 | |||
4175 | private ObjectPropertiesPacket.ObjectDataBlock CreateObjectPropertiesBlock(SceneObjectPart sop) | ||
4176 | { | ||
4177 | //ObjectPropertiesPacket proper = (ObjectPropertiesPacket)PacketPool.Instance.GetPacket(PacketType.ObjectProperties); | ||
4178 | // TODO: don't create new blocks if recycling an old packet | ||
4179 | |||
4180 | ObjectPropertiesPacket.ObjectDataBlock block = | ||
4181 | new ObjectPropertiesPacket.ObjectDataBlock(); | ||
4182 | |||
4183 | block.ObjectID = sop.UUID; | ||
4184 | block.Name = Util.StringToBytes256(sop.Name); | ||
4185 | block.Description = Util.StringToBytes256(sop.Description); | ||
4186 | |||
4187 | block.CreationDate = (ulong)sop.CreationDate * 1000000; // viewer wants date in microseconds | ||
4188 | block.CreatorID = sop.CreatorID; | ||
4189 | block.GroupID = sop.GroupID; | ||
4190 | block.LastOwnerID = sop.LastOwnerID; | ||
4191 | if (sop.OwnerID == sop.GroupID) | ||
4192 | block.OwnerID = UUID.Zero; | ||
4193 | else | ||
4194 | block.OwnerID = sop.OwnerID; | ||
4195 | |||
4196 | block.ItemID = sop.FromUserInventoryItemID; | ||
4197 | block.FolderID = UUID.Zero; // sop.FromFolderID ?? | ||
4198 | block.FromTaskID = UUID.Zero; // ??? | ||
4199 | block.InventorySerial = (short)sop.InventorySerial; | ||
4200 | |||
4201 | SceneObjectPart root = sop.ParentGroup.RootPart; | ||
4202 | |||
4203 | block.TouchName = Util.StringToBytes256(root.TouchName); | ||
4204 | block.TextureID = new byte[0]; // TextureID ??? | ||
4205 | block.SitName = Util.StringToBytes256(root.SitName); | ||
4206 | block.OwnerMask = root.OwnerMask; | ||
4207 | block.NextOwnerMask = root.NextOwnerMask; | ||
4208 | block.GroupMask = root.GroupMask; | ||
4209 | block.EveryoneMask = root.EveryoneMask; | ||
4210 | block.BaseMask = root.BaseMask; | ||
4211 | block.SaleType = root.ObjectSaleType; | ||
4212 | block.SalePrice = root.SalePrice; | ||
4213 | |||
4214 | return block; | ||
4211 | } | 4215 | } |
4212 | 4216 | ||
4213 | #region Estate Data Sending Methods | 4217 | #region Estate Data Sending Methods |
@@ -4548,6 +4552,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4548 | 4552 | ||
4549 | public void SendForceClientSelectObjects(List<uint> ObjectIDs) | 4553 | public void SendForceClientSelectObjects(List<uint> ObjectIDs) |
4550 | { | 4554 | { |
4555 | m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); | ||
4556 | |||
4551 | bool firstCall = true; | 4557 | bool firstCall = true; |
4552 | const int MAX_OBJECTS_PER_PACKET = 251; | 4558 | const int MAX_OBJECTS_PER_PACKET = 251; |
4553 | ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); | 4559 | ForceObjectSelectPacket pack = (ForceObjectSelectPacket)PacketPool.Instance.GetPacket(PacketType.ForceObjectSelect); |
@@ -11491,7 +11497,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11491 | if (logPacket) | 11497 | if (logPacket) |
11492 | m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); | 11498 | m_log.DebugFormat("[CLIENT]: Packet OUT {0}", packet.Type); |
11493 | } | 11499 | } |
11494 | 11500 | ||
11495 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); | 11501 | m_udpServer.SendPacket(m_udpClient, packet, throttlePacketType, doAutomaticSplitting); |
11496 | } | 11502 | } |
11497 | 11503 | ||