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.cs71
5 files changed, 436 insertions, 347 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 2c6795f..3972ec9 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;
@@ -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; } }
@@ -476,18 +486,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
476 486
477 #region Client Methods 487 #region Client Methods
478 488
489
479 /// <summary> 490 /// <summary>
480 /// Shut down the client view 491 /// Shut down the client view
481 /// </summary> 492 /// </summary>
482 public void Close() 493 public void Close()
483 { 494 {
495 Close(true);
496 }
497
498 /// <summary>
499 /// Shut down the client view
500 /// </summary>
501 public void Close(bool sendStop)
502 {
484 m_log.DebugFormat( 503 m_log.DebugFormat(
485 "[CLIENT]: Close has been called for {0} attached to scene {1}", 504 "[CLIENT]: Close has been called for {0} attached to scene {1}",
486 Name, m_scene.RegionInfo.RegionName); 505 Name, m_scene.RegionInfo.RegionName);
487 506
488 // Send the STOP packet 507 if (sendStop)
489 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 508 {
490 OutPacket(disable, ThrottleOutPacketType.Unknown); 509 // Send the STOP packet
510 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
511 OutPacket(disable, ThrottleOutPacketType.Unknown);
512 }
491 513
492 IsActive = false; 514 IsActive = false;
493 515
@@ -768,7 +790,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
768 reply.ChatData.OwnerID = fromAgentID; 790 reply.ChatData.OwnerID = fromAgentID;
769 reply.ChatData.SourceID = fromAgentID; 791 reply.ChatData.SourceID = fromAgentID;
770 792
771 OutPacket(reply, ThrottleOutPacketType.Task); 793 OutPacket(reply, ThrottleOutPacketType.Unknown);
772 } 794 }
773 795
774 /// <summary> 796 /// <summary>
@@ -1054,6 +1076,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1054 public virtual void SendLayerData(float[] map) 1076 public virtual void SendLayerData(float[] map)
1055 { 1077 {
1056 Util.FireAndForget(DoSendLayerData, map); 1078 Util.FireAndForget(DoSendLayerData, map);
1079
1080 // Send it sync, and async. It's not that much data
1081 // and it improves user experience just so much!
1082 DoSendLayerData(map);
1057 } 1083 }
1058 1084
1059 /// <summary> 1085 /// <summary>
@@ -1066,16 +1092,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1066 1092
1067 try 1093 try
1068 { 1094 {
1069 //for (int y = 0; y < 16; y++) 1095 for (int y = 0; y < 16; y++)
1070 //{ 1096 {
1071 // for (int x = 0; x < 16; x++) 1097 for (int x = 0; x < 16; x+=4)
1072 // { 1098 {
1073 // SendLayerData(x, y, map); 1099 SendLayerPacket(x, y, map);
1074 // } 1100 }
1075 //} 1101 }
1076
1077 // Send LayerData in a spiral pattern. Fun!
1078 SendLayerTopRight(map, 0, 0, 15, 15);
1079 } 1102 }
1080 catch (Exception e) 1103 catch (Exception e)
1081 { 1104 {
@@ -1083,51 +1106,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1083 } 1106 }
1084 } 1107 }
1085 1108
1086 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1087 {
1088 // Row
1089 for (int i = x1; i <= x2; i++)
1090 SendLayerData(i, y1, map);
1091
1092 // Column
1093 for (int j = y1 + 1; j <= y2; j++)
1094 SendLayerData(x2, j, map);
1095
1096 if (x2 - x1 > 0)
1097 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1098 }
1099
1100 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1101 {
1102 // Row in reverse
1103 for (int i = x2; i >= x1; i--)
1104 SendLayerData(i, y2, map);
1105
1106 // Column in reverse
1107 for (int j = y2 - 1; j >= y1; j--)
1108 SendLayerData(x1, j, map);
1109
1110 if (x2 - x1 > 0)
1111 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1112 }
1113
1114 /// <summary> 1109 /// <summary>
1115 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1110 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1116 /// </summary> 1111 /// </summary>
1117 /// <param name="map">heightmap</param> 1112 /// <param name="map">heightmap</param>
1118 /// <param name="px">X coordinate for patches 0..12</param> 1113 /// <param name="px">X coordinate for patches 0..12</param>
1119 /// <param name="py">Y coordinate for patches 0..15</param> 1114 /// <param name="py">Y coordinate for patches 0..15</param>
1120 // private void SendLayerPacket(float[] map, int y, int x) 1115 private void SendLayerPacket(int x, int y, float[] map)
1121 // { 1116 {
1122 // int[] patches = new int[4]; 1117 int[] patches = new int[4];
1123 // patches[0] = x + 0 + y * 16; 1118 patches[0] = x + 0 + y * 16;
1124 // patches[1] = x + 1 + y * 16; 1119 patches[1] = x + 1 + y * 16;
1125 // patches[2] = x + 2 + y * 16; 1120 patches[2] = x + 2 + y * 16;
1126 // patches[3] = x + 3 + y * 16; 1121 patches[3] = x + 3 + y * 16;
1127 1122
1128 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1123 float[] heightmap = (map.Length == 65536) ?
1129 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1124 map :
1130 // } 1125 LLHeightFieldMoronize(map);
1126
1127 try
1128 {
1129 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1130 OutPacket(layerpack, ThrottleOutPacketType.Land);
1131 }
1132 catch
1133 {
1134 for (int px = x ; px < x + 4 ; px++)
1135 SendLayerData(px, y, map);
1136 }
1137 }
1131 1138
1132 /// <summary> 1139 /// <summary>
1133 /// Sends a specified patch to a client 1140 /// Sends a specified patch to a client
@@ -1147,7 +1154,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1147 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1154 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1148 layerpack.Header.Reliable = true; 1155 layerpack.Header.Reliable = true;
1149 1156
1150 OutPacket(layerpack, ThrottleOutPacketType.Land); 1157 OutPacket(layerpack, ThrottleOutPacketType.Task);
1151 } 1158 }
1152 catch (Exception e) 1159 catch (Exception e)
1153 { 1160 {
@@ -1508,37 +1515,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1508 OutPacket(pc, ThrottleOutPacketType.Unknown); 1515 OutPacket(pc, ThrottleOutPacketType.Unknown);
1509 } 1516 }
1510 1517
1511 public void SendKillObject(ulong regionHandle, uint localID) 1518 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1512 { 1519 {
1513// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1520// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1514 1521
1515 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1522 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1516 // TODO: don't create new blocks if recycling an old packet 1523 // TODO: don't create new blocks if recycling an old packet
1517 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; 1524 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1518 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); 1525 for (int i = 0 ; i < localIDs.Count ; i++ )
1519 kill.ObjectData[0].ID = localID; 1526 {
1527 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1528 kill.ObjectData[i].ID = localIDs[i];
1529 }
1520 kill.Header.Reliable = true; 1530 kill.Header.Reliable = true;
1521 kill.Header.Zerocoded = true; 1531 kill.Header.Zerocoded = true;
1522 1532
1523 if (m_scene.GetScenePresence(localID) == null) 1533 lock (m_killRecord)
1524 { 1534 {
1525 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1535 if (localIDs.Count == 1)
1526 // condition where a kill can be processed before an out-of-date update for the same object. 1536 {
1527 lock (m_killRecord) 1537 if (m_scene.GetScenePresence(localIDs[0]) != null)
1538 {
1539 OutPacket(kill, ThrottleOutPacketType.State);
1540 return;
1541 }
1542 m_killRecord.Add(localIDs[0]);
1543 }
1544 else
1528 { 1545 {
1529 m_killRecord.Add(localID); 1546 lock (m_entityUpdates.SyncRoot)
1530 1547 {
1531 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1548 foreach (uint localID in localIDs)
1532 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1549 m_killRecord.Add(localID);
1533 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1550 }
1534 // scene objects in a viewer until that viewer is relogged in.
1535 OutPacket(kill, ThrottleOutPacketType.Task);
1536 } 1551 }
1537 } 1552 }
1538 else 1553
1539 { 1554 // The throttle queue used here must match that being used for
1540 OutPacket(kill, ThrottleOutPacketType.State); 1555 // updates. Otherwise, there is a chance that a kill packet put
1541 } 1556 // on a separate queue will be sent to the client before an
1557 // existing update packet on another queue. Receiving updates
1558 // after kills results in unowned and undeletable
1559 // scene objects in a viewer until that viewer is relogged in.
1560 OutPacket(kill, ThrottleOutPacketType.Task);
1542 } 1561 }
1543 1562
1544 /// <summary> 1563 /// <summary>
@@ -2251,6 +2270,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2251 OutPacket(sound, ThrottleOutPacketType.Task); 2270 OutPacket(sound, ThrottleOutPacketType.Task);
2252 } 2271 }
2253 2272
2273 public void SendTransferAbort(TransferRequestPacket transferRequest)
2274 {
2275 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2276 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2277 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2278 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2279 OutPacket(abort, ThrottleOutPacketType.Task);
2280 }
2281
2254 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2282 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2255 { 2283 {
2256 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2284 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3553,6 +3581,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3553 /// </summary> 3581 /// </summary>
3554 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3582 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3555 { 3583 {
3584 if (entity is SceneObjectPart)
3585 {
3586 SceneObjectPart e = (SceneObjectPart)entity;
3587 SceneObjectGroup g = e.ParentGroup;
3588 if (g.RootPart.Shape.State > 30) // HUD
3589 if (g.OwnerID != AgentId)
3590 return; // Don't send updates for other people's HUDs
3591 }
3592
3556 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3593 double priority = m_prioritizer.GetUpdatePriority(this, entity);
3557 3594
3558 lock (m_entityUpdates.SyncRoot) 3595 lock (m_entityUpdates.SyncRoot)
@@ -3569,232 +3606,257 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3569 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3606 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue;
3570 int updatesThisCall = 0; 3607 int updatesThisCall = 0;
3571 3608
3572 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3609 float avgTimeDilation = 0;
3573 // condition where a kill can be processed before an out-of-date update for the same object. 3610
3574 lock (m_killRecord) 3611 EntityUpdate update;
3612 while (updatesThisCall < maxUpdates)
3575 { 3613 {
3576 float avgTimeDilation = 1.0f; 3614 lock (m_entityUpdates.SyncRoot)
3577 EntityUpdate update; 3615 if (!m_entityUpdates.TryDequeue(out update))
3578 while (updatesThisCall < maxUpdates) 3616 break;
3617
3618 avgTimeDilation += update.TimeDilation;
3619 avgTimeDilation *= 0.5f;
3620
3621 if (update.Entity is SceneObjectPart)
3579 { 3622 {
3580 lock (m_entityUpdates.SyncRoot) 3623 SceneObjectPart part = (SceneObjectPart)update.Entity;
3581 if (!m_entityUpdates.TryDequeue(out update))
3582 break;
3583 avgTimeDilation += update.TimeDilation;
3584 avgTimeDilation *= 0.5f;
3585 3624
3586 if (update.Entity is SceneObjectPart) 3625 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3626 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3627 // safety measure.
3628 //
3629 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3630 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3631 // updates and kills on different threads with different scheduling strategies, hence this protection.
3632 //
3633 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3634 // after the root prim has been deleted.
3635 lock (m_killRecord)
3587 { 3636 {
3588 SceneObjectPart part = (SceneObjectPart)update.Entity;
3589
3590 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3591 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3592 // safety measure.
3593 //
3594 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3595 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3596 // updates and kills on different threads with different scheduling strategies, hence this protection.
3597 //
3598 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3599 // after the root prim has been deleted.
3600 if (m_killRecord.Contains(part.LocalId)) 3637 if (m_killRecord.Contains(part.LocalId))
3601 {
3602 // m_log.WarnFormat(
3603 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3604 // part.LocalId, Name);
3605 continue; 3638 continue;
3606 } 3639 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3607 3640 continue;
3608 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3641 }
3642
3643 if (part.ParentGroup.IsDeleted)
3644 continue;
3645
3646 if (part.ParentGroup.IsAttachment)
3647 { // Someone else's HUD, why are we getting these?
3648 if (part.ParentGroup.OwnerID != AgentId &&
3649 part.ParentGroup.RootPart.Shape.State >= 30)
3650 continue;
3651 ScenePresence sp;
3652 // Owner is not in the sim, don't update it to
3653 // anyone
3654 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3655 continue;
3656
3657 List<SceneObjectGroup> atts = sp.Attachments;
3658 bool found = false;
3659 foreach (SceneObjectGroup att in atts)
3609 { 3660 {
3610 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3661 if (att == part.ParentGroup)
3611 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3612 { 3662 {
3613 part.Shape.LightEntry = false; 3663 found = true;
3664 break;
3614 } 3665 }
3615 } 3666 }
3667
3668 // It's an attachment of a valid avatar, but
3669 // doesn't seem to be attached, skip
3670 if (!found)
3671 continue;
3616 } 3672 }
3617 3673
3618 ++updatesThisCall; 3674 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3619
3620 #region UpdateFlags to packet type conversion
3621
3622 PrimUpdateFlags updateFlags = update.Flags;
3623
3624 bool canUseCompressed = true;
3625 bool canUseImproved = true;
3626
3627 // Compressed object updates only make sense for LL primitives
3628 if (!(update.Entity is SceneObjectPart))
3629 {
3630 canUseCompressed = false;
3631 }
3632
3633 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3634 {
3635 canUseCompressed = false;
3636 canUseImproved = false;
3637 }
3638 else
3639 { 3675 {
3640 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || 3676 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3641 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || 3677 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3642 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3643 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3644 { 3678 {
3645 canUseCompressed = false; 3679 part.Shape.LightEntry = false;
3646 }
3647
3648 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3649 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3650 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3651 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3652 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3653 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3654 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3655 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3656 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3657 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3658 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3659 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3660 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3661 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3662 {
3663 canUseImproved = false;
3664 } 3680 }
3665 } 3681 }
3666 3682 }
3667 #endregion UpdateFlags to packet type conversion 3683
3668 3684 ++updatesThisCall;
3669 #region Block Construction 3685
3670 3686 #region UpdateFlags to packet type conversion
3671 // TODO: Remove this once we can build compressed updates 3687
3688 PrimUpdateFlags updateFlags = update.Flags;
3689
3690 bool canUseCompressed = true;
3691 bool canUseImproved = true;
3692
3693 // Compressed object updates only make sense for LL primitives
3694 if (!(update.Entity is SceneObjectPart))
3695 {
3672 canUseCompressed = false; 3696 canUseCompressed = false;
3673 3697 }
3674 if (!canUseImproved && !canUseCompressed) 3698
3699 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3700 {
3701 canUseCompressed = false;
3702 canUseImproved = false;
3703 }
3704 else
3705 {
3706 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3707 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3708 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3709 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3675 { 3710 {
3676 if (update.Entity is ScenePresence) 3711 canUseCompressed = false;
3677 {
3678 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3679 }
3680 else
3681 {
3682 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3683 // {
3684 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3685 // string text = sop.Text;
3686 // if (text.IndexOf("\n") >= 0)
3687 // text = text.Remove(text.IndexOf("\n"));
3688 //
3689 // if (m_attachmentsSent.Contains(sop.ParentID))
3690 // {
3691 //// m_log.DebugFormat(
3692 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3693 //// sop.LocalId, text);
3694 //
3695 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3696 //
3697 // m_attachmentsSent.Add(sop.LocalId);
3698 // }
3699 // else
3700 // {
3701 // m_log.DebugFormat(
3702 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3703 // sop.LocalId, text, sop.ParentID);
3704 //
3705 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3706 // }
3707 // }
3708 // else
3709 // {
3710 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3711 // }
3712 }
3713 } 3712 }
3714 else if (!canUseImproved) 3713
3714 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3715 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3716 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3717 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3718 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3719 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3720 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3721 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3722 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3723 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3724 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3725 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3726 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3727 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3715 { 3728 {
3716 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); 3729 canUseImproved = false;
3730 }
3731 }
3732
3733 #endregion UpdateFlags to packet type conversion
3734
3735 #region Block Construction
3736
3737 // TODO: Remove this once we can build compressed updates
3738 canUseCompressed = false;
3739
3740 if (!canUseImproved && !canUseCompressed)
3741 {
3742 if (update.Entity is ScenePresence)
3743 {
3744 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3717 } 3745 }
3718 else 3746 else
3719 { 3747 {
3720 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3748// if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3721 // Self updates go into a special list 3749// {
3722 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 3750// SceneObjectPart sop = (SceneObjectPart)update.Entity;
3723 else 3751// string text = sop.Text;
3724 // Everything else goes here 3752// if (text.IndexOf("\n") >= 0)
3725 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 3753// text = text.Remove(text.IndexOf("\n"));
3754//
3755// if (m_attachmentsSent.Contains(sop.ParentID))
3756// {
3757//// m_log.DebugFormat(
3758//// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3759//// sop.LocalId, text);
3760//
3761// objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3762//
3763// m_attachmentsSent.Add(sop.LocalId);
3764// }
3765// else
3766// {
3767// m_log.DebugFormat(
3768// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3769// sop.LocalId, text, sop.ParentID);
3770//
3771// m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3772// }
3773// }
3774// else
3775// {
3776 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3777// }
3726 } 3778 }
3727
3728 #endregion Block Construction
3729 } 3779 }
3780 else if (!canUseImproved)
3781 {
3782 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3783 }
3784 else
3785 {
3786 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3787 // Self updates go into a special list
3788 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3789 else
3790 // Everything else goes here
3791 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3792 }
3793
3794 #endregion Block Construction
3795 }
3796
3797 #region Packet Sending
3730 3798
3731 #region Packet Sending 3799 const float TIME_DILATION = 1.0f;
3732 3800 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3733 //const float TIME_DILATION = 1.0f; 3801
3802 if (terseAgentUpdateBlocks.IsValueCreated)
3803 {
3804 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3805
3806 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3807 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3808 packet.RegionData.TimeDilation = timeDilation;
3809 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3734 3810
3811 for (int i = 0; i < blocks.Count; i++)
3812 packet.ObjectData[i] = blocks[i];
3735 3813
3736 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3814 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3815 }
3816
3817 if (objectUpdateBlocks.IsValueCreated)
3818 {
3819 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3737 3820
3738 if (terseAgentUpdateBlocks.IsValueCreated) 3821 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3739 { 3822 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3740 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3823 packet.RegionData.TimeDilation = timeDilation;
3824 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3825
3826 for (int i = 0; i < blocks.Count; i++)
3827 packet.ObjectData[i] = blocks[i];
3741 3828
3742 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3829 OutPacket(packet, ThrottleOutPacketType.Task, true);
3743 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3830 }
3744 packet.RegionData.TimeDilation = timeDilation; 3831
3745 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3832 if (compressedUpdateBlocks.IsValueCreated)
3833 {
3834 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3746 3835
3747 for (int i = 0; i < blocks.Count; i++) 3836 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3748 packet.ObjectData[i] = blocks[i]; 3837 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3838 packet.RegionData.TimeDilation = timeDilation;
3839 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3749 3840
3750 3841 for (int i = 0; i < blocks.Count; i++)
3751 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3842 packet.ObjectData[i] = blocks[i];
3752 }
3753 3843
3754 if (objectUpdateBlocks.IsValueCreated) 3844 OutPacket(packet, ThrottleOutPacketType.Task, true);
3755 { 3845 }
3756 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3846
3757 3847 if (terseUpdateBlocks.IsValueCreated)
3758 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3848 {
3759 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3849 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3760 packet.RegionData.TimeDilation = timeDilation; 3850
3761 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3851 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3762 3852 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3763 for (int i = 0; i < blocks.Count; i++) 3853 packet.RegionData.TimeDilation = timeDilation;
3764 packet.ObjectData[i] = blocks[i]; 3854 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3765 3855
3766 OutPacket(packet, ThrottleOutPacketType.Task, true); 3856 for (int i = 0; i < blocks.Count; i++)
3767 } 3857 packet.ObjectData[i] = blocks[i];
3768 3858
3769 if (compressedUpdateBlocks.IsValueCreated) 3859 OutPacket(packet, ThrottleOutPacketType.Task, true);
3770 {
3771 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3772
3773 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3774 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3775 packet.RegionData.TimeDilation = timeDilation;
3776 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3777
3778 for (int i = 0; i < blocks.Count; i++)
3779 packet.ObjectData[i] = blocks[i];
3780
3781 OutPacket(packet, ThrottleOutPacketType.Task, true);
3782 }
3783
3784 if (terseUpdateBlocks.IsValueCreated)
3785 {
3786 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3787
3788 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3789 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3790 packet.RegionData.TimeDilation = timeDilation;
3791 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3792
3793 for (int i = 0; i < blocks.Count; i++)
3794 packet.ObjectData[i] = blocks[i];
3795
3796 OutPacket(packet, ThrottleOutPacketType.Task, true);
3797 }
3798 } 3860 }
3799 3861
3800 #endregion Packet Sending 3862 #endregion Packet Sending
@@ -4060,6 +4122,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4060 { 4122 {
4061 m_propertiesPacketTimer.Stop(); 4123 m_propertiesPacketTimer.Stop();
4062 4124
4125 if (m_propertiesBlocks.Count == 0)
4126 return;
4127
4063 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4128 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
4064 4129
4065 int index = 0; 4130 int index = 0;
@@ -4452,14 +4517,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4452 4517
4453 if (notifyCount > 0) 4518 if (notifyCount > 0)
4454 { 4519 {
4455 if (notifyCount > 32) 4520// if (notifyCount > 32)
4456 { 4521// {
4457 m_log.InfoFormat( 4522// m_log.InfoFormat(
4458 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4523// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4459 + " - a developer might want to investigate whether this is a hard limit", 32); 4524// + " - a developer might want to investigate whether this is a hard limit", 32);
4460 4525//
4461 notifyCount = 32; 4526// notifyCount = 32;
4462 } 4527// }
4463 4528
4464 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4529 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4465 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4530 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4967,6 +5032,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4967 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5032 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
4968 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5033 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
4969 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5034 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5035 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
4970 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5036 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
4971 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5037 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
4972 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5038 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5066,6 +5132,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5066 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5132 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5067 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5133 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5068 (x.ControlFlags != lastarg.ControlFlags) || 5134 (x.ControlFlags != lastarg.ControlFlags) ||
5135 (x.ControlFlags != 0) ||
5069 (x.Far != lastarg.Far) || 5136 (x.Far != lastarg.Far) ||
5070 (x.Flags != lastarg.Flags) || 5137 (x.Flags != lastarg.Flags) ||
5071 (x.State != lastarg.State) || 5138 (x.State != lastarg.State) ||
@@ -5439,7 +5506,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5439 args.Channel = ch; 5506 args.Channel = ch;
5440 args.From = String.Empty; 5507 args.From = String.Empty;
5441 args.Message = Utils.BytesToString(msg); 5508 args.Message = Utils.BytesToString(msg);
5442 args.Type = ChatTypeEnum.Shout; 5509 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5443 args.Position = new Vector3(); 5510 args.Position = new Vector3();
5444 args.Scene = Scene; 5511 args.Scene = Scene;
5445 args.Sender = this; 5512 args.Sender = this;
@@ -9411,7 +9478,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9411 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9478 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9412 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9479 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9413 UpdateMuteListEntry.MuteData.MuteType, 9480 UpdateMuteListEntry.MuteData.MuteType,
9414 UpdateMuteListEntry.AgentData.AgentID); 9481 UpdateMuteListEntry.MuteData.MuteFlags);
9415 return true; 9482 return true;
9416 } 9483 }
9417 return false; 9484 return false;
@@ -9426,8 +9493,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9426 { 9493 {
9427 handlerRemoveMuteListEntry(this, 9494 handlerRemoveMuteListEntry(this,
9428 RemoveMuteListEntry.MuteData.MuteID, 9495 RemoveMuteListEntry.MuteData.MuteID,
9429 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9496 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9430 RemoveMuteListEntry.AgentData.AgentID);
9431 return true; 9497 return true;
9432 } 9498 }
9433 return false; 9499 return false;
@@ -9475,6 +9541,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9475 { 9541 {
9476 return true; 9542 return true;
9477 } 9543 }
9544
9545 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9546 {
9547 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9548
9549 #region Packet Session and User Check
9550 if (m_checkPackets)
9551 {
9552 if (packet.AgentData.SessionID != SessionId ||
9553 packet.AgentData.AgentID != AgentId)
9554 return true;
9555 }
9556 #endregion
9557 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9558 List<InventoryItemBase> items = new List<InventoryItemBase>();
9559 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9560 {
9561 InventoryItemBase b = new InventoryItemBase();
9562 b.ID = n.OldItemID;
9563 b.Folder = n.OldFolderID;
9564 items.Add(b);
9565 }
9566
9567 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9568 if (handlerMoveItemsAndLeaveCopy != null)
9569 {
9570 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9571 }
9572
9573 return true;
9574 }
9478 9575
9479 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9576 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9480 { 9577 {
@@ -10473,11 +10570,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10473 10570
10474 StartLure handlerStartLure = OnStartLure; 10571 StartLure handlerStartLure = OnStartLure;
10475 if (handlerStartLure != null) 10572 if (handlerStartLure != null)
10476 handlerStartLure(startLureRequest.Info.LureType, 10573 {
10477 Utils.BytesToString( 10574 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10478 startLureRequest.Info.Message), 10575 {
10479 startLureRequest.TargetData[0].TargetID, 10576 handlerStartLure(startLureRequest.Info.LureType,
10480 this); 10577 Utils.BytesToString(
10578 startLureRequest.Info.Message),
10579 startLureRequest.TargetData[i].TargetID,
10580 this);
10581 }
10582 }
10481 return true; 10583 return true;
10482 } 10584 }
10483 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10585 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10972,7 +11074,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10972 { 11074 {
10973 // It's a ghost! tell the client to delete it from view. 11075 // It's a ghost! tell the client to delete it from view.
10974 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11076 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
10975 localId); 11077 new List<uint>() { localId });
10976 } 11078 }
10977 else 11079 else
10978 { 11080 {
@@ -11345,22 +11447,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11345 /// <param name="Pack">OpenMetaverse.packet</param> 11447 /// <param name="Pack">OpenMetaverse.packet</param>
11346 public void ProcessInPacket(Packet packet) 11448 public void ProcessInPacket(Packet packet)
11347 { 11449 {
11348 if (m_debugPacketLevel > 0) 11450 if (m_debugPacketLevel >= 255)
11349 { 11451 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11350 bool outputPacket = true;
11351
11352 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11353 outputPacket = false;
11354
11355 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11356 outputPacket = false;
11357
11358 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11359 outputPacket = false;
11360
11361 if (outputPacket)
11362 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11363 }
11364 11452
11365 if (!ProcessPacketMethod(packet)) 11453 if (!ProcessPacketMethod(packet))
11366 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11454 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11602,7 +11690,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11602 11690
11603// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11691// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11604 11692
11693
11694 //Note, the bool returned from the below function is useless since it is always false.
11605 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11695 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11696
11606 } 11697 }
11607 11698
11608 /// <summary> 11699 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 65a8fe3..d6159cd 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -151,6 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
151 151
152 private int m_defaultRTO = 3000; 152 private int m_defaultRTO = 3000;
153 private int m_maxRTO = 60000; 153 private int m_maxRTO = 60000;
154 public bool m_deliverPackets = true;
154 155
155 /// <summary> 156 /// <summary>
156 /// Default constructor 157 /// Default constructor
@@ -418,6 +419,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
418 if (category >= 0 && category < m_packetOutboxes.Length) 419 if (category >= 0 && category < m_packetOutboxes.Length)
419 { 420 {
420 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 421 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
422
423 if (m_deliverPackets == false)
424 {
425 queue.Enqueue(packet);
426 return true;
427 }
428
421 TokenBucket bucket = m_throttleCategories[category]; 429 TokenBucket bucket = m_throttleCategories[category];
422 430
423 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 431 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -457,6 +465,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
457 /// <returns>True if any packets were sent, otherwise false</returns> 465 /// <returns>True if any packets were sent, otherwise false</returns>
458 public bool DequeueOutgoing() 466 public bool DequeueOutgoing()
459 { 467 {
468 if (m_deliverPackets == false) return false;
469
460 OutgoingPacket packet; 470 OutgoingPacket packet;
461 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 471 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
462 TokenBucket bucket; 472 TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 583214c..c865c0f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -960,7 +960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
960 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 960 if (m_scene.TryGetClient(udpClient.AgentID, out client))
961 { 961 {
962 client.IsLoggingOut = true; 962 client.IsLoggingOut = true;
963 client.Close(); 963 client.Close(false);
964 } 964 }
965 } 965 }
966 966
@@ -972,6 +972,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
972 972
973 while (base.IsRunning) 973 while (base.IsRunning)
974 { 974 {
975 m_scene.ThreadAlive(1);
975 try 976 try
976 { 977 {
977 IncomingPacket incomingPacket = null; 978 IncomingPacket incomingPacket = null;
@@ -1014,6 +1015,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1014 1015
1015 while (base.IsRunning) 1016 while (base.IsRunning)
1016 { 1017 {
1018 m_scene.ThreadAlive(2);
1017 try 1019 try
1018 { 1020 {
1019 m_packetSent = false; 1021 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 0a8331f..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,30 +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
201 if (deltaMS <= 0)
202 {
203 if (deltaMS < 0)
204 lastDrip = now;
205 return false;
206 }
207 186
208 int dripAmount = deltaMS * tokensPerMS; 187 int now = Environment.TickCount;
188 int deltaMS = now - lastDrip;
189 lastDrip = now;
209 190
210 content = Math.Min(content + dripAmount, maxBurst); 191 if (deltaMS <= 0)
211 lastDrip = now; 192 {
212 193 return false;
213 if (dripAmount < 0 || content < 0) 194 }
214 // sim has been idle for too long, integer has overflown
215 // previous calculation is meaningless, let's put it at correct max
216 content = maxBurst;
217 195
218 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
219 } 200 }
201 content = (int)dripAmount;
202 return true;
220 } 203 }
221 } 204 }
222} 205}