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.cs709
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs10
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs4
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs71
5 files changed, 450 insertions, 347 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
index e9e2dca..9dd6663 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs
@@ -202,6 +202,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
202 m_stopPacket = TexturePacketCount(); 202 m_stopPacket = TexturePacketCount();
203 } 203 }
204 204
205 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
206 if (m_stopPacket == 1 && Layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
207
205 m_currentPacket = StartPacket; 208 m_currentPacket = StartPacket;
206 } 209 }
207 } 210 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 2faffae..311b1e4 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.
1527 lock (m_killRecord)
1528 { 1536 {
1529 m_killRecord.Add(localID); 1537 if (m_scene.GetScenePresence(localIDs[0]) != null)
1530 1538 {
1531 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1539 OutPacket(kill, ThrottleOutPacketType.State);
1532 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1540 return;
1533 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1541 }
1534 // scene objects in a viewer until that viewer is relogged in. 1542 m_killRecord.Add(localIDs[0]);
1535 OutPacket(kill, ThrottleOutPacketType.Task); 1543 }
1544 else
1545 {
1546 lock (m_entityUpdates.SyncRoot)
1547 {
1548 foreach (uint localID in localIDs)
1549 m_killRecord.Add(localID);
1550 }
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];
3810
3811 for (int i = 0; i < blocks.Count; i++)
3812 packet.ObjectData[i] = blocks[i];
3734 3813
3814 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3815 }
3735 3816
3736 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 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;
3745 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3746 3831
3747 for (int i = 0; i < blocks.Count; i++) 3832 if (compressedUpdateBlocks.IsValueCreated)
3748 packet.ObjectData[i] = blocks[i]; 3833 {
3834 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3835
3836 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
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;
@@ -4461,14 +4526,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4461 4526
4462 if (notifyCount > 0) 4527 if (notifyCount > 0)
4463 { 4528 {
4464 if (notifyCount > 32) 4529// if (notifyCount > 32)
4465 { 4530// {
4466 m_log.InfoFormat( 4531// m_log.InfoFormat(
4467 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4532// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4468 + " - a developer might want to investigate whether this is a hard limit", 32); 4533// + " - a developer might want to investigate whether this is a hard limit", 32);
4469 4534//
4470 notifyCount = 32; 4535// notifyCount = 32;
4471 } 4536// }
4472 4537
4473 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4538 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4474 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4539 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4976,6 +5041,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4976 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5041 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
4977 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5042 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
4978 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5043 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5044 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
4979 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5045 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
4980 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5046 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
4981 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5047 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5075,6 +5141,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5075 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5141 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5076 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5142 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5077 (x.ControlFlags != lastarg.ControlFlags) || 5143 (x.ControlFlags != lastarg.ControlFlags) ||
5144 (x.ControlFlags != 0) ||
5078 (x.Far != lastarg.Far) || 5145 (x.Far != lastarg.Far) ||
5079 (x.Flags != lastarg.Flags) || 5146 (x.Flags != lastarg.Flags) ||
5080 (x.State != lastarg.State) || 5147 (x.State != lastarg.State) ||
@@ -5448,7 +5515,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5448 args.Channel = ch; 5515 args.Channel = ch;
5449 args.From = String.Empty; 5516 args.From = String.Empty;
5450 args.Message = Utils.BytesToString(msg); 5517 args.Message = Utils.BytesToString(msg);
5451 args.Type = ChatTypeEnum.Shout; 5518 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5452 args.Position = new Vector3(); 5519 args.Position = new Vector3();
5453 args.Scene = Scene; 5520 args.Scene = Scene;
5454 args.Sender = this; 5521 args.Sender = this;
@@ -9420,7 +9487,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9420 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9487 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9421 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9488 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9422 UpdateMuteListEntry.MuteData.MuteType, 9489 UpdateMuteListEntry.MuteData.MuteType,
9423 UpdateMuteListEntry.AgentData.AgentID); 9490 UpdateMuteListEntry.MuteData.MuteFlags);
9424 return true; 9491 return true;
9425 } 9492 }
9426 return false; 9493 return false;
@@ -9435,8 +9502,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9435 { 9502 {
9436 handlerRemoveMuteListEntry(this, 9503 handlerRemoveMuteListEntry(this,
9437 RemoveMuteListEntry.MuteData.MuteID, 9504 RemoveMuteListEntry.MuteData.MuteID,
9438 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9505 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9439 RemoveMuteListEntry.AgentData.AgentID);
9440 return true; 9506 return true;
9441 } 9507 }
9442 return false; 9508 return false;
@@ -9484,6 +9550,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9484 { 9550 {
9485 return true; 9551 return true;
9486 } 9552 }
9553
9554 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9555 {
9556 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9557
9558 #region Packet Session and User Check
9559 if (m_checkPackets)
9560 {
9561 if (packet.AgentData.SessionID != SessionId ||
9562 packet.AgentData.AgentID != AgentId)
9563 return true;
9564 }
9565 #endregion
9566 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9567 List<InventoryItemBase> items = new List<InventoryItemBase>();
9568 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9569 {
9570 InventoryItemBase b = new InventoryItemBase();
9571 b.ID = n.OldItemID;
9572 b.Folder = n.OldFolderID;
9573 items.Add(b);
9574 }
9575
9576 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9577 if (handlerMoveItemsAndLeaveCopy != null)
9578 {
9579 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9580 }
9581
9582 return true;
9583 }
9487 9584
9488 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9585 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9489 { 9586 {
@@ -9910,6 +10007,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9910 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10007 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
9911 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10008 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
9912 10009
10010 Scene scene = (Scene)m_scene;
10011 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10012 {
10013 ScenePresence p;
10014 if (scene.TryGetScenePresence(sender.AgentId, out p))
10015 {
10016 if (p.GodLevel >= 200)
10017 {
10018 groupProfileReply.GroupData.OpenEnrollment = true;
10019 groupProfileReply.GroupData.MembershipFee = 0;
10020 }
10021 }
10022 }
10023
9913 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10024 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
9914 } 10025 }
9915 return true; 10026 return true;
@@ -10482,11 +10593,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10482 10593
10483 StartLure handlerStartLure = OnStartLure; 10594 StartLure handlerStartLure = OnStartLure;
10484 if (handlerStartLure != null) 10595 if (handlerStartLure != null)
10485 handlerStartLure(startLureRequest.Info.LureType, 10596 {
10486 Utils.BytesToString( 10597 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10487 startLureRequest.Info.Message), 10598 {
10488 startLureRequest.TargetData[0].TargetID, 10599 handlerStartLure(startLureRequest.Info.LureType,
10489 this); 10600 Utils.BytesToString(
10601 startLureRequest.Info.Message),
10602 startLureRequest.TargetData[i].TargetID,
10603 this);
10604 }
10605 }
10490 return true; 10606 return true;
10491 } 10607 }
10492 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10608 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10981,7 +11097,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10981 { 11097 {
10982 // It's a ghost! tell the client to delete it from view. 11098 // It's a ghost! tell the client to delete it from view.
10983 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11099 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
10984 localId); 11100 new List<uint>() { localId });
10985 } 11101 }
10986 else 11102 else
10987 { 11103 {
@@ -11354,22 +11470,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11354 /// <param name="Pack">OpenMetaverse.packet</param> 11470 /// <param name="Pack">OpenMetaverse.packet</param>
11355 public void ProcessInPacket(Packet packet) 11471 public void ProcessInPacket(Packet packet)
11356 { 11472 {
11357 if (m_debugPacketLevel > 0) 11473 if (m_debugPacketLevel >= 255)
11358 { 11474 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11359 bool outputPacket = true;
11360
11361 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11362 outputPacket = false;
11363
11364 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11365 outputPacket = false;
11366
11367 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11368 outputPacket = false;
11369
11370 if (outputPacket)
11371 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11372 }
11373 11475
11374 if (!ProcessPacketMethod(packet)) 11476 if (!ProcessPacketMethod(packet))
11375 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11477 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11611,7 +11713,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11611 11713
11612// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11714// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11613 11715
11716
11717 //Note, the bool returned from the below function is useless since it is always false.
11614 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11718 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11719
11615 } 11720 }
11616 11721
11617 /// <summary> 11722 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 65a8fe3..d6159cd 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -151,6 +151,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
151 151
152 private int m_defaultRTO = 3000; 152 private int m_defaultRTO = 3000;
153 private int m_maxRTO = 60000; 153 private int m_maxRTO = 60000;
154 public bool m_deliverPackets = true;
154 155
155 /// <summary> 156 /// <summary>
156 /// Default constructor 157 /// Default constructor
@@ -418,6 +419,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
418 if (category >= 0 && category < m_packetOutboxes.Length) 419 if (category >= 0 && category < m_packetOutboxes.Length)
419 { 420 {
420 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 421 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
422
423 if (m_deliverPackets == false)
424 {
425 queue.Enqueue(packet);
426 return true;
427 }
428
421 TokenBucket bucket = m_throttleCategories[category]; 429 TokenBucket bucket = m_throttleCategories[category];
422 430
423 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength)) 431 if (!forceQueue && bucket.RemoveTokens(packet.Buffer.DataLength))
@@ -457,6 +465,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
457 /// <returns>True if any packets were sent, otherwise false</returns> 465 /// <returns>True if any packets were sent, otherwise false</returns>
458 public bool DequeueOutgoing() 466 public bool DequeueOutgoing()
459 { 467 {
468 if (m_deliverPackets == false) return false;
469
460 OutgoingPacket packet; 470 OutgoingPacket packet;
461 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 471 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
462 TokenBucket bucket; 472 TokenBucket bucket;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 583214c..c865c0f 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -960,7 +960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
960 if (m_scene.TryGetClient(udpClient.AgentID, out client)) 960 if (m_scene.TryGetClient(udpClient.AgentID, out client))
961 { 961 {
962 client.IsLoggingOut = true; 962 client.IsLoggingOut = true;
963 client.Close(); 963 client.Close(false);
964 } 964 }
965 } 965 }
966 966
@@ -972,6 +972,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
972 972
973 while (base.IsRunning) 973 while (base.IsRunning)
974 { 974 {
975 m_scene.ThreadAlive(1);
975 try 976 try
976 { 977 {
977 IncomingPacket incomingPacket = null; 978 IncomingPacket incomingPacket = null;
@@ -1014,6 +1015,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1014 1015
1015 while (base.IsRunning) 1016 while (base.IsRunning)
1016 { 1017 {
1018 m_scene.ThreadAlive(2);
1017 try 1019 try
1018 { 1020 {
1019 m_packetSent = false; 1021 m_packetSent = false;
diff --git a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
index 0a8331f..91e3d20 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/TokenBucket.cs
@@ -133,7 +133,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
133 this.parent = parent; 133 this.parent = parent;
134 MaxBurst = maxBurst; 134 MaxBurst = maxBurst;
135 DripRate = dripRate; 135 DripRate = dripRate;
136 lastDrip = Environment.TickCount & Int32.MaxValue; 136 lastDrip = Environment.TickCount;
137 } 137 }
138 138
139 /// <summary> 139 /// <summary>
@@ -144,40 +144,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
144 /// the bucket, otherwise false</returns> 144 /// the bucket, otherwise false</returns>
145 public bool RemoveTokens(int amount) 145 public bool RemoveTokens(int amount)
146 { 146 {
147 bool dummy;
148 return RemoveTokens(amount, out dummy);
149 }
150
151 /// <summary>
152 /// Remove a given number of tokens from the bucket
153 /// </summary>
154 /// <param name="amount">Number of tokens to remove from the bucket</param>
155 /// <param name="dripSucceeded">True if tokens were added to the bucket
156 /// during this call, otherwise false</param>
157 /// <returns>True if the requested number of tokens were removed from
158 /// the bucket, otherwise false</returns>
159 public bool RemoveTokens(int amount, out bool dripSucceeded)
160 {
161 if (maxBurst == 0) 147 if (maxBurst == 0)
162 { 148 {
163 dripSucceeded = true;
164 return true; 149 return true;
165 } 150 }
166 151
167 dripSucceeded = Drip(); 152 if (amount > maxBurst)
168
169 if (content - amount >= 0)
170 { 153 {
171 if (parent != null && !parent.RemoveTokens(amount)) 154 throw new Exception("amount " + amount + " exceeds maxBurst " + maxBurst);
172 return false; 155 }
173 156
174 content -= amount; 157 Drip();
175 return true; 158
159 if (content < amount)
160 {
161 return false;
176 } 162 }
177 else 163
164 if (parent != null && !parent.RemoveTokens(amount))
178 { 165 {
179 return false; 166 return false;
180 } 167 }
168
169 content -= amount;
170 return true;
181 } 171 }
182 172
183 /// <summary> 173 /// <summary>
@@ -193,30 +183,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
193 content = maxBurst; 183 content = maxBurst;
194 return true; 184 return true;
195 } 185 }
196 else
197 {
198 int now = Environment.TickCount & Int32.MaxValue;
199 int deltaMS = now - lastDrip;
200
201 if (deltaMS <= 0)
202 {
203 if (deltaMS < 0)
204 lastDrip = now;
205 return false;
206 }
207 186
208 int dripAmount = deltaMS * tokensPerMS; 187 int now = Environment.TickCount;
188 int deltaMS = now - lastDrip;
189 lastDrip = now;
209 190
210 content = Math.Min(content + dripAmount, maxBurst); 191 if (deltaMS <= 0)
211 lastDrip = now; 192 {
212 193 return false;
213 if (dripAmount < 0 || content < 0) 194 }
214 // sim has been idle for too long, integer has overflown
215 // previous calculation is meaningless, let's put it at correct max
216 content = maxBurst;
217 195
218 return true; 196 long dripAmount = (long)deltaMS * (long)tokensPerMS + (long)content;
197 if (dripAmount > maxBurst)
198 {
199 dripAmount = maxBurst;
219 } 200 }
201 content = (int)dripAmount;
202 return true;
220 } 203 }
221 } 204 }
222} 205}