aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs735
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs12
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs4
5 files changed, 446 insertions, 312 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index e9e2dca..9dd6663 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -202,6 +202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 m_stopPacket = TexturePacketCount(); 202 m_stopPacket = TexturePacketCount();
203 } 203 }
204 204
205 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
206 if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
207
205 m_currentPacket = StartPacket; 208 m_currentPacket = StartPacket;
206 } 209 }
207 } 210 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index a7f83f9..30acbdf 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -157,6 +157,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
157 public event RequestTaskInventory OnRequestTaskInventory; 157 public event RequestTaskInventory OnRequestTaskInventory;
158 public event UpdateInventoryItem OnUpdateInventoryItem; 158 public event UpdateInventoryItem OnUpdateInventoryItem;
159 public event CopyInventoryItem OnCopyInventoryItem; 159 public event CopyInventoryItem OnCopyInventoryItem;
160 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
160 public event MoveInventoryItem OnMoveInventoryItem; 161 public event MoveInventoryItem OnMoveInventoryItem;
161 public event RemoveInventoryItem OnRemoveInventoryItem; 162 public event RemoveInventoryItem OnRemoveInventoryItem;
162 public event RemoveInventoryFolder OnRemoveInventoryFolder; 163 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -254,7 +255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
254 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 255 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
255 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 256 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
256 public event ClassifiedDelete OnClassifiedDelete; 257 public event ClassifiedDelete OnClassifiedDelete;
257 public event ClassifiedDelete OnClassifiedGodDelete; 258 public event ClassifiedGodDelete OnClassifiedGodDelete;
258 public event EventNotificationAddRequest OnEventNotificationAddRequest; 259 public event EventNotificationAddRequest OnEventNotificationAddRequest;
259 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 260 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
260 public event EventGodDelete OnEventGodDelete; 261 public event EventGodDelete OnEventGodDelete;
@@ -330,7 +331,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
330 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 331 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
331 /// ownerless phantom. 332 /// ownerless phantom.
332 /// 333 ///
333 /// All manipulation of this set has to occur under a lock 334 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
334 /// 335 ///
335 /// </value> 336 /// </value>
336 protected HashSet<uint> m_killRecord; 337 protected HashSet<uint> m_killRecord;
@@ -338,6 +339,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
338// protected HashSet<uint> m_attachmentsSent; 339// protected HashSet<uint> m_attachmentsSent;
339 340
340 private int m_moneyBalance; 341 private int m_moneyBalance;
342 private bool m_deliverPackets = true;
341 private int m_animationSequenceNumber = 1; 343 private int m_animationSequenceNumber = 1;
342 private bool m_SendLogoutPacketWhenClosing = true; 344 private bool m_SendLogoutPacketWhenClosing = true;
343 private AgentUpdateArgs lastarg; 345 private AgentUpdateArgs lastarg;
@@ -378,6 +380,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
378 get { return m_startpos; } 380 get { return m_startpos; }
379 set { m_startpos = value; } 381 set { m_startpos = value; }
380 } 382 }
383 public bool DeliverPackets
384 {
385 get { return m_deliverPackets; }
386 set {
387 m_deliverPackets = value;
388 m_udpClient.m_deliverPackets = value;
389 }
390 }
381 public UUID AgentId { get { return m_agentId; } } 391 public UUID AgentId { get { return m_agentId; } }
382 public UUID ActiveGroupId { get { return m_activeGroupID; } } 392 public UUID ActiveGroupId { get { return m_activeGroupID; } }
383 public string ActiveGroupName { get { return m_activeGroupName; } } 393 public string ActiveGroupName { get { return m_activeGroupName; } }
@@ -479,18 +489,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
479 489
480 #region Client Methods 490 #region Client Methods
481 491
492
482 /// <summary> 493 /// <summary>
483 /// Shut down the client view 494 /// Shut down the client view
484 /// </summary> 495 /// </summary>
485 public void Close() 496 public void Close()
486 { 497 {
498 Close(true);
499 }
500
501 /// <summary>
502 /// Shut down the client view
503 /// </summary>
504 public void Close(bool sendStop)
505 {
487 m_log.DebugFormat( 506 m_log.DebugFormat(
488 "[CLIENT]: Close has been called for {0} attached to scene {1}", 507 "[CLIENT]: Close has been called for {0} attached to scene {1}",
489 Name, m_scene.RegionInfo.RegionName); 508 Name, m_scene.RegionInfo.RegionName);
490 509
491 // Send the STOP packet 510 if (sendStop)
492 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 511 {
493 OutPacket(disable, ThrottleOutPacketType.Unknown); 512 // Send the STOP packet
513 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
514 OutPacket(disable, ThrottleOutPacketType.Unknown);
515 }
494 516
495 IsActive = false; 517 IsActive = false;
496 518
@@ -791,7 +813,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
791 reply.ChatData.OwnerID = fromAgentID; 813 reply.ChatData.OwnerID = fromAgentID;
792 reply.ChatData.SourceID = fromAgentID; 814 reply.ChatData.SourceID = fromAgentID;
793 815
794 OutPacket(reply, ThrottleOutPacketType.Task); 816 OutPacket(reply, ThrottleOutPacketType.Unknown);
795 } 817 }
796 818
797 /// <summary> 819 /// <summary>
@@ -1077,6 +1099,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1077 public virtual void SendLayerData(float[] map) 1099 public virtual void SendLayerData(float[] map)
1078 { 1100 {
1079 Util.FireAndForget(DoSendLayerData, map); 1101 Util.FireAndForget(DoSendLayerData, map);
1102
1103 // Send it sync, and async. It's not that much data
1104 // and it improves user experience just so much!
1105 DoSendLayerData(map);
1080 } 1106 }
1081 1107
1082 /// <summary> 1108 /// <summary>
@@ -1089,16 +1115,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1089 1115
1090 try 1116 try
1091 { 1117 {
1092 //for (int y = 0; y < 16; y++) 1118 for (int y = 0; y < 16; y++)
1093 //{ 1119 {
1094 // for (int x = 0; x < 16; x++) 1120 for (int x = 0; x < 16; x+=4)
1095 // { 1121 {
1096 // SendLayerData(x, y, map); 1122 SendLayerPacket(x, y, map);
1097 // } 1123 }
1098 //} 1124 }
1099
1100 // Send LayerData in a spiral pattern. Fun!
1101 SendLayerTopRight(map, 0, 0, 15, 15);
1102 } 1125 }
1103 catch (Exception e) 1126 catch (Exception e)
1104 { 1127 {
@@ -1106,51 +1129,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1106 } 1129 }
1107 } 1130 }
1108 1131
1109 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1110 {
1111 // Row
1112 for (int i = x1; i <= x2; i++)
1113 SendLayerData(i, y1, map);
1114
1115 // Column
1116 for (int j = y1 + 1; j <= y2; j++)
1117 SendLayerData(x2, j, map);
1118
1119 if (x2 - x1 > 0)
1120 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1121 }
1122
1123 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1124 {
1125 // Row in reverse
1126 for (int i = x2; i >= x1; i--)
1127 SendLayerData(i, y2, map);
1128
1129 // Column in reverse
1130 for (int j = y2 - 1; j >= y1; j--)
1131 SendLayerData(x1, j, map);
1132
1133 if (x2 - x1 > 0)
1134 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1135 }
1136
1137 /// <summary> 1132 /// <summary>
1138 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1133 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1139 /// </summary> 1134 /// </summary>
1140 /// <param name="map">heightmap</param> 1135 /// <param name="map">heightmap</param>
1141 /// <param name="px">X coordinate for patches 0..12</param> 1136 /// <param name="px">X coordinate for patches 0..12</param>
1142 /// <param name="py">Y coordinate for patches 0..15</param> 1137 /// <param name="py">Y coordinate for patches 0..15</param>
1143 // private void SendLayerPacket(float[] map, int y, int x) 1138 private void SendLayerPacket(int x, int y, float[] map)
1144 // { 1139 {
1145 // int[] patches = new int[4]; 1140 int[] patches = new int[4];
1146 // patches[0] = x + 0 + y * 16; 1141 patches[0] = x + 0 + y * 16;
1147 // patches[1] = x + 1 + y * 16; 1142 patches[1] = x + 1 + y * 16;
1148 // patches[2] = x + 2 + y * 16; 1143 patches[2] = x + 2 + y * 16;
1149 // patches[3] = x + 3 + y * 16; 1144 patches[3] = x + 3 + y * 16;
1150 1145
1151 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1146 float[] heightmap = (map.Length == 65536) ?
1152 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1147 map :
1153 // } 1148 LLHeightFieldMoronize(map);
1149
1150 try
1151 {
1152 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1153 OutPacket(layerpack, ThrottleOutPacketType.Land);
1154 }
1155 catch
1156 {
1157 for (int px = x ; px < x + 4 ; px++)
1158 SendLayerData(px, y, map);
1159 }
1160 }
1154 1161
1155 /// <summary> 1162 /// <summary>
1156 /// Sends a specified patch to a client 1163 /// Sends a specified patch to a client
@@ -1170,7 +1177,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1170 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1177 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1171 layerpack.Header.Reliable = true; 1178 layerpack.Header.Reliable = true;
1172 1179
1173 OutPacket(layerpack, ThrottleOutPacketType.Land); 1180 OutPacket(layerpack, ThrottleOutPacketType.Task);
1174 } 1181 }
1175 catch (Exception e) 1182 catch (Exception e)
1176 { 1183 {
@@ -1531,38 +1538,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1531 OutPacket(pc, ThrottleOutPacketType.Unknown); 1538 OutPacket(pc, ThrottleOutPacketType.Unknown);
1532 } 1539 }
1533 1540
1534 public void SendKillObject(ulong regionHandle, uint localID) 1541 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1535 { 1542 {
1536// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1543// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1537 1544
1538 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1545 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1539 // TODO: don't create new blocks if recycling an old packet 1546 // TODO: don't create new blocks if recycling an old packet
1540 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; 1547 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1541 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); 1548 for (int i = 0 ; i < localIDs.Count ; i++ )
1542 kill.ObjectData[0].ID = localID; 1549 {
1550 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1551 kill.ObjectData[i].ID = localIDs[i];
1552 }
1543 kill.Header.Reliable = true; 1553 kill.Header.Reliable = true;
1544 kill.Header.Zerocoded = true; 1554 kill.Header.Zerocoded = true;
1545 1555
1546 if (m_scene.GetScenePresence(localID) == null) 1556 lock (m_killRecord)
1547 { 1557 {
1548 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1558 if (localIDs.Count == 1)
1549 // condition where a kill can be processed before an out-of-date update for the same object.
1550 lock (m_killRecord)
1551 { 1559 {
1552 m_killRecord.Add(localID); 1560 if (m_scene.GetScenePresence(localIDs[0]) != null)
1553 1561 {
1554 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1562 OutPacket(kill, ThrottleOutPacketType.State);
1555 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1563 return;
1556 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1564 }
1557 // scene objects in a viewer until that viewer is relogged in. 1565 m_killRecord.Add(localIDs[0]);
1558 OutPacket(kill, ThrottleOutPacketType.Task); 1566 }
1567 else
1568 {
1569 lock (m_entityUpdates.SyncRoot)
1570 {
1571 foreach (uint localID in localIDs)
1572 m_killRecord.Add(localID);
1573 }
1559 } 1574 }
1560 } 1575 }
1561 else 1576
1562 { 1577 // The throttle queue used here must match that being used for
1563 // OutPacket(kill, ThrottleOutPacketType.State); 1578 // updates. Otherwise, there is a chance that a kill packet put
1564 OutPacket(kill, ThrottleOutPacketType.Task); 1579 // on a separate queue will be sent to the client before an
1565 } 1580 // existing update packet on another queue. Receiving updates
1581 // after kills results in unowned and undeletable
1582 // scene objects in a viewer until that viewer is relogged in.
1583 OutPacket(kill, ThrottleOutPacketType.Task);
1566 } 1584 }
1567 1585
1568 /// <summary> 1586 /// <summary>
@@ -2289,6 +2307,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2289 OutPacket(sound, ThrottleOutPacketType.Task); 2307 OutPacket(sound, ThrottleOutPacketType.Task);
2290 } 2308 }
2291 2309
2310 public void SendTransferAbort(TransferRequestPacket transferRequest)
2311 {
2312 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2313 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2314 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2315 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2316 OutPacket(abort, ThrottleOutPacketType.Task);
2317 }
2318
2292 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2319 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2293 { 2320 {
2294 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2321 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3591,7 +3618,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3591 /// </summary> 3618 /// </summary>
3592 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3619 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3593 { 3620 {
3594 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3621 if (entity is SceneObjectPart)
3622 {
3623 SceneObjectPart e = (SceneObjectPart)entity;
3624 SceneObjectGroup g = e.ParentGroup;
3625 if (g.RootPart.Shape.State > 30) // HUD
3626 if (g.OwnerID != AgentId)
3627 return; // Don't send updates for other people's HUDs
3628 }
3629
3595 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3630 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3596 3631
3597 lock (m_entityUpdates.SyncRoot) 3632 lock (m_entityUpdates.SyncRoot)
@@ -3658,211 +3693,230 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3658 3693
3659 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3694 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3660 // condition where a kill can be processed before an out-of-date update for the same object. 3695 // condition where a kill can be processed before an out-of-date update for the same object.
3661 lock (m_killRecord) 3696 float avgTimeDilation = 1.0f;
3697 IEntityUpdate iupdate;
3698 Int32 timeinqueue; // this is just debugging code & can be dropped later
3699
3700 while (updatesThisCall < maxUpdates)
3662 { 3701 {
3663 float avgTimeDilation = 1.0f; 3702 lock (m_entityUpdates.SyncRoot)
3664 IEntityUpdate iupdate; 3703 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3665 Int32 timeinqueue; // this is just debugging code & can be dropped later 3704 break;
3666
3667 while (updatesThisCall < maxUpdates)
3668 {
3669 lock (m_entityUpdates.SyncRoot)
3670 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3671 break;
3672 3705
3673 EntityUpdate update = (EntityUpdate)iupdate; 3706 EntityUpdate update = (EntityUpdate)iupdate;
3674 3707
3675 avgTimeDilation += update.TimeDilation; 3708 avgTimeDilation += update.TimeDilation;
3676 avgTimeDilation *= 0.5f; 3709 avgTimeDilation *= 0.5f;
3677 3710
3678 if (update.Entity is SceneObjectPart) 3711 if (update.Entity is SceneObjectPart)
3712 {
3713 SceneObjectPart part = (SceneObjectPart)update.Entity;
3714
3715 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3716 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3717 // safety measure.
3718 //
3719 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3720 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3721 // updates and kills on different threads with different scheduling strategies, hence this protection.
3722 //
3723 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3724 // after the root prim has been deleted.
3725 lock (m_killRecord)
3679 { 3726 {
3680 SceneObjectPart part = (SceneObjectPart)update.Entity;
3681
3682 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3683 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3684 // safety measure.
3685 //
3686 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3687 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3688 // updates and kills on different threads with different scheduling strategies, hence this protection.
3689 //
3690 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3691 // after the root prim has been deleted.
3692 if (m_killRecord.Contains(part.LocalId)) 3727 if (m_killRecord.Contains(part.LocalId))
3693 {
3694 // m_log.WarnFormat(
3695 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3696 // part.LocalId, Name);
3697 continue; 3728 continue;
3698 } 3729 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3699 3730 continue;
3700 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3731 }
3732
3733 if (part.ParentGroup.IsDeleted)
3734 continue;
3735
3736 if (part.ParentGroup.IsAttachment)
3737 { // Someone else's HUD, why are we getting these?
3738 if (part.ParentGroup.OwnerID != AgentId &&
3739 part.ParentGroup.RootPart.Shape.State >= 30)
3740 continue;
3741 ScenePresence sp;
3742 // Owner is not in the sim, don't update it to
3743 // anyone
3744 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3745 continue;
3746
3747 List<SceneObjectGroup> atts = sp.GetAttachments();
3748 bool found = false;
3749 foreach (SceneObjectGroup att in atts)
3701 { 3750 {
3702 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3751 if (att == part.ParentGroup)
3703 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3704 { 3752 {
3705 part.Shape.LightEntry = false; 3753 found = true;
3754 break;
3706 } 3755 }
3707 } 3756 }
3757
3758 // It's an attachment of a valid avatar, but
3759 // doesn't seem to be attached, skip
3760 if (!found)
3761 continue;
3708 } 3762 }
3709 3763 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3710 ++updatesThisCall;
3711
3712 #region UpdateFlags to packet type conversion
3713
3714 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3715
3716 bool canUseCompressed = true;
3717 bool canUseImproved = true;
3718
3719 // Compressed object updates only make sense for LL primitives
3720 if (!(update.Entity is SceneObjectPart))
3721 {
3722 canUseCompressed = false;
3723 }
3724
3725 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3726 {
3727 canUseCompressed = false;
3728 canUseImproved = false;
3729 }
3730 else
3731 { 3764 {
3732 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 3765 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3733 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || 3766 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3734 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3735 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3736 {
3737 canUseCompressed = false;
3738 }
3739
3740 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3741 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3742 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3743 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3744 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3745 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3746 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3747 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3748 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3749 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3750 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3751 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3752 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3753 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3754 { 3767 {
3755 canUseImproved = false; 3768 part.Shape.LightEntry = false;
3756 } 3769 }
3757 } 3770 }
3758 3771 }
3759 #endregion UpdateFlags to packet type conversion 3772
3760 3773 ++updatesThisCall;
3761 #region Block Construction 3774
3762 3775 #region UpdateFlags to packet type conversion
3763 // TODO: Remove this once we can build compressed updates 3776
3777 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3778
3779 bool canUseCompressed = true;
3780 bool canUseImproved = true;
3781
3782 // Compressed object updates only make sense for LL primitives
3783 if (!(update.Entity is SceneObjectPart))
3784 {
3764 canUseCompressed = false; 3785 canUseCompressed = false;
3765 3786 }
3766 if (!canUseImproved && !canUseCompressed) 3787
3767 { 3788 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3768 if (update.Entity is ScenePresence) 3789 {
3769 { 3790 canUseCompressed = false;
3770 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); 3791 canUseImproved = false;
3771 objectUpdates.Value.Add(update); 3792 }
3772 } 3793 else
3773 else 3794 {
3774 { 3795 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3775 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); 3796 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3776 objectUpdates.Value.Add(update); 3797 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3777 } 3798 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3778 }
3779 else if (!canUseImproved)
3780 { 3799 {
3781 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); 3800 canUseCompressed = false;
3782 compressedUpdates.Value.Add(update);
3783 } 3801 }
3784 else 3802
3803 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3804 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3805 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3806 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3807 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3808 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3809 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3810 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3811 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3812 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3813 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3814 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3815 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3816 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3785 { 3817 {
3786 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3818 canUseImproved = false;
3787 {
3788 // Self updates go into a special list
3789 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3790 terseAgentUpdates.Value.Add(update);
3791 }
3792 else
3793 {
3794 // Everything else goes here
3795 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3796 terseUpdates.Value.Add(update);
3797 }
3798 } 3819 }
3799
3800 #endregion Block Construction
3801 } 3820 }
3802
3803
3804 #region Packet Sending
3805 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3806 3821
3807 if (terseAgentUpdateBlocks.IsValueCreated) 3822 #endregion UpdateFlags to packet type conversion
3808 {
3809 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3810 3823
3811 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3824 #region Block Construction
3812 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3813 packet.RegionData.TimeDilation = timeDilation;
3814 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3815 3825
3816 for (int i = 0; i < blocks.Count; i++) 3826 // TODO: Remove this once we can build compressed updates
3817 packet.ObjectData[i] = blocks[i]; 3827 canUseCompressed = false;
3818 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3819 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
3820 }
3821 3828
3822 if (objectUpdateBlocks.IsValueCreated) 3829 if (!canUseImproved && !canUseCompressed)
3823 { 3830 {
3824 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3831 if (update.Entity is ScenePresence)
3825 3832 {
3826 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3833 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3827 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3834 }
3828 packet.RegionData.TimeDilation = timeDilation; 3835 else
3829 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3836 {
3830 3837 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3831 for (int i = 0; i < blocks.Count; i++) 3838 }
3832 packet.ObjectData[i] = blocks[i];
3833 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3834 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3835 } 3839 }
3836 3840 else if (!canUseImproved)
3837 if (compressedUpdateBlocks.IsValueCreated)
3838 { 3841 {
3839 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 3842 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3840
3841 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3842 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3843 packet.RegionData.TimeDilation = timeDilation;
3844 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3845
3846 for (int i = 0; i < blocks.Count; i++)
3847 packet.ObjectData[i] = blocks[i];
3848 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3849 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3850 } 3843 }
3851 3844 else
3852 if (terseUpdateBlocks.IsValueCreated)
3853 { 3845 {
3854 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 3846 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3855 3847 // Self updates go into a special list
3856 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3848 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3857 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3849 else
3858 packet.RegionData.TimeDilation = timeDilation; 3850 // Everything else goes here
3859 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3851 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3860
3861 for (int i = 0; i < blocks.Count; i++)
3862 packet.ObjectData[i] = blocks[i];
3863 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3864 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3865 } 3852 }
3853
3854 #endregion Block Construction
3855 }
3856
3857 #region Packet Sending
3858
3859 const float TIME_DILATION = 1.0f;
3860 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3861
3862 if (terseAgentUpdateBlocks.IsValueCreated)
3863 {
3864 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3865
3866 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3867 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3868 packet.RegionData.TimeDilation = timeDilation;
3869 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3870
3871 for (int i = 0; i < blocks.Count; i++)
3872 packet.ObjectData[i] = blocks[i];
3873
3874 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3875 }
3876
3877 if (objectUpdateBlocks.IsValueCreated)
3878 {
3879 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3880
3881 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3882 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3883 packet.RegionData.TimeDilation = timeDilation;
3884 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3885
3886 for (int i = 0; i < blocks.Count; i++)
3887 packet.ObjectData[i] = blocks[i];
3888
3889 OutPacket(packet, ThrottleOutPacketType.Task, true);
3890 }
3891
3892 if (compressedUpdateBlocks.IsValueCreated)
3893 {
3894 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3895
3896 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3897 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3898 packet.RegionData.TimeDilation = timeDilation;
3899 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3900
3901 for (int i = 0; i < blocks.Count; i++)
3902 packet.ObjectData[i] = blocks[i];
3903
3904 OutPacket(packet, ThrottleOutPacketType.Task, true);
3905 }
3906
3907 if (terseUpdateBlocks.IsValueCreated)
3908 {
3909 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3910
3911 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3912 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3913 packet.RegionData.TimeDilation = timeDilation;
3914 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3915
3916 for (int i = 0; i < blocks.Count; i++)
3917 packet.ObjectData[i] = blocks[i];
3918
3919 OutPacket(packet, ThrottleOutPacketType.Task, true);
3866 } 3920 }
3867 3921
3868 #endregion Packet Sending 3922 #endregion Packet Sending
@@ -4163,11 +4217,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4163 4217
4164 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4218 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4165 // of the object rather than the properties when the packet was created 4219 // of the object rather than the properties when the packet was created
4166 OutPacket(packet, ThrottleOutPacketType.Task, true, 4220 // HACK : Remove intelligent resending until it's fixed in core
4167 delegate(OutgoingPacket oPacket) 4221 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4168 { 4222 // delegate(OutgoingPacket oPacket)
4169 ResendPropertyUpdates(updates, oPacket); 4223 // {
4170 }); 4224 // ResendPropertyUpdates(updates, oPacket);
4225 // });
4226 OutPacket(packet, ThrottleOutPacketType.Task, true);
4171 4227
4172 // pbcnt += blocks.Count; 4228 // pbcnt += blocks.Count;
4173 // ppcnt++; 4229 // ppcnt++;
@@ -4193,11 +4249,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4193 // of the object rather than the properties when the packet was created 4249 // of the object rather than the properties when the packet was created
4194 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4250 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4195 updates.Add(familyUpdates.Value[i]); 4251 updates.Add(familyUpdates.Value[i]);
4196 OutPacket(packet, ThrottleOutPacketType.Task, true, 4252 // HACK : Remove intelligent resending until it's fixed in core
4197 delegate(OutgoingPacket oPacket) 4253 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4198 { 4254 // delegate(OutgoingPacket oPacket)
4199 ResendPropertyUpdates(updates, oPacket); 4255 // {
4200 }); 4256 // ResendPropertyUpdates(updates, oPacket);
4257 // });
4258 OutPacket(packet, ThrottleOutPacketType.Task, true);
4201 4259
4202 // fpcnt++; 4260 // fpcnt++;
4203 // fbcnt++; 4261 // fbcnt++;
@@ -4346,37 +4404,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4346 if (bl[i].BannedUserID == UUID.Zero) 4404 if (bl[i].BannedUserID == UUID.Zero)
4347 continue; 4405 continue;
4348 BannedUsers.Add(bl[i].BannedUserID); 4406 BannedUsers.Add(bl[i].BannedUserID);
4349 }
4350 4407
4351 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); 4408 if (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 0))
4352 packet.AgentData.TransactionID = UUID.Random(); 4409 {
4353 packet.AgentData.AgentID = AgentId; 4410 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4354 packet.AgentData.SessionID = SessionId; 4411 packet.AgentData.TransactionID = UUID.Random();
4355 packet.MethodData.Invoice = invoice; 4412 packet.AgentData.AgentID = AgentId;
4356 packet.MethodData.Method = Utils.StringToBytes("setaccess"); 4413 packet.AgentData.SessionID = SessionId;
4414 packet.MethodData.Invoice = invoice;
4415 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4357 4416
4358 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; 4417 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
4359 4418
4360 for (int i = 0; i < (6 + BannedUsers.Count); i++) 4419 int j;
4361 { 4420 for (j = 0; j < (6 + BannedUsers.Count); j++)
4362 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); 4421 {
4363 } 4422 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4364 int j = 0; 4423 }
4424 j = 0;
4365 4425
4366 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4426 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4367 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4427 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
4368 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4428 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4369 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4429 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4370 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; 4430 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
4371 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4431 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4372 4432
4373 foreach (UUID banned in BannedUsers) 4433 foreach (UUID banned in BannedUsers)
4374 { 4434 {
4375 returnblock[j].Parameter = banned.GetBytes(); j++; 4435 returnblock[j].Parameter = banned.GetBytes(); j++;
4436 }
4437 packet.ParamList = returnblock;
4438 packet.Header.Reliable = true;
4439 OutPacket(packet, ThrottleOutPacketType.Task);
4440
4441 BannedUsers.Clear();
4442 }
4376 } 4443 }
4377 packet.ParamList = returnblock; 4444
4378 packet.Header.Reliable = false;
4379 OutPacket(packet, ThrottleOutPacketType.Task);
4380 } 4445 }
4381 4446
4382 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) 4447 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
@@ -4545,7 +4610,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4545 4610
4546 if (landData.SimwideArea > 0) 4611 if (landData.SimwideArea > 0)
4547 { 4612 {
4548 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4613 int simulatorCapacity = (int)((double)(landData.SimwideArea * m_scene.RegionInfo.ObjectCapacity) * m_scene.RegionInfo.RegionSettings.ObjectBonus) / 65536;
4614 // Never report more than sim total capacity
4615 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4616 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4549 updateMessage.SimWideMaxPrims = simulatorCapacity; 4617 updateMessage.SimWideMaxPrims = simulatorCapacity;
4550 } 4618 }
4551 else 4619 else
@@ -4674,14 +4742,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4674 4742
4675 if (notifyCount > 0) 4743 if (notifyCount > 0)
4676 { 4744 {
4677 if (notifyCount > 32) 4745// if (notifyCount > 32)
4678 { 4746// {
4679 m_log.InfoFormat( 4747// m_log.InfoFormat(
4680 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4748// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4681 + " - a developer might want to investigate whether this is a hard limit", 32); 4749// + " - a developer might want to investigate whether this is a hard limit", 32);
4682 4750//
4683 notifyCount = 32; 4751// notifyCount = 32;
4684 } 4752// }
4685 4753
4686 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4754 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4687 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4755 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5215,6 +5283,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5215 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5283 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5216 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5284 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5217 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5285 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5286 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5218 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5287 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5219 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5288 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5220 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5289 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5316,6 +5385,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5316 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5385 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5317 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5386 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5318 (x.ControlFlags != lastarg.ControlFlags) || 5387 (x.ControlFlags != lastarg.ControlFlags) ||
5388 (x.ControlFlags != 0) ||
5319 (x.Far != lastarg.Far) || 5389 (x.Far != lastarg.Far) ||
5320 (x.Flags != lastarg.Flags) || 5390 (x.Flags != lastarg.Flags) ||
5321 (x.State != lastarg.State) || 5391 (x.State != lastarg.State) ||
@@ -5693,7 +5763,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5693 args.Channel = ch; 5763 args.Channel = ch;
5694 args.From = String.Empty; 5764 args.From = String.Empty;
5695 args.Message = Utils.BytesToString(msg); 5765 args.Message = Utils.BytesToString(msg);
5696 args.Type = ChatTypeEnum.Shout; 5766 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5697 args.Position = new Vector3(); 5767 args.Position = new Vector3();
5698 args.Scene = Scene; 5768 args.Scene = Scene;
5699 args.Sender = this; 5769 args.Sender = this;
@@ -9699,7 +9769,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9699 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9769 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9700 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9770 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9701 UpdateMuteListEntry.MuteData.MuteType, 9771 UpdateMuteListEntry.MuteData.MuteType,
9702 UpdateMuteListEntry.AgentData.AgentID); 9772 UpdateMuteListEntry.MuteData.MuteFlags);
9703 return true; 9773 return true;
9704 } 9774 }
9705 return false; 9775 return false;
@@ -9714,8 +9784,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9714 { 9784 {
9715 handlerRemoveMuteListEntry(this, 9785 handlerRemoveMuteListEntry(this,
9716 RemoveMuteListEntry.MuteData.MuteID, 9786 RemoveMuteListEntry.MuteData.MuteID,
9717 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9787 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9718 RemoveMuteListEntry.AgentData.AgentID);
9719 return true; 9788 return true;
9720 } 9789 }
9721 return false; 9790 return false;
@@ -9763,6 +9832,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9763 { 9832 {
9764 return true; 9833 return true;
9765 } 9834 }
9835
9836 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9837 {
9838 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9839
9840 #region Packet Session and User Check
9841 if (m_checkPackets)
9842 {
9843 if (packet.AgentData.SessionID != SessionId ||
9844 packet.AgentData.AgentID != AgentId)
9845 return true;
9846 }
9847 #endregion
9848 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9849 List<InventoryItemBase> items = new List<InventoryItemBase>();
9850 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9851 {
9852 InventoryItemBase b = new InventoryItemBase();
9853 b.ID = n.OldItemID;
9854 b.Folder = n.OldFolderID;
9855 items.Add(b);
9856 }
9857
9858 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9859 if (handlerMoveItemsAndLeaveCopy != null)
9860 {
9861 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9862 }
9863
9864 return true;
9865 }
9766 9866
9767 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9867 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9768 { 9868 {
@@ -10189,6 +10289,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10189 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10289 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10190 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10290 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10191 10291
10292 Scene scene = (Scene)m_scene;
10293 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10294 {
10295 ScenePresence p;
10296 if (scene.TryGetScenePresence(sender.AgentId, out p))
10297 {
10298 if (p.GodLevel >= 200)
10299 {
10300 groupProfileReply.GroupData.OpenEnrollment = true;
10301 groupProfileReply.GroupData.MembershipFee = 0;
10302 }
10303 }
10304 }
10305
10192 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10306 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10193 } 10307 }
10194 return true; 10308 return true;
@@ -10761,11 +10875,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10761 10875
10762 StartLure handlerStartLure = OnStartLure; 10876 StartLure handlerStartLure = OnStartLure;
10763 if (handlerStartLure != null) 10877 if (handlerStartLure != null)
10764 handlerStartLure(startLureRequest.Info.LureType, 10878 {
10765 Utils.BytesToString( 10879 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10766 startLureRequest.Info.Message), 10880 {
10767 startLureRequest.TargetData[0].TargetID, 10881 handlerStartLure(startLureRequest.Info.LureType,
10768 this); 10882 Utils.BytesToString(
10883 startLureRequest.Info.Message),
10884 startLureRequest.TargetData[i].TargetID,
10885 this);
10886 }
10887 }
10769 return true; 10888 return true;
10770 } 10889 }
10771 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10890 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10879,10 +10998,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10879 } 10998 }
10880 #endregion 10999 #endregion
10881 11000
10882 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11001 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
10883 if (handlerClassifiedGodDelete != null) 11002 if (handlerClassifiedGodDelete != null)
10884 handlerClassifiedGodDelete( 11003 handlerClassifiedGodDelete(
10885 classifiedGodDelete.Data.ClassifiedID, 11004 classifiedGodDelete.Data.ClassifiedID,
11005 classifiedGodDelete.Data.QueryID,
10886 this); 11006 this);
10887 return true; 11007 return true;
10888 } 11008 }
@@ -11265,7 +11385,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11265 { 11385 {
11266 // It's a ghost! tell the client to delete it from view. 11386 // It's a ghost! tell the client to delete it from view.
11267 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11387 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
11268 localId); 11388 new List<uint>() { localId });
11269 } 11389 }
11270 else 11390 else
11271 { 11391 {
@@ -11912,7 +12032,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11912 12032
11913// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 12033// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11914 12034
12035
12036 //Note, the bool returned from the below function is useless since it is always false.
11915 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12037 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12038
11916 } 12039 }
11917 12040
11918 /// <summary> 12041 /// <summary>
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index ffa3be4..c951071 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -158,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 158
159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
160 private int m_maxRTO = 60000; 160 private int m_maxRTO = 60000;
161 public bool m_deliverPackets = true;
161 162
162 /// <summary> 163 /// <summary>
163 /// Default constructor 164 /// Default constructor
@@ -439,6 +440,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
439 if (category >= 0 && category < m_packetOutboxes.Length) 440 if (category >= 0 && category < m_packetOutboxes.Length)
440 { 441 {
441 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 442 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
443
444 if (m_deliverPackets == false)
445 {
446 queue.Enqueue(packet);
447 return true;
448 }
449
442 TokenBucket bucket = m_throttleCategories[category]; 450 TokenBucket bucket = m_throttleCategories[category];
443 451
444 // Don't send this packet if there is already a packet waiting in the queue 452 // Don't send this packet if there is already a packet waiting in the queue
@@ -488,6 +496,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
488 /// <returns>True if any packets were sent, otherwise false</returns> 496 /// <returns>True if any packets were sent, otherwise false</returns>
489 public bool DequeueOutgoing() 497 public bool DequeueOutgoing()
490 { 498 {
499 if (m_deliverPackets == false) return false;
500
491 OutgoingPacket packet; 501 OutgoingPacket packet;
492 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 502 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
493 TokenBucket bucket; 503 TokenBucket bucket;
@@ -520,7 +530,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
520 // No dequeued packet waiting to be sent, try to pull one off 530 // No dequeued packet waiting to be sent, try to pull one off
521 // this queue 531 // this queue
522 queue = m_packetOutboxes[i]; 532 queue = m_packetOutboxes[i];
523 if (queue.Dequeue(out packet)) 533 if (queue != null && queue.Dequeue(out packet))
524 { 534 {
525 // A packet was pulled off the queue. See if we have 535 // A packet was pulled off the queue. See if we have
526 // enough tokens in the bucket to send it out 536 // enough tokens in the bucket to send it out
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index ccad241..ae8251a 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -991,7 +991,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
991 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 991 if (m_scene.TryGetClient(udpClient.AgentID, out client))
992 { 992 {
993 client.IsLoggingOut = true; 993 client.IsLoggingOut = true;
994 client.Close(); 994 client.Close(false);
995 } 995 }
996 } 996 }
997 997
@@ -1003,6 +1003,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1003 1003
1004 while (base.IsRunning) 1004 while (base.IsRunning)
1005 { 1005 {
1006 m_scene.ThreadAlive(1);
1006 try 1007 try
1007 { 1008 {
1008 IncomingPacket incomingPacket = null; 1009 IncomingPacket incomingPacket = null;
@@ -1045,6 +1046,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1045 1046
1046 while (base.IsRunning) 1047 while (base.IsRunning)
1047 { 1048 {
1049 m_scene.ThreadAlive(2);
1048 try 1050 try
1049 { 1051 {
1050 m_packetSent = false; 1052 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 6eebd9d..d2779ba 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -100,10 +100,6 @@ namespace OpenMetaverse
100 const int SIO_UDP_CONNRESET = -1744830452; 100 const int SIO_UDP_CONNRESET = -1744830452;
101 101
102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 102 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
103
104 m_log.DebugFormat(
105 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
106 ipep.Address, ipep.Port);
107 103
108 m_udpSocket = new Socket( 104 m_udpSocket = new Socket(
109 AddressFamily.InterNetwork, 105 AddressFamily.InterNetwork,