aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs642
1 files changed, 369 insertions, 273 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 3b7328d..196ac50 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;
@@ -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 if (localIDs.Count == 1)
1523 { 1533 {
1524 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1534 if (m_scene.GetScenePresence(localIDs[0]) != null)
1525 // condition where a kill can be processed before an out-of-date update for the same object. 1535 {
1536 OutPacket(kill, ThrottleOutPacketType.State);
1537 return;
1538 }
1526 lock (m_killRecord) 1539 lock (m_killRecord)
1527 { 1540 {
1528 m_killRecord.Add(localID); 1541 m_killRecord.Add(localIDs[0]);
1529
1530 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1531 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1532 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1533 // scene objects in a viewer until that viewer is relogged in.
1534 OutPacket(kill, ThrottleOutPacketType.Task);
1535 } 1542 }
1536 } 1543 }
1537 else 1544 else
1538 { 1545 {
1539 OutPacket(kill, ThrottleOutPacketType.State); 1546 lock (m_killRecord)
1547 {
1548 foreach (uint localID in localIDs)
1549 m_killRecord.Add(localID);
1550 }
1540 } 1551 }
1552
1553 // The throttle queue used here must match that being used for
1554 // updates. Otherwise, there is a chance that a kill packet put
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>
@@ -2243,6 +2262,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2243 OutPacket(sound, ThrottleOutPacketType.Task); 2262 OutPacket(sound, ThrottleOutPacketType.Task);
2244 } 2263 }
2245 2264
2265 public void SendTransferAbort(TransferRequestPacket transferRequest)
2266 {
2267 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2268 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2269 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2270 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2271 OutPacket(abort, ThrottleOutPacketType.Task);
2272 }
2273
2246 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2274 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2247 { 2275 {
2248 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2276 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3544,6 +3572,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3544 /// </summary> 3572 /// </summary>
3545 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3573 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3546 { 3574 {
3575 if (entity is SceneObjectPart)
3576 {
3577 SceneObjectPart e = (SceneObjectPart)entity;
3578 SceneObjectGroup g = e.ParentGroup;
3579 if (g.RootPart.Shape.State > 30) // HUD
3580 if (g.OwnerID != AgentId)
3581 return; // Don't send updates for other people's HUDs
3582 }
3583
3547 double priority = m_prioritizer.GetUpdatePriority(this, entity); 3584 double priority = m_prioritizer.GetUpdatePriority(this, entity);
3548 3585
3549 lock (m_entityUpdates.SyncRoot) 3586 lock (m_entityUpdates.SyncRoot)
@@ -3560,21 +3597,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3560 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; 3597 if (maxUpdates <= 0) maxUpdates = Int32.MaxValue;
3561 int updatesThisCall = 0; 3598 int updatesThisCall = 0;
3562 3599
3563 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3600 EntityUpdate update;
3564 // condition where a kill can be processed before an out-of-date update for the same object.
3565 lock (m_killRecord) 3601 lock (m_killRecord)
3566 { 3602 {
3567 EntityUpdate update;
3568 while (updatesThisCall < maxUpdates) 3603 while (updatesThisCall < maxUpdates)
3569 { 3604 {
3570 lock (m_entityUpdates.SyncRoot) 3605 lock (m_entityUpdates.SyncRoot)
3571 if (!m_entityUpdates.TryDequeue(out update)) 3606 if (!m_entityUpdates.TryDequeue(out update))
3572 break; 3607 break;
3573 3608
3574 if (update.Entity is SceneObjectPart) 3609 if (update.Entity is SceneObjectPart)
3575 { 3610 {
3576 SceneObjectPart part = (SceneObjectPart)update.Entity; 3611 SceneObjectPart part = (SceneObjectPart)update.Entity;
3577 3612
3578 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3613 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3579 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3614 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3580 // safety measure. 3615 // safety measure.
@@ -3586,199 +3621,230 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3586 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3621 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3587 // after the root prim has been deleted. 3622 // after the root prim has been deleted.
3588 if (m_killRecord.Contains(part.LocalId)) 3623 if (m_killRecord.Contains(part.LocalId))
3589 {
3590 // m_log.WarnFormat(
3591 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3592 // part.LocalId, Name);
3593 continue; 3624 continue;
3594 } 3625 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3595 3626 continue;
3627
3628 if (part.ParentGroup.IsDeleted)
3629 continue;
3630
3631 if (part.ParentGroup.IsAttachment)
3632 { // Someone else's HUD, why are we getting these?
3633 if (part.ParentGroup.OwnerID != AgentId &&
3634 part.ParentGroup.RootPart.Shape.State >= 30)
3635 continue;
3636 ScenePresence sp;
3637 // Owner is not in the sim, don't update it to
3638 // anyone
3639 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3640 continue;
3641
3642 List<SceneObjectGroup> atts = sp.Attachments;
3643 bool found = false;
3644 foreach (SceneObjectGroup att in atts)
3645 {
3646 if (att == part.ParentGroup)
3647 {
3648 found = true;
3649 break;
3650 }
3651 }
3652
3653 // It's an attachment of a valid avatar, but
3654 // doesn't seem to be attached, skip
3655 if (!found)
3656 continue;
3657 }
3658
3596 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3659 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3597 { 3660 {
3598 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3661 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3599 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3600 { 3662 {
3601 part.Shape.LightEntry = false; 3663 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3664 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3665 {
3666 part.Shape.LightEntry = false;
3667 }
3602 } 3668 }
3603 } 3669 }
3604 } 3670
3605 3671 ++updatesThisCall;
3606 ++updatesThisCall; 3672
3607 3673 #region UpdateFlags to packet type conversion
3608 #region UpdateFlags to packet type conversion 3674
3609 3675 PrimUpdateFlags updateFlags = update.Flags;
3610 PrimUpdateFlags updateFlags = update.Flags; 3676
3611 3677 bool canUseCompressed = true;
3612 bool canUseCompressed = true; 3678 bool canUseImproved = true;
3613 bool canUseImproved = true; 3679
3614 3680 // Compressed object updates only make sense for LL primitives
3615 // Compressed object updates only make sense for LL primitives 3681 if (!(update.Entity is SceneObjectPart))
3616 if (!(update.Entity is SceneObjectPart))
3617 {
3618 canUseCompressed = false;
3619 }
3620
3621 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3622 {
3623 canUseCompressed = false;
3624 canUseImproved = false;
3625 }
3626 else
3627 {
3628 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3629 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3630 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3631 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3632 { 3682 {
3633 canUseCompressed = false; 3683 canUseCompressed = false;
3634 } 3684 }
3635 3685
3636 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || 3686 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3637 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3638 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3639 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3640 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3641 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3642 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3643 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3644 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3645 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3646 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3647 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3648 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3649 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3650 { 3687 {
3688 canUseCompressed = false;
3651 canUseImproved = false; 3689 canUseImproved = false;
3652 } 3690 }
3653 }
3654
3655 #endregion UpdateFlags to packet type conversion
3656
3657 #region Block Construction
3658
3659 // TODO: Remove this once we can build compressed updates
3660 canUseCompressed = false;
3661
3662 if (!canUseImproved && !canUseCompressed)
3663 {
3664 if (update.Entity is ScenePresence)
3665 {
3666 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3667 }
3668 else 3691 else
3669 { 3692 {
3670 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment) 3693 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3671 // { 3694 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3672 // SceneObjectPart sop = (SceneObjectPart)update.Entity; 3695 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3673 // string text = sop.Text; 3696 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3674 // if (text.IndexOf("\n") >= 0) 3697 {
3675 // text = text.Remove(text.IndexOf("\n")); 3698 canUseCompressed = false;
3676 // 3699 }
3677 // if (m_attachmentsSent.Contains(sop.ParentID))
3678 // {
3679 //// m_log.DebugFormat(
3680 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3681 //// sop.LocalId, text);
3682 //
3683 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3684 //
3685 // m_attachmentsSent.Add(sop.LocalId);
3686 // }
3687 // else
3688 // {
3689 // m_log.DebugFormat(
3690 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3691 // sop.LocalId, text, sop.ParentID);
3692 //
3693 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3694 // }
3695 // }
3696 // else
3697 // {
3698 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3699 // }
3700 }
3701 }
3702 else if (!canUseImproved)
3703 {
3704 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3705 }
3706 else
3707 {
3708 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3709 // Self updates go into a special list
3710 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3711 else
3712 // Everything else goes here
3713 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3714 }
3715
3716 #endregion Block Construction
3717 }
3718
3719 #region Packet Sending
3720 3700
3721 const float TIME_DILATION = 1.0f; 3701 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3722 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 3702 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3723 3703 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3724 if (terseAgentUpdateBlocks.IsValueCreated) 3704 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3725 { 3705 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3726 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3706 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3727 3707 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3728 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3708 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3729 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3709 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3730 packet.RegionData.TimeDilation = timeDilation; 3710 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3731 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3711 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3732 3712 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3733 for (int i = 0; i < blocks.Count; i++) 3713 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3734 packet.ObjectData[i] = blocks[i]; 3714 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3735 3715 {
3736 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3716 canUseImproved = false;
3737 } 3717 }
3738 3718 }
3739 if (objectUpdateBlocks.IsValueCreated)
3740 {
3741 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3742 3719
3743 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3720 #endregion UpdateFlags to packet type conversion
3744 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3745 packet.RegionData.TimeDilation = timeDilation;
3746 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3747 3721
3748 for (int i = 0; i < blocks.Count; i++) 3722 #region Block Construction
3749 packet.ObjectData[i] = blocks[i];
3750 3723
3751 OutPacket(packet, ThrottleOutPacketType.Task, true); 3724 // TODO: Remove this once we can build compressed updates
3752 } 3725 canUseCompressed = false;
3753 3726
3754 if (compressedUpdateBlocks.IsValueCreated) 3727 if (!canUseImproved && !canUseCompressed)
3755 { 3728 {
3756 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 3729 if (update.Entity is ScenePresence)
3730 {
3731 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3732 }
3733 else
3734 {
3735 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3736 // {
3737 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3738 // string text = sop.Text;
3739 // if (text.IndexOf("\n") >= 0)
3740 // text = text.Remove(text.IndexOf("\n"));
3741 //
3742 // if (m_attachmentsSent.Contains(sop.ParentID))
3743 // {
3744 //// m_log.DebugFormat(
3745 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3746 //// sop.LocalId, text);
3747 //
3748 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3749 //
3750 // m_attachmentsSent.Add(sop.LocalId);
3751 // }
3752 // else
3753 // {
3754 // m_log.DebugFormat(
3755 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3756 // sop.LocalId, text, sop.ParentID);
3757 //
3758 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3759 // }
3760 // }
3761 // else
3762 // {
3763 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3764 // }
3765 }
3766 }
3767 else if (!canUseImproved)
3768 {
3769 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3770 }
3771 else
3772 {
3773 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3774 // Self updates go into a special list
3775 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3776 else
3777 // Everything else goes here
3778 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3779 }
3757 3780
3758 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); 3781 #endregion Block Construction
3759 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3782 }
3760 packet.RegionData.TimeDilation = timeDilation;
3761 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3762 3783
3763 for (int i = 0; i < blocks.Count; i++) 3784 #region Packet Sending
3764 packet.ObjectData[i] = blocks[i]; 3785
3786 const float TIME_DILATION = 1.0f;
3787 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
3765 3788
3766 OutPacket(packet, ThrottleOutPacketType.Task, true); 3789 if (terseAgentUpdateBlocks.IsValueCreated)
3767 } 3790 {
3791 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3768 3792
3769 if (terseUpdateBlocks.IsValueCreated) 3793 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3770 { 3794 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3771 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 3795 packet.RegionData.TimeDilation = timeDilation;
3796 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3772 3797
3773 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3798 for (int i = 0; i < blocks.Count; i++)
3774 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3799 packet.ObjectData[i] = blocks[i];
3775 packet.RegionData.TimeDilation = timeDilation;
3776 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3777 3800
3778 for (int i = 0; i < blocks.Count; i++) 3801 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3779 packet.ObjectData[i] = blocks[i]; 3802 }
3780 3803
3781 OutPacket(packet, ThrottleOutPacketType.Task, true); 3804 if (objectUpdateBlocks.IsValueCreated)
3805 {
3806 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3807
3808 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3809 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3810 packet.RegionData.TimeDilation = timeDilation;
3811 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3812
3813 for (int i = 0; i < blocks.Count; i++)
3814 packet.ObjectData[i] = blocks[i];
3815
3816 OutPacket(packet, ThrottleOutPacketType.Task, true);
3817 }
3818
3819 if (compressedUpdateBlocks.IsValueCreated)
3820 {
3821 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3822
3823 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3824 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3825 packet.RegionData.TimeDilation = timeDilation;
3826 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3827
3828 for (int i = 0; i < blocks.Count; i++)
3829 packet.ObjectData[i] = blocks[i];
3830
3831 OutPacket(packet, ThrottleOutPacketType.Task, true);
3832 }
3833
3834 if (terseUpdateBlocks.IsValueCreated)
3835 {
3836 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3837
3838 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3839 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3840 packet.RegionData.TimeDilation = timeDilation;
3841 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3842
3843 for (int i = 0; i < blocks.Count; i++)
3844 packet.ObjectData[i] = blocks[i];
3845
3846 OutPacket(packet, ThrottleOutPacketType.Task, true);
3847 }
3782 } 3848 }
3783 } 3849 }
3784 3850
@@ -4045,6 +4111,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4045 { 4111 {
4046 m_propertiesPacketTimer.Stop(); 4112 m_propertiesPacketTimer.Stop();
4047 4113
4114 if (m_propertiesBlocks.Count == 0)
4115 return;
4116
4048 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4117 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
4049 4118
4050 int index = 0; 4119 int index = 0;
@@ -4436,14 +4505,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4436 4505
4437 if (notifyCount > 0) 4506 if (notifyCount > 0)
4438 { 4507 {
4439 if (notifyCount > 32) 4508// if (notifyCount > 32)
4440 { 4509// {
4441 m_log.InfoFormat( 4510// m_log.InfoFormat(
4442 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4511// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4443 + " - a developer might want to investigate whether this is a hard limit", 32); 4512// + " - a developer might want to investigate whether this is a hard limit", 32);
4444 4513//
4445 notifyCount = 32; 4514// notifyCount = 32;
4446 } 4515// }
4447 4516
4448 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4517 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4449 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4518 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4951,6 +5020,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4951 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5020 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
4952 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5021 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
4953 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5022 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5023 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
4954 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5024 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
4955 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5025 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
4956 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5026 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5050,6 +5120,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5050 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5120 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5051 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5121 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5052 (x.ControlFlags != lastarg.ControlFlags) || 5122 (x.ControlFlags != lastarg.ControlFlags) ||
5123 (x.ControlFlags != 0) ||
5053 (x.Far != lastarg.Far) || 5124 (x.Far != lastarg.Far) ||
5054 (x.Flags != lastarg.Flags) || 5125 (x.Flags != lastarg.Flags) ||
5055 (x.State != lastarg.State) || 5126 (x.State != lastarg.State) ||
@@ -5423,7 +5494,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5423 args.Channel = ch; 5494 args.Channel = ch;
5424 args.From = String.Empty; 5495 args.From = String.Empty;
5425 args.Message = Utils.BytesToString(msg); 5496 args.Message = Utils.BytesToString(msg);
5426 args.Type = ChatTypeEnum.Shout; 5497 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5427 args.Position = new Vector3(); 5498 args.Position = new Vector3();
5428 args.Scene = Scene; 5499 args.Scene = Scene;
5429 args.Sender = this; 5500 args.Sender = this;
@@ -9467,6 +9538,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9467 { 9538 {
9468 return true; 9539 return true;
9469 } 9540 }
9541
9542 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9543 {
9544 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9545
9546 #region Packet Session and User Check
9547 if (m_checkPackets)
9548 {
9549 if (packet.AgentData.SessionID != SessionId ||
9550 packet.AgentData.AgentID != AgentId)
9551 return true;
9552 }
9553 #endregion
9554 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9555 List<InventoryItemBase> items = new List<InventoryItemBase>();
9556 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9557 {
9558 InventoryItemBase b = new InventoryItemBase();
9559 b.ID = n.OldItemID;
9560 b.Folder = n.OldFolderID;
9561 items.Add(b);
9562 }
9563
9564 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9565 if (handlerMoveItemsAndLeaveCopy != null)
9566 {
9567 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9568 }
9569
9570 return true;
9571 }
9470 9572
9471 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9573 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9472 { 9574 {
@@ -10465,11 +10567,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10465 10567
10466 StartLure handlerStartLure = OnStartLure; 10568 StartLure handlerStartLure = OnStartLure;
10467 if (handlerStartLure != null) 10569 if (handlerStartLure != null)
10468 handlerStartLure(startLureRequest.Info.LureType, 10570 {
10469 Utils.BytesToString( 10571 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10470 startLureRequest.Info.Message), 10572 {
10471 startLureRequest.TargetData[0].TargetID, 10573 handlerStartLure(startLureRequest.Info.LureType,
10472 this); 10574 Utils.BytesToString(
10575 startLureRequest.Info.Message),
10576 startLureRequest.TargetData[i].TargetID,
10577 this);
10578 }
10579 }
10473 return true; 10580 return true;
10474 } 10581 }
10475 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10582 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10964,7 +11071,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10964 { 11071 {
10965 // It's a ghost! tell the client to delete it from view. 11072 // It's a ghost! tell the client to delete it from view.
10966 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11073 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
10967 localId); 11074 new List<uint>() { localId });
10968 } 11075 }
10969 else 11076 else
10970 { 11077 {
@@ -11334,22 +11441,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11334 /// <param name="Pack">OpenMetaverse.packet</param> 11441 /// <param name="Pack">OpenMetaverse.packet</param>
11335 public void ProcessInPacket(Packet packet) 11442 public void ProcessInPacket(Packet packet)
11336 { 11443 {
11337 if (m_debugPacketLevel > 0) 11444 if (m_debugPacketLevel >= 255)
11338 { 11445 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11339 bool outputPacket = true;
11340
11341 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11342 outputPacket = false;
11343
11344 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11345 outputPacket = false;
11346
11347 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11348 outputPacket = false;
11349
11350 if (outputPacket)
11351 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11352 }
11353 11446
11354 if (!ProcessPacketMethod(packet)) 11447 if (!ProcessPacketMethod(packet))
11355 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11448 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11591,7 +11684,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11591 11684
11592// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11685// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11593 11686
11687
11688 //Note, the bool returned from the below function is useless since it is always false.
11594 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11689 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11690
11595 } 11691 }
11596 11692
11597 /// <summary> 11693 /// <summary>