aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs695
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs10
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs66
5 files changed, 436 insertions, 342 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index e9e2dca..9dd6663 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/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/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index ee4f04e..e416d05 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -155,6 +155,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
155 public event RequestTaskInventory OnRequestTaskInventory; 155 public event RequestTaskInventory OnRequestTaskInventory;
156 public event UpdateInventoryItem OnUpdateInventoryItem; 156 public event UpdateInventoryItem OnUpdateInventoryItem;
157 public event CopyInventoryItem OnCopyInventoryItem; 157 public event CopyInventoryItem OnCopyInventoryItem;
158 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
158 public event MoveInventoryItem OnMoveInventoryItem; 159 public event MoveInventoryItem OnMoveInventoryItem;
159 public event RemoveInventoryItem OnRemoveInventoryItem; 160 public event RemoveInventoryItem OnRemoveInventoryItem;
160 public event RemoveInventoryFolder OnRemoveInventoryFolder; 161 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -327,7 +328,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
327 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 328 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
328 /// ownerless phantom. 329 /// ownerless phantom.
329 /// 330 ///
330 /// All manipulation of this set has to occur under a lock 331 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
331 /// 332 ///
332 /// </value> 333 /// </value>
333 protected HashSet<uint> m_killRecord; 334 protected HashSet<uint> m_killRecord;
@@ -335,6 +336,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
335// protected HashSet<uint> m_attachmentsSent; 336// protected HashSet<uint> m_attachmentsSent;
336 337
337 private int m_moneyBalance; 338 private int m_moneyBalance;
339 private bool m_deliverPackets = true;
338 private int m_animationSequenceNumber = 1; 340 private int m_animationSequenceNumber = 1;
339 private bool m_SendLogoutPacketWhenClosing = true; 341 private bool m_SendLogoutPacketWhenClosing = true;
340 private AgentUpdateArgs lastarg; 342 private AgentUpdateArgs lastarg;
@@ -377,6 +379,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
377 get { return m_startpos; } 379 get { return m_startpos; }
378 set { m_startpos = value; } 380 set { m_startpos = value; }
379 } 381 }
382 public bool DeliverPackets
383 {
384 get { return m_deliverPackets; }
385 set {
386 m_deliverPackets = value;
387 m_udpClient.m_deliverPackets = value;
388 }
389 }
380 public UUID AgentId { get { return m_agentId; } } 390 public UUID AgentId { get { return m_agentId; } }
381 public UUID ActiveGroupId { get { return m_activeGroupID; } } 391 public UUID ActiveGroupId { get { return m_activeGroupID; } }
382 public string ActiveGroupName { get { return m_activeGroupName; } } 392 public string ActiveGroupName { get { return m_activeGroupName; } }
@@ -475,18 +485,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
475 485
476 #region Client Methods 486 #region Client Methods
477 487
488
478 /// <summary> 489 /// <summary>
479 /// Shut down the client view 490 /// Shut down the client view
480 /// </summary> 491 /// </summary>
481 public void Close() 492 public void Close()
482 { 493 {
494 Close(true);
495 }
496
497 /// <summary>
498 /// Shut down the client view
499 /// </summary>
500 public void Close(bool sendStop)
501 {
483 m_log.DebugFormat( 502 m_log.DebugFormat(
484 "[CLIENT]: Close has been called for {0} attached to scene {1}", 503 "[CLIENT]: Close has been called for {0} attached to scene {1}",
485 Name, m_scene.RegionInfo.RegionName); 504 Name, m_scene.RegionInfo.RegionName);
486 505
487 // Send the STOP packet 506 if (sendStop)
488 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 507 {
489 OutPacket(disable, ThrottleOutPacketType.Unknown); 508 // Send the STOP packet
509 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
510 OutPacket(disable, ThrottleOutPacketType.Unknown);
511 }
490 512
491 IsActive = false; 513 IsActive = false;
492 514
@@ -767,7 +789,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
767 reply.ChatData.OwnerID = fromAgentID; 789 reply.ChatData.OwnerID = fromAgentID;
768 reply.ChatData.SourceID = fromAgentID; 790 reply.ChatData.SourceID = fromAgentID;
769 791
770 OutPacket(reply, ThrottleOutPacketType.Task); 792 OutPacket(reply, ThrottleOutPacketType.Unknown);
771 } 793 }
772 794
773 /// <summary> 795 /// <summary>
@@ -1053,6 +1075,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1053 public virtual void SendLayerData(float[] map) 1075 public virtual void SendLayerData(float[] map)
1054 { 1076 {
1055 Util.FireAndForget(DoSendLayerData, map); 1077 Util.FireAndForget(DoSendLayerData, map);
1078
1079 // Send it sync, and async. It's not that much data
1080 // and it improves user experience just so much!
1081 DoSendLayerData(map);
1056 } 1082 }
1057 1083
1058 /// <summary> 1084 /// <summary>
@@ -1065,16 +1091,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1065 1091
1066 try 1092 try
1067 { 1093 {
1068 //for (int y = 0; y < 16; y++) 1094 for (int y = 0; y < 16; y++)
1069 //{ 1095 {
1070 // for (int x = 0; x < 16; x++) 1096 for (int x = 0; x < 16; x+=4)
1071 // { 1097 {
1072 // SendLayerData(x, y, map); 1098 SendLayerPacket(x, y, map);
1073 // } 1099 }
1074 //} 1100 }
1075
1076 // Send LayerData in a spiral pattern. Fun!
1077 SendLayerTopRight(map, 0, 0, 15, 15);
1078 } 1101 }
1079 catch (Exception e) 1102 catch (Exception e)
1080 { 1103 {
@@ -1082,51 +1105,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1082 } 1105 }
1083 } 1106 }
1084 1107
1085 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1086 {
1087 // Row
1088 for (int i = x1; i <= x2; i++)
1089 SendLayerData(i, y1, map);
1090
1091 // Column
1092 for (int j = y1 + 1; j <= y2; j++)
1093 SendLayerData(x2, j, map);
1094
1095 if (x2 - x1 > 0)
1096 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1097 }
1098
1099 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1100 {
1101 // Row in reverse
1102 for (int i = x2; i >= x1; i--)
1103 SendLayerData(i, y2, map);
1104
1105 // Column in reverse
1106 for (int j = y2 - 1; j >= y1; j--)
1107 SendLayerData(x1, j, map);
1108
1109 if (x2 - x1 > 0)
1110 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1111 }
1112
1113 /// <summary> 1108 /// <summary>
1114 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1109 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1115 /// </summary> 1110 /// </summary>
1116 /// <param name="map">heightmap</param> 1111 /// <param name="map">heightmap</param>
1117 /// <param name="px">X coordinate for patches 0..12</param> 1112 /// <param name="px">X coordinate for patches 0..12</param>
1118 /// <param name="py">Y coordinate for patches 0..15</param> 1113 /// <param name="py">Y coordinate for patches 0..15</param>
1119 // private void SendLayerPacket(float[] map, int y, int x) 1114 private void SendLayerPacket(int x, int y, float[] map)
1120 // { 1115 {
1121 // int[] patches = new int[4]; 1116 int[] patches = new int[4];
1122 // patches[0] = x + 0 + y * 16; 1117 patches[0] = x + 0 + y * 16;
1123 // patches[1] = x + 1 + y * 16; 1118 patches[1] = x + 1 + y * 16;
1124 // patches[2] = x + 2 + y * 16; 1119 patches[2] = x + 2 + y * 16;
1125 // patches[3] = x + 3 + y * 16; 1120 patches[3] = x + 3 + y * 16;
1126 1121
1127 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1122 float[] heightmap = (map.Length == 65536) ?
1128 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1123 map :
1129 // } 1124 LLHeightFieldMoronize(map);
1125
1126 try
1127 {
1128 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1129 OutPacket(layerpack, ThrottleOutPacketType.Land);
1130 }
1131 catch
1132 {
1133 for (int px = x ; px < x + 4 ; px++)
1134 SendLayerData(px, y, map);
1135 }
1136 }
1130 1137
1131 /// <summary> 1138 /// <summary>
1132 /// Sends a specified patch to a client 1139 /// Sends a specified patch to a client
@@ -1146,7 +1153,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1146 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1153 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1147 layerpack.Header.Reliable = true; 1154 layerpack.Header.Reliable = true;
1148 1155
1149 OutPacket(layerpack, ThrottleOutPacketType.Land); 1156 OutPacket(layerpack, ThrottleOutPacketType.Task);
1150 } 1157 }
1151 catch (Exception e) 1158 catch (Exception e)
1152 { 1159 {
@@ -1507,37 +1514,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1507 OutPacket(pc, ThrottleOutPacketType.Unknown); 1514 OutPacket(pc, ThrottleOutPacketType.Unknown);
1508 } 1515 }
1509 1516
1510 public void SendKillObject(ulong regionHandle, uint localID) 1517 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1511 { 1518 {
1512// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1519// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1513 1520
1514 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1521 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1515 // TODO: don't create new blocks if recycling an old packet 1522 // TODO: don't create new blocks if recycling an old packet
1516 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; 1523 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1517 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); 1524 for (int i = 0 ; i < localIDs.Count ; i++ )
1518 kill.ObjectData[0].ID = localID; 1525 {
1526 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1527 kill.ObjectData[i].ID = localIDs[i];
1528 }
1519 kill.Header.Reliable = true; 1529 kill.Header.Reliable = true;
1520 kill.Header.Zerocoded = true; 1530 kill.Header.Zerocoded = true;
1521 1531
1522 if (m_scene.GetScenePresence(localID) == null) 1532 lock (m_killRecord)
1523 { 1533 {
1524 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1534 if (localIDs.Count == 1)
1525 // condition where a kill can be processed before an out-of-date update for the same object. 1535 {
1526 lock (m_killRecord) 1536 if (m_scene.GetScenePresence(localIDs[0]) != null)
1537 {
1538 OutPacket(kill, ThrottleOutPacketType.State);
1539 return;
1540 }
1541 m_killRecord.Add(localIDs[0]);
1542 }
1543 else
1527 { 1544 {
1528 m_killRecord.Add(localID); 1545 lock (m_entityUpdates.SyncRoot)
1529 1546 {
1530 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1547 foreach (uint localID in localIDs)
1531 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1548 m_killRecord.Add(localID);
1532 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1549 }
1533 // scene objects in a viewer until that viewer is relogged in.
1534 OutPacket(kill, ThrottleOutPacketType.Task);
1535 } 1550 }
1536 } 1551 }
1537 else 1552
1538 { 1553 // The throttle queue used here must match that being used for
1539 OutPacket(kill, ThrottleOutPacketType.State); 1554 // updates. Otherwise, there is a chance that a kill packet put
1540 } 1555 // on a separate queue will be sent to the client before an
1556 // existing update packet on another queue. Receiving updates
1557 // after kills results in unowned and undeletable
1558 // scene objects in a viewer until that viewer is relogged in.
1559 OutPacket(kill, ThrottleOutPacketType.Task);
1541 } 1560 }
1542 1561
1543 /// <summary> 1562 /// <summary>
@@ -2250,6 +2269,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2250 OutPacket(sound, ThrottleOutPacketType.Task); 2269 OutPacket(sound, ThrottleOutPacketType.Task);
2251 } 2270 }
2252 2271
2272 public void SendTransferAbort(TransferRequestPacket transferRequest)
2273 {
2274 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2275 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2276 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2277 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2278 OutPacket(abort, ThrottleOutPacketType.Task);
2279 }
2280
2253 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2281 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2254 { 2282 {
2255 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2283 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3551,6 +3579,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3551 /// </summary> 3579 /// </summary>
3552 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3580 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3553 { 3581 {
3582 if (entity is SceneObjectPart)
3583 {
3584 SceneObjectPart e = (SceneObjectPart)entity;
3585 SceneObjectGroup g = e.ParentGroup;
3586 if (g.RootPart.Shape.State > 30) // HUD
3587 if (g.OwnerID != AgentId)
3588 return; // Don't send updates for other people's HUDs
3589 }
3590
3554 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3591 double priority = m_prioritizer.GetUpdatePriority(this, entity);
3555 3592
3556 lock (m_entityUpdates.SyncRoot) 3593 lock (m_entityUpdates.SyncRoot)
@@ -3567,232 +3604,257 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3567 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3604 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue;
3568 int updatesThisCall = 0; 3605 int updatesThisCall = 0;
3569 3606
3570 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3607 float avgTimeDilation = 0;
3571 // condition where a kill can be processed before an out-of-date update for the same object. 3608
3572 lock (m_killRecord) 3609 EntityUpdate update;
3610 while (updatesThisCall < maxUpdates)
3573 { 3611 {
3574 float avgTimeDilation = 1.0f; 3612 lock (m_entityUpdates.SyncRoot)
3575 EntityUpdate update; 3613 if (!m_entityUpdates.TryDequeue(out update))
3576 while (updatesThisCall < maxUpdates) 3614 break;
3615
3616 avgTimeDilation += update.TimeDilation;
3617 avgTimeDilation *= 0.5f;
3618
3619 if (update.Entity is SceneObjectPart)
3577 { 3620 {
3578 lock (m_entityUpdates.SyncRoot) 3621 SceneObjectPart part = (SceneObjectPart)update.Entity;
3579 if (!m_entityUpdates.TryDequeue(out update))
3580 break;
3581 avgTimeDilation += update.TimeDilation;
3582 avgTimeDilation *= 0.5f;
3583 3622
3584 if (update.Entity is SceneObjectPart) 3623 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3624 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3625 // safety measure.
3626 //
3627 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3628 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3629 // updates and kills on different threads with different scheduling strategies, hence this protection.
3630 //
3631 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3632 // after the root prim has been deleted.
3633 lock (m_killRecord)
3585 { 3634 {
3586 SceneObjectPart part = (SceneObjectPart)update.Entity;
3587
3588 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3589 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3590 // safety measure.
3591 //
3592 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3593 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3594 // updates and kills on different threads with different scheduling strategies, hence this protection.
3595 //
3596 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3597 // after the root prim has been deleted.
3598 if (m_killRecord.Contains(part.LocalId)) 3635 if (m_killRecord.Contains(part.LocalId))
3599 {
3600 // m_log.WarnFormat(
3601 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3602 // part.LocalId, Name);
3603 continue; 3636 continue;
3604 } 3637 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3605 3638 continue;
3606 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3639 }
3640
3641 if (part.ParentGroup.IsDeleted)
3642 continue;
3643
3644 if (part.ParentGroup.IsAttachment)
3645 { // Someone else's HUD, why are we getting these?
3646 if (part.ParentGroup.OwnerID != AgentId &&
3647 part.ParentGroup.RootPart.Shape.State >= 30)
3648 continue;
3649 ScenePresence sp;
3650 // Owner is not in the sim, don't update it to
3651 // anyone
3652 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3653 continue;
3654
3655 List<SceneObjectGroup> atts = sp.Attachments;
3656 bool found = false;
3657 foreach (SceneObjectGroup att in atts)
3607 { 3658 {
3608 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3659 if (att == part.ParentGroup)
3609 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3610 { 3660 {
3611 part.Shape.LightEntry = false; 3661 found = true;
3662 break;
3612 } 3663 }
3613 } 3664 }
3665
3666 // It's an attachment of a valid avatar, but
3667 // doesn't seem to be attached, skip
3668 if (!found)
3669 continue;
3614 } 3670 }
3615 3671
3616 ++updatesThisCall; 3672 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3617
3618 #region UpdateFlags to packet type conversion
3619
3620 PrimUpdateFlags updateFlags = update.Flags;
3621
3622 bool canUseCompressed = true;
3623 bool canUseImproved = true;
3624
3625 // Compressed object updates only make sense for LL primitives
3626 if (!(update.Entity is SceneObjectPart))
3627 {
3628 canUseCompressed = false;
3629 }
3630
3631 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3632 {
3633 canUseCompressed = false;
3634 canUseImproved = false;
3635 }
3636 else
3637 { 3673 {
3638 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 3674 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3639 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || 3675 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3640 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3641 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3642 { 3676 {
3643 canUseCompressed = false; 3677 part.Shape.LightEntry = false;
3644 }
3645
3646 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3647 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3648 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3649 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3650 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3651 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3652 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3653 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3654 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3655 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3656 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3657 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3658 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3659 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3660 {
3661 canUseImproved = false;
3662 } 3678 }
3663 } 3679 }
3664 3680 }
3665 #endregion UpdateFlags to packet type conversion 3681
3666 3682 ++updatesThisCall;
3667 #region Block Construction 3683
3668 3684 #region UpdateFlags to packet type conversion
3669 // TODO: Remove this once we can build compressed updates 3685
3686 PrimUpdateFlags updateFlags = update.Flags;
3687
3688 bool canUseCompressed = true;
3689 bool canUseImproved = true;
3690
3691 // Compressed object updates only make sense for LL primitives
3692 if (!(update.Entity is SceneObjectPart))
3693 {
3670 canUseCompressed = false; 3694 canUseCompressed = false;
3671 3695 }
3672 if (!canUseImproved && !canUseCompressed) 3696
3697 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3698 {
3699 canUseCompressed = false;
3700 canUseImproved = false;
3701 }
3702 else
3703 {
3704 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3705 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3706 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3707 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3673 { 3708 {
3674 if (update.Entity is ScenePresence) 3709 canUseCompressed = false;
3675 {
3676 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3677 }
3678 else
3679 {
3680 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3681 // {
3682 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3683 // string text = sop.Text;
3684 // if (text.IndexOf("\n") >= 0)
3685 // text = text.Remove(text.IndexOf("\n"));
3686 //
3687 // if (m_attachmentsSent.Contains(sop.ParentID))
3688 // {
3689 //// m_log.DebugFormat(
3690 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3691 //// sop.LocalId, text);
3692 //
3693 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3694 //
3695 // m_attachmentsSent.Add(sop.LocalId);
3696 // }
3697 // else
3698 // {
3699 // m_log.DebugFormat(
3700 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3701 // sop.LocalId, text, sop.ParentID);
3702 //
3703 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3704 // }
3705 // }
3706 // else
3707 // {
3708 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3709 // }
3710 }
3711 } 3710 }
3712 else if (!canUseImproved) 3711
3712 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3713 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3714 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3715 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3716 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3717 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3718 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3719 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3720 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3721 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3722 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3723 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3724 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3725 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3713 { 3726 {
3714 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); 3727 canUseImproved = false;
3728 }
3729 }
3730
3731 #endregion UpdateFlags to packet type conversion
3732
3733 #region Block Construction
3734
3735 // TODO: Remove this once we can build compressed updates
3736 canUseCompressed = false;
3737
3738 if (!canUseImproved && !canUseCompressed)
3739 {
3740 if (update.Entity is ScenePresence)
3741 {
3742 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3715 } 3743 }
3716 else 3744 else
3717 { 3745 {
3718 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3746// if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3719 // Self updates go into a special list 3747// {
3720 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 3748// SceneObjectPart sop = (SceneObjectPart)update.Entity;
3721 else 3749// string text = sop.Text;
3722 // Everything else goes here 3750// if (text.IndexOf("\n") >= 0)
3723 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 3751// text = text.Remove(text.IndexOf("\n"));
3752//
3753// if (m_attachmentsSent.Contains(sop.ParentID))
3754// {
3755//// m_log.DebugFormat(
3756//// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3757//// sop.LocalId, text);
3758//
3759// objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3760//
3761// m_attachmentsSent.Add(sop.LocalId);
3762// }
3763// else
3764// {
3765// m_log.DebugFormat(
3766// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3767// sop.LocalId, text, sop.ParentID);
3768//
3769// m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3770// }
3771// }
3772// else
3773// {
3774 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3775// }
3724 } 3776 }
3725
3726 #endregion Block Construction
3727 } 3777 }
3778 else if (!canUseImproved)
3779 {
3780 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3781 }
3782 else
3783 {
3784 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3785 // Self updates go into a special list
3786 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3787 else
3788 // Everything else goes here
3789 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3790 }
3791
3792 #endregion Block Construction
3793 }
3794
3795 #region Packet Sending
3728 3796
3729 #region Packet Sending 3797 const float TIME_DILATION = 1.0f;
3730 3798 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3731 //const float TIME_DILATION = 1.0f; 3799
3800 if (terseAgentUpdateBlocks.IsValueCreated)
3801 {
3802 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3803
3804 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3805 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3806 packet.RegionData.TimeDilation = timeDilation;
3807 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3732 3808
3809 for (int i = 0; i < blocks.Count; i++)
3810 packet.ObjectData[i] = blocks[i];
3733 3811
3734 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3812 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3813 }
3814
3815 if (objectUpdateBlocks.IsValueCreated)
3816 {
3817 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3735 3818
3736 if (terseAgentUpdateBlocks.IsValueCreated) 3819 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3737 { 3820 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3738 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3821 packet.RegionData.TimeDilation = timeDilation;
3822 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3823
3824 for (int i = 0; i < blocks.Count; i++)
3825 packet.ObjectData[i] = blocks[i];
3739 3826
3740 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3827 OutPacket(packet, ThrottleOutPacketType.Task, true);
3741 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3828 }
3742 packet.RegionData.TimeDilation = timeDilation; 3829
3743 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3830 if (compressedUpdateBlocks.IsValueCreated)
3831 {
3832 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3744 3833
3745 for (int i = 0; i < blocks.Count; i++) 3834 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3746 packet.ObjectData[i] = blocks[i]; 3835 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3836 packet.RegionData.TimeDilation = timeDilation;
3837 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3747 3838
3748 3839 for (int i = 0; i < blocks.Count; i++)
3749 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3840 packet.ObjectData[i] = blocks[i];
3750 }
3751 3841
3752 if (objectUpdateBlocks.IsValueCreated) 3842 OutPacket(packet, ThrottleOutPacketType.Task, true);
3753 { 3843 }
3754 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3844
3755 3845 if (terseUpdateBlocks.IsValueCreated)
3756 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3846 {
3757 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3847 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3758 packet.RegionData.TimeDilation = timeDilation; 3848
3759 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3849 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3760 3850 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3761 for (int i = 0; i < blocks.Count; i++) 3851 packet.RegionData.TimeDilation = timeDilation;
3762 packet.ObjectData[i] = blocks[i]; 3852 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3763 3853
3764 OutPacket(packet, ThrottleOutPacketType.Task, true); 3854 for (int i = 0; i < blocks.Count; i++)
3765 } 3855 packet.ObjectData[i] = blocks[i];
3766 3856
3767 if (compressedUpdateBlocks.IsValueCreated) 3857 OutPacket(packet, ThrottleOutPacketType.Task, true);
3768 {
3769 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3770
3771 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3772 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3773 packet.RegionData.TimeDilation = timeDilation;
3774 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3775
3776 for (int i = 0; i < blocks.Count; i++)
3777 packet.ObjectData[i] = blocks[i];
3778
3779 OutPacket(packet, ThrottleOutPacketType.Task, true);
3780 }
3781
3782 if (terseUpdateBlocks.IsValueCreated)
3783 {
3784 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3785
3786 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3787 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3788 packet.RegionData.TimeDilation = timeDilation;
3789 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3790
3791 for (int i = 0; i < blocks.Count; i++)
3792 packet.ObjectData[i] = blocks[i];
3793
3794 OutPacket(packet, ThrottleOutPacketType.Task, true);
3795 }
3796 } 3858 }
3797 3859
3798 #endregion Packet Sending 3860 #endregion Packet Sending
@@ -4058,6 +4120,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4058 { 4120 {
4059 m_propertiesPacketTimer.Stop(); 4121 m_propertiesPacketTimer.Stop();
4060 4122
4123 if (m_propertiesBlocks.Count == 0)
4124 return;
4125
4061 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4126 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
4062 4127
4063 int index = 0; 4128 int index = 0;
@@ -4449,14 +4514,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4449 4514
4450 if (notifyCount > 0) 4515 if (notifyCount > 0)
4451 { 4516 {
4452 if (notifyCount > 32) 4517// if (notifyCount > 32)
4453 { 4518// {
4454 m_log.InfoFormat( 4519// m_log.InfoFormat(
4455 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4520// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4456 + " - a developer might want to investigate whether this is a hard limit", 32); 4521// + " - a developer might want to investigate whether this is a hard limit", 32);
4457 4522//
4458 notifyCount = 32; 4523// notifyCount = 32;
4459 } 4524// }
4460 4525
4461 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4526 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4462 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4527 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4964,6 +5029,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4964 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5029 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
4965 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5030 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
4966 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5031 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5032 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
4967 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5033 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
4968 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5034 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
4969 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5035 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5063,6 +5129,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5063 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5129 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5064 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5130 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5065 (x.ControlFlags != lastarg.ControlFlags) || 5131 (x.ControlFlags != lastarg.ControlFlags) ||
5132 (x.ControlFlags != 0) ||
5066 (x.Far != lastarg.Far) || 5133 (x.Far != lastarg.Far) ||
5067 (x.Flags != lastarg.Flags) || 5134 (x.Flags != lastarg.Flags) ||
5068 (x.State != lastarg.State) || 5135 (x.State != lastarg.State) ||
@@ -5436,7 +5503,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5436 args.Channel = ch; 5503 args.Channel = ch;
5437 args.From = String.Empty; 5504 args.From = String.Empty;
5438 args.Message = Utils.BytesToString(msg); 5505 args.Message = Utils.BytesToString(msg);
5439 args.Type = ChatTypeEnum.Shout; 5506 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5440 args.Position = new Vector3(); 5507 args.Position = new Vector3();
5441 args.Scene = Scene; 5508 args.Scene = Scene;
5442 args.Sender = this; 5509 args.Sender = this;
@@ -9408,7 +9475,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9408 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9475 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9409 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9476 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9410 UpdateMuteListEntry.MuteData.MuteType, 9477 UpdateMuteListEntry.MuteData.MuteType,
9411 UpdateMuteListEntry.AgentData.AgentID); 9478 UpdateMuteListEntry.MuteData.MuteFlags);
9412 return true; 9479 return true;
9413 } 9480 }
9414 return false; 9481 return false;
@@ -9423,8 +9490,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9423 { 9490 {
9424 handlerRemoveMuteListEntry(this, 9491 handlerRemoveMuteListEntry(this,
9425 RemoveMuteListEntry.MuteData.MuteID, 9492 RemoveMuteListEntry.MuteData.MuteID,
9426 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9493 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9427 RemoveMuteListEntry.AgentData.AgentID);
9428 return true; 9494 return true;
9429 } 9495 }
9430 return false; 9496 return false;
@@ -9472,6 +9538,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9472 { 9538 {
9473 return true; 9539 return true;
9474 } 9540 }
9541
9542 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9543 {
9544 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9545
9546 #region Packet Session and User Check
9547 if (m_checkPackets)
9548 {
9549 if (packet.AgentData.SessionID != SessionId ||
9550 packet.AgentData.AgentID != AgentId)
9551 return true;
9552 }
9553 #endregion
9554 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9555 List<InventoryItemBase> items = new List<InventoryItemBase>();
9556 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9557 {
9558 InventoryItemBase b = new InventoryItemBase();
9559 b.ID = n.OldItemID;
9560 b.Folder = n.OldFolderID;
9561 items.Add(b);
9562 }
9563
9564 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9565 if (handlerMoveItemsAndLeaveCopy != null)
9566 {
9567 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9568 }
9569
9570 return true;
9571 }
9475 9572
9476 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9573 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9477 { 9574 {
@@ -10470,11 +10567,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10470 10567
10471 StartLure handlerStartLure = OnStartLure; 10568 StartLure handlerStartLure = OnStartLure;
10472 if (handlerStartLure != null) 10569 if (handlerStartLure != null)
10473 handlerStartLure(startLureRequest.Info.LureType, 10570 {
10474 Utils.BytesToString( 10571 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10475 startLureRequest.Info.Message), 10572 {
10476 startLureRequest.TargetData[0].TargetID, 10573 handlerStartLure(startLureRequest.Info.LureType,
10477 this); 10574 Utils.BytesToString(
10575 startLureRequest.Info.Message),
10576 startLureRequest.TargetData[i].TargetID,
10577 this);
10578 }
10579 }
10478 return true; 10580 return true;
10479 } 10581 }
10480 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10582 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10969,7 +11071,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10969 { 11071 {
10970 // It's a ghost! tell the client to delete it from view. 11072 // It's a ghost! tell the client to delete it from view.
10971 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11073 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
10972 localId); 11074 new List<uint>() { localId });
10973 } 11075 }
10974 else 11076 else
10975 { 11077 {
@@ -11342,22 +11444,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11342 /// <param name="Pack">OpenMetaverse.packet</param> 11444 /// <param name="Pack">OpenMetaverse.packet</param>
11343 public void ProcessInPacket(Packet packet) 11445 public void ProcessInPacket(Packet packet)
11344 { 11446 {
11345 if (m_debugPacketLevel > 0) 11447 if (m_debugPacketLevel >= 255)
11346 { 11448 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11347 bool outputPacket = true;
11348
11349 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11350 outputPacket = false;
11351
11352 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11353 outputPacket = false;
11354
11355 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11356 outputPacket = false;
11357
11358 if (outputPacket)
11359 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11360 }
11361 11449
11362 if (!ProcessPacketMethod(packet)) 11450 if (!ProcessPacketMethod(packet))
11363 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11451 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11599,7 +11687,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11599 11687
11600// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11688// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11601 11689
11690
11691 //Note, the bool returned from the below function is useless since it is always false.
11602 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11692 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11693
11603 } 11694 }
11604 11695
11605 /// <summary> 11696 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index e02783a..5aa9b40 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -149,6 +149,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
149 149
150 private int m_defaultRTO = 3000; 150 private int m_defaultRTO = 3000;
151 private int m_maxRTO = 60000; 151 private int m_maxRTO = 60000;
152 public bool m_deliverPackets = true;
152 153
153 /// <summary> 154 /// <summary>
154 /// Default constructor 155 /// Default constructor
@@ -415,6 +416,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
415 if (category >= 0 && category < m_packetOutboxes.Length) 416 if (category >= 0 && category < m_packetOutboxes.Length)
416 { 417 {
417 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 418 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
419
420 if (m_deliverPackets == false)
421 {
422 queue.Enqueue(packet);
423 return true;
424 }
425
418 TokenBucket bucket = m_throttleCategories[category]; 426 TokenBucket bucket = m_throttleCategories[category];
419 427
420 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 428 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -451,6 +459,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
451 /// <returns>True if any packets were sent, otherwise false</returns> 459 /// <returns>True if any packets were sent, otherwise false</returns>
452 public bool DequeueOutgoing() 460 public bool DequeueOutgoing()
453 { 461 {
462 if (m_deliverPackets == false) return false;
463
454 OutgoingPacket packet; 464 OutgoingPacket packet;
455 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 465 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
456 TokenBucket bucket; 466 TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 149ae9e..7396c2d 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -952,7 +952,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
952 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 952 if (m_scene.TryGetClient(udpClient.AgentID, out client))
953 { 953 {
954 client.IsLoggingOut = true; 954 client.IsLoggingOut = true;
955 client.Close(); 955 client.Close(false);
956 } 956 }
957 } 957 }
958 958
@@ -964,6 +964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
964 964
965 while (base.IsRunning) 965 while (base.IsRunning)
966 { 966 {
967 m_scene.ThreadAlive(1);
967 try 968 try
968 { 969 {
969 IncomingPacket incomingPacket = null; 970 IncomingPacket incomingPacket = null;
@@ -1006,6 +1007,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1006 1007
1007 while (base.IsRunning) 1008 while (base.IsRunning)
1008 { 1009 {
1010 m_scene.ThreadAlive(2);
1009 try 1011 try
1010 { 1012 {
1011 m_packetSent = false; 1013 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index bdbd284..91e3d20 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
133 this.parent = parent; 133 this.parent = parent;
134 MaxBurst = maxBurst; 134 MaxBurst = maxBurst;
135 DripRate = dripRate; 135 DripRate = dripRate;
136 lastDrip = Environment.TickCount & Int32.MaxValue; 136 lastDrip = Environment.TickCount;
137 } 137 }
138 138
139 /// <summary> 139 /// <summary>
@@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
144 /// the bucket, otherwise false</returns> 144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount) 145 public bool RemoveTokens(int amount)
146 { 146 {
147 bool dummy;
148 return RemoveTokens(amount, out dummy);
149 }
150
151 /// <summary>
152 /// Remove a given number of tokens from the bucket
153 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded)
160 {
161 if (maxBurst == 0) 147 if (maxBurst == 0)
162 { 148 {
163 dripSucceeded = true;
164 return true; 149 return true;
165 } 150 }
166 151
167 dripSucceeded = Drip(); 152 if (amount > maxBurst)
168
169 if (content - amount >= 0)
170 { 153 {
171 if (parent != null && !parent.RemoveTokens(amount)) 154 throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst);
172 return false; 155 }
173 156
174 content -= amount; 157 Drip();
175 return true; 158
159 if (content < amount)
160 {
161 return false;
176 } 162 }
177 else 163
164 if (parent != null && !parent.RemoveTokens(amount))
178 { 165 {
179 return false; 166 return false;
180 } 167 }
168
169 content -= amount;
170 return true;
181 } 171 }
182 172
183 /// <summary> 173 /// <summary>
@@ -193,25 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 content = maxBurst; 183 content = maxBurst;
194 return true; 184 return true;
195 } 185 }
196 else
197 {
198 int now = Environment.TickCount & Int32.MaxValue;
199 int deltaMS = now - lastDrip;
200 186
201 if (deltaMS <= 0) 187 int now = Environment.TickCount;
202 { 188 int deltaMS = now - lastDrip;
203 if (deltaMS < 0) 189 lastDrip = now;
204 lastDrip = now;
205 return false;
206 }
207 190
208 int dripAmount = deltaMS * tokensPerMS; 191 if (deltaMS <= 0)
209 192 {
210 content = Math.Min(content + dripAmount, maxBurst); 193 return false;
211 lastDrip = now; 194 }
212 195
213 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
214 } 200 }
201 content = (int)dripAmount;
202 return true;
215 } 203 }
216 } 204 }
217} 205}