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