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 5dab1bc..72348b9 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;
@@ -4451,14 +4516,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4451 4516
4452 if (notifyCount > 0) 4517 if (notifyCount > 0)
4453 { 4518 {
4454 if (notifyCount > 32) 4519// if (notifyCount > 32)
4455 { 4520// {
4456 m_log.InfoFormat( 4521// m_log.InfoFormat(
4457 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4522// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4458 + " - a developer might want to investigate whether this is a hard limit", 32); 4523// + " - a developer might want to investigate whether this is a hard limit", 32);
4459 4524//
4460 notifyCount = 32; 4525// notifyCount = 32;
4461 } 4526// }
4462 4527
4463 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4528 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4464 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4529 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4966,6 +5031,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4966 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5031 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
4967 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5032 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
4968 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5033 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5034 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
4969 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5035 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
4970 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5036 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
4971 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5037 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5065,6 +5131,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5065 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5131 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5066 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5132 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5067 (x.ControlFlags != lastarg.ControlFlags) || 5133 (x.ControlFlags != lastarg.ControlFlags) ||
5134 (x.ControlFlags != 0) ||
5068 (x.Far != lastarg.Far) || 5135 (x.Far != lastarg.Far) ||
5069 (x.Flags != lastarg.Flags) || 5136 (x.Flags != lastarg.Flags) ||
5070 (x.State != lastarg.State) || 5137 (x.State != lastarg.State) ||
@@ -5438,7 +5505,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5438 args.Channel = ch; 5505 args.Channel = ch;
5439 args.From = String.Empty; 5506 args.From = String.Empty;
5440 args.Message = Utils.BytesToString(msg); 5507 args.Message = Utils.BytesToString(msg);
5441 args.Type = ChatTypeEnum.Shout; 5508 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5442 args.Position = new Vector3(); 5509 args.Position = new Vector3();
5443 args.Scene = Scene; 5510 args.Scene = Scene;
5444 args.Sender = this; 5511 args.Sender = this;
@@ -9410,7 +9477,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9410 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9477 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9411 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9478 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9412 UpdateMuteListEntry.MuteData.MuteType, 9479 UpdateMuteListEntry.MuteData.MuteType,
9413 UpdateMuteListEntry.AgentData.AgentID); 9480 UpdateMuteListEntry.MuteData.MuteFlags);
9414 return true; 9481 return true;
9415 } 9482 }
9416 return false; 9483 return false;
@@ -9425,8 +9492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9425 { 9492 {
9426 handlerRemoveMuteListEntry(this, 9493 handlerRemoveMuteListEntry(this,
9427 RemoveMuteListEntry.MuteData.MuteID, 9494 RemoveMuteListEntry.MuteData.MuteID,
9428 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9495 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9429 RemoveMuteListEntry.AgentData.AgentID);
9430 return true; 9496 return true;
9431 } 9497 }
9432 return false; 9498 return false;
@@ -9474,6 +9540,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9474 { 9540 {
9475 return true; 9541 return true;
9476 } 9542 }
9543
9544 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9545 {
9546 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9547
9548 #region Packet Session and User Check
9549 if (m_checkPackets)
9550 {
9551 if (packet.AgentData.SessionID != SessionId ||
9552 packet.AgentData.AgentID != AgentId)
9553 return true;
9554 }
9555 #endregion
9556 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9557 List<InventoryItemBase> items = new List<InventoryItemBase>();
9558 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9559 {
9560 InventoryItemBase b = new InventoryItemBase();
9561 b.ID = n.OldItemID;
9562 b.Folder = n.OldFolderID;
9563 items.Add(b);
9564 }
9565
9566 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9567 if (handlerMoveItemsAndLeaveCopy != null)
9568 {
9569 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9570 }
9571
9572 return true;
9573 }
9477 9574
9478 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9575 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9479 { 9576 {
@@ -10472,11 +10569,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10472 10569
10473 StartLure handlerStartLure = OnStartLure; 10570 StartLure handlerStartLure = OnStartLure;
10474 if (handlerStartLure != null) 10571 if (handlerStartLure != null)
10475 handlerStartLure(startLureRequest.Info.LureType, 10572 {
10476 Utils.BytesToString( 10573 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10477 startLureRequest.Info.Message), 10574 {
10478 startLureRequest.TargetData[0].TargetID, 10575 handlerStartLure(startLureRequest.Info.LureType,
10479 this); 10576 Utils.BytesToString(
10577 startLureRequest.Info.Message),
10578 startLureRequest.TargetData[i].TargetID,
10579 this);
10580 }
10581 }
10480 return true; 10582 return true;
10481 } 10583 }
10482 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10584 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10971,7 +11073,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10971 { 11073 {
10972 // It's a ghost! tell the client to delete it from view. 11074 // It's a ghost! tell the client to delete it from view.
10973 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11075 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
10974 localId); 11076 new List<uint>() { localId });
10975 } 11077 }
10976 else 11078 else
10977 { 11079 {
@@ -11344,22 +11446,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11344 /// <param name="Pack">OpenMetaverse.packet</param> 11446 /// <param name="Pack">OpenMetaverse.packet</param>
11345 public void ProcessInPacket(Packet packet) 11447 public void ProcessInPacket(Packet packet)
11346 { 11448 {
11347 if (m_debugPacketLevel > 0) 11449 if (m_debugPacketLevel >= 255)
11348 { 11450 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11349 bool outputPacket = true;
11350
11351 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11352 outputPacket = false;
11353
11354 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11355 outputPacket = false;
11356
11357 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11358 outputPacket = false;
11359
11360 if (outputPacket)
11361 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11362 }
11363 11451
11364 if (!ProcessPacketMethod(packet)) 11452 if (!ProcessPacketMethod(packet))
11365 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11453 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11601,7 +11689,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11601 11689
11602// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11690// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11603 11691
11692
11693 //Note, the bool returned from the below function is useless since it is always false.
11604 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11694 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11695
11605 } 11696 }
11606 11697
11607 /// <summary> 11698 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index d4c3307..f1fdbc5 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 df8ddbb..703176c 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}