aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs526
1 files changed, 335 insertions, 191 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 76d7f79..bdb73ad 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -157,6 +157,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
157 public event RequestTaskInventory OnRequestTaskInventory; 157 public event RequestTaskInventory OnRequestTaskInventory;
158 public event UpdateInventoryItem OnUpdateInventoryItem; 158 public event UpdateInventoryItem OnUpdateInventoryItem;
159 public event CopyInventoryItem OnCopyInventoryItem; 159 public event CopyInventoryItem OnCopyInventoryItem;
160 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
160 public event MoveInventoryItem OnMoveInventoryItem; 161 public event MoveInventoryItem OnMoveInventoryItem;
161 public event RemoveInventoryItem OnRemoveInventoryItem; 162 public event RemoveInventoryItem OnRemoveInventoryItem;
162 public event RemoveInventoryFolder OnRemoveInventoryFolder; 163 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -400,7 +401,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
400 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 401 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
401 /// ownerless phantom. 402 /// ownerless phantom.
402 /// 403 ///
403 /// All manipulation of this set has to occur under a lock 404 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
404 /// 405 ///
405 /// </value> 406 /// </value>
406 protected HashSet<uint> m_killRecord; 407 protected HashSet<uint> m_killRecord;
@@ -408,6 +409,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
408// protected HashSet<uint> m_attachmentsSent; 409// protected HashSet<uint> m_attachmentsSent;
409 410
410 private int m_moneyBalance; 411 private int m_moneyBalance;
412 private bool m_deliverPackets = true;
411 private int m_animationSequenceNumber = 1; 413 private int m_animationSequenceNumber = 1;
412 private bool m_SendLogoutPacketWhenClosing = true; 414 private bool m_SendLogoutPacketWhenClosing = true;
413 private AgentUpdateArgs lastarg; 415 private AgentUpdateArgs lastarg;
@@ -451,6 +453,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
451 get { return m_startpos; } 453 get { return m_startpos; }
452 set { m_startpos = value; } 454 set { m_startpos = value; }
453 } 455 }
456 public bool DeliverPackets
457 {
458 get { return m_deliverPackets; }
459 set {
460 m_deliverPackets = value;
461 m_udpClient.m_deliverPackets = value;
462 }
463 }
454 public UUID AgentId { get { return m_agentId; } } 464 public UUID AgentId { get { return m_agentId; } }
455 public UUID ActiveGroupId { get { return m_activeGroupID; } } 465 public UUID ActiveGroupId { get { return m_activeGroupID; } }
456 public string ActiveGroupName { get { return m_activeGroupName; } } 466 public string ActiveGroupName { get { return m_activeGroupName; } }
@@ -549,18 +559,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
549 559
550 #region Client Methods 560 #region Client Methods
551 561
562
552 /// <summary> 563 /// <summary>
553 /// Shut down the client view 564 /// Shut down the client view
554 /// </summary> 565 /// </summary>
555 public void Close() 566 public void Close()
556 { 567 {
568 Close(true);
569 }
570
571 /// <summary>
572 /// Shut down the client view
573 /// </summary>
574 public void Close(bool sendStop)
575 {
557 m_log.DebugFormat( 576 m_log.DebugFormat(
558 "[CLIENT]: Close has been called for {0} attached to scene {1}", 577 "[CLIENT]: Close has been called for {0} attached to scene {1}",
559 Name, m_scene.RegionInfo.RegionName); 578 Name, m_scene.RegionInfo.RegionName);
560 579
561 // Send the STOP packet 580 if (sendStop)
562 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 581 {
563 OutPacket(disable, ThrottleOutPacketType.Unknown); 582 // Send the STOP packet
583 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
584 OutPacket(disable, ThrottleOutPacketType.Unknown);
585 }
564 586
565 IsActive = false; 587 IsActive = false;
566 588
@@ -841,7 +863,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
841 reply.ChatData.OwnerID = fromAgentID; 863 reply.ChatData.OwnerID = fromAgentID;
842 reply.ChatData.SourceID = fromAgentID; 864 reply.ChatData.SourceID = fromAgentID;
843 865
844 OutPacket(reply, ThrottleOutPacketType.Task); 866 OutPacket(reply, ThrottleOutPacketType.Unknown);
845 } 867 }
846 868
847 /// <summary> 869 /// <summary>
@@ -1127,6 +1149,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 public virtual void SendLayerData(float[] map) 1149 public virtual void SendLayerData(float[] map)
1128 { 1150 {
1129 Util.FireAndForget(DoSendLayerData, map); 1151 Util.FireAndForget(DoSendLayerData, map);
1152
1153 // Send it sync, and async. It's not that much data
1154 // and it improves user experience just so much!
1155 DoSendLayerData(map);
1130 } 1156 }
1131 1157
1132 /// <summary> 1158 /// <summary>
@@ -1139,16 +1165,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1139 1165
1140 try 1166 try
1141 { 1167 {
1142 //for (int y = 0; y < 16; y++) 1168 for (int y = 0; y < 16; y++)
1143 //{ 1169 {
1144 // for (int x = 0; x < 16; x++) 1170 for (int x = 0; x < 16; x+=4)
1145 // { 1171 {
1146 // SendLayerData(x, y, map); 1172 SendLayerPacket(x, y, map);
1147 // } 1173 }
1148 //} 1174 }
1149
1150 // Send LayerData in a spiral pattern. Fun!
1151 SendLayerTopRight(map, 0, 0, 15, 15);
1152 } 1175 }
1153 catch (Exception e) 1176 catch (Exception e)
1154 { 1177 {
@@ -1156,51 +1179,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1156 } 1179 }
1157 } 1180 }
1158 1181
1159 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1160 {
1161 // Row
1162 for (int i = x1; i <= x2; i++)
1163 SendLayerData(i, y1, map);
1164
1165 // Column
1166 for (int j = y1 + 1; j <= y2; j++)
1167 SendLayerData(x2, j, map);
1168
1169 if (x2 - x1 > 0)
1170 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1171 }
1172
1173 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1174 {
1175 // Row in reverse
1176 for (int i = x2; i >= x1; i--)
1177 SendLayerData(i, y2, map);
1178
1179 // Column in reverse
1180 for (int j = y2 - 1; j >= y1; j--)
1181 SendLayerData(x1, j, map);
1182
1183 if (x2 - x1 > 0)
1184 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1185 }
1186
1187 /// <summary> 1182 /// <summary>
1188 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1183 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1189 /// </summary> 1184 /// </summary>
1190 /// <param name="map">heightmap</param> 1185 /// <param name="map">heightmap</param>
1191 /// <param name="px">X coordinate for patches 0..12</param> 1186 /// <param name="px">X coordinate for patches 0..12</param>
1192 /// <param name="py">Y coordinate for patches 0..15</param> 1187 /// <param name="py">Y coordinate for patches 0..15</param>
1193 // private void SendLayerPacket(float[] map, int y, int x) 1188 private void SendLayerPacket(int x, int y, float[] map)
1194 // { 1189 {
1195 // int[] patches = new int[4]; 1190 int[] patches = new int[4];
1196 // patches[0] = x + 0 + y * 16; 1191 patches[0] = x + 0 + y * 16;
1197 // patches[1] = x + 1 + y * 16; 1192 patches[1] = x + 1 + y * 16;
1198 // patches[2] = x + 2 + y * 16; 1193 patches[2] = x + 2 + y * 16;
1199 // patches[3] = x + 3 + y * 16; 1194 patches[3] = x + 3 + y * 16;
1200 1195
1201 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1196 float[] heightmap = (map.Length == 65536) ?
1202 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1197 map :
1203 // } 1198 LLHeightFieldMoronize(map);
1199
1200 try
1201 {
1202 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1203 OutPacket(layerpack, ThrottleOutPacketType.Land);
1204 }
1205 catch
1206 {
1207 for (int px = x ; px < x + 4 ; px++)
1208 SendLayerData(px, y, map);
1209 }
1210 }
1204 1211
1205 /// <summary> 1212 /// <summary>
1206 /// Sends a specified patch to a client 1213 /// Sends a specified patch to a client
@@ -1220,7 +1227,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1220 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1227 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1221 layerpack.Header.Reliable = true; 1228 layerpack.Header.Reliable = true;
1222 1229
1223 OutPacket(layerpack, ThrottleOutPacketType.Land); 1230 OutPacket(layerpack, ThrottleOutPacketType.Task);
1224 } 1231 }
1225 catch (Exception e) 1232 catch (Exception e)
1226 { 1233 {
@@ -1581,37 +1588,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1581 OutPacket(pc, ThrottleOutPacketType.Unknown); 1588 OutPacket(pc, ThrottleOutPacketType.Unknown);
1582 } 1589 }
1583 1590
1584 public void SendKillObject(ulong regionHandle, uint localID) 1591 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1585 { 1592 {
1586// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1593// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle);
1587 1594
1588 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1595 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1589 // TODO: don't create new blocks if recycling an old packet 1596 // TODO: don't create new blocks if recycling an old packet
1590 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[1]; 1597 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
1591 kill.ObjectData[0] = new KillObjectPacket.ObjectDataBlock(); 1598 for (int i = 0 ; i < localIDs.Count ; i++ )
1592 kill.ObjectData[0].ID = localID; 1599 {
1600 kill.ObjectData[i] = new KillObjectPacket.ObjectDataBlock();
1601 kill.ObjectData[i].ID = localIDs[i];
1602 }
1593 kill.Header.Reliable = true; 1603 kill.Header.Reliable = true;
1594 kill.Header.Zerocoded = true; 1604 kill.Header.Zerocoded = true;
1595 1605
1596 if (m_scene.GetScenePresence(localID) == null) 1606 lock (m_killRecord)
1597 { 1607 {
1598 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 1608 if (localIDs.Count == 1)
1599 // condition where a kill can be processed before an out-of-date update for the same object.
1600 lock (m_killRecord)
1601 { 1609 {
1602 m_killRecord.Add(localID); 1610 if (m_scene.GetScenePresence(localIDs[0]) != null)
1603 1611 {
1604 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1612 OutPacket(kill, ThrottleOutPacketType.State);
1605 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1613 return;
1606 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1614 }
1607 // scene objects in a viewer until that viewer is relogged in. 1615 m_killRecord.Add(localIDs[0]);
1608 OutPacket(kill, ThrottleOutPacketType.Task); 1616 }
1617 else
1618 {
1619 lock (m_entityUpdates.SyncRoot)
1620 {
1621 foreach (uint localID in localIDs)
1622 m_killRecord.Add(localID);
1623 }
1609 } 1624 }
1610 } 1625 }
1611 else 1626
1612 { 1627 // The throttle queue used here must match that being used for
1613 OutPacket(kill, ThrottleOutPacketType.State); 1628 // updates. Otherwise, there is a chance that a kill packet put
1614 } 1629 // on a separate queue will be sent to the client before an
1630 // existing update packet on another queue. Receiving updates
1631 // after kills results in unowned and undeletable
1632 // scene objects in a viewer until that viewer is relogged in.
1633 OutPacket(kill, ThrottleOutPacketType.Task);
1615 } 1634 }
1616 1635
1617 /// <summary> 1636 /// <summary>
@@ -2324,6 +2343,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2324 OutPacket(sound, ThrottleOutPacketType.Task); 2343 OutPacket(sound, ThrottleOutPacketType.Task);
2325 } 2344 }
2326 2345
2346 public void SendTransferAbort(TransferRequestPacket transferRequest)
2347 {
2348 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2349 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2350 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2351 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2352 OutPacket(abort, ThrottleOutPacketType.Task);
2353 }
2354
2327 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2355 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2328 { 2356 {
2329 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2357 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -3627,7 +3655,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3627 /// </summary> 3655 /// </summary>
3628 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3656 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3629 { 3657 {
3630 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3658 if (entity is SceneObjectPart)
3659 {
3660 SceneObjectPart e = (SceneObjectPart)entity;
3661 SceneObjectGroup g = e.ParentGroup;
3662 if (g.RootPart.Shape.State > 30) // HUD
3663 if (g.OwnerID != AgentId)
3664 return; // Don't send updates for other people's HUDs
3665 }
3666
3631 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3667 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3632 3668
3633 lock (m_entityUpdates.SyncRoot) 3669 lock (m_entityUpdates.SyncRoot)
@@ -3673,9 +3709,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3673//</MIC> 3709//</MIC>
3674 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3710 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3675 // condition where a kill can be processed before an out-of-date update for the same object. 3711 // condition where a kill can be processed before an out-of-date update for the same object.
3712 float avgTimeDilation = 1.0f;
3713
3676 lock (m_killRecord) 3714 lock (m_killRecord)
3677 { 3715 {
3678 float avgTimeDilation = 1.0f;
3679 EntityUpdate update; 3716 EntityUpdate update;
3680 Int32 timeinqueue; // this is just debugging code & can be dropped later 3717 Int32 timeinqueue; // this is just debugging code & can be dropped later
3681 3718
@@ -3690,7 +3727,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3690 if (update.Entity is SceneObjectPart) 3727 if (update.Entity is SceneObjectPart)
3691 { 3728 {
3692 SceneObjectPart part = (SceneObjectPart)update.Entity; 3729 SceneObjectPart part = (SceneObjectPart)update.Entity;
3693 3730
3694 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3731 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3695 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3732 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3696 // safety measure. 3733 // safety measure.
@@ -3701,14 +3738,45 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3701 // 3738 //
3702 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3739 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3703 // after the root prim has been deleted. 3740 // after the root prim has been deleted.
3704 if (m_killRecord.Contains(part.LocalId)) 3741 lock (m_killRecord)
3705 { 3742 {
3706 // m_log.WarnFormat( 3743 if (m_killRecord.Contains(part.LocalId))
3707 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", 3744 continue;
3708 // part.LocalId, Name); 3745 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3746 continue;
3747 }
3748
3749 if (part.ParentGroup.IsDeleted)
3709 continue; 3750 continue;
3710 } 3751
3711 3752 if (part.ParentGroup.IsAttachment)
3753 { // Someone else's HUD, why are we getting these?
3754 if (part.ParentGroup.OwnerID != AgentId &&
3755 part.ParentGroup.RootPart.Shape.State >= 30)
3756 continue;
3757 ScenePresence sp;
3758 // Owner is not in the sim, don't update it to
3759 // anyone
3760 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3761 continue;
3762
3763 List<SceneObjectGroup> atts = sp.Attachments;
3764 bool found = false;
3765 foreach (SceneObjectGroup att in atts)
3766 {
3767 if (att == part.ParentGroup)
3768 {
3769 found = true;
3770 break;
3771 }
3772 }
3773
3774 // It's an attachment of a valid avatar, but
3775 // doesn't seem to be attached, skip
3776 if (!found)
3777 continue;
3778 }
3779
3712 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3780 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3713 { 3781 {
3714 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3782 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
@@ -3718,22 +3786,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3718 } 3786 }
3719 } 3787 }
3720 } 3788 }
3721 3789
3722 ++updatesThisCall; 3790 ++updatesThisCall;
3723 3791
3724 #region UpdateFlags to packet type conversion 3792 #region UpdateFlags to packet type conversion
3725 3793
3726 PrimUpdateFlags updateFlags = update.Flags; 3794 PrimUpdateFlags updateFlags = update.Flags;
3727 3795
3728 bool canUseCompressed = true; 3796 bool canUseCompressed = true;
3729 bool canUseImproved = true; 3797 bool canUseImproved = true;
3730 3798
3731 // Compressed object updates only make sense for LL primitives 3799 // Compressed object updates only make sense for LL primitives
3732 if (!(update.Entity is SceneObjectPart)) 3800 if (!(update.Entity is SceneObjectPart))
3733 { 3801 {
3734 canUseCompressed = false; 3802 canUseCompressed = false;
3735 } 3803 }
3736 3804
3737 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3805 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3738 { 3806 {
3739 canUseCompressed = false; 3807 canUseCompressed = false;
@@ -3746,9 +3814,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3746 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || 3814 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3747 updateFlags.HasFlag(PrimUpdateFlags.Joint)) 3815 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3748 { 3816 {
3749 canUseCompressed = false; 3817 if (update.Entity is ScenePresence)
3818 {
3819 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3820 }
3821 else
3822 {
3823 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3824 }
3750 } 3825 }
3751 3826
3752 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || 3827 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3753 updateFlags.HasFlag(PrimUpdateFlags.ParentID) || 3828 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3754 updateFlags.HasFlag(PrimUpdateFlags.Scale) || 3829 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
@@ -3767,14 +3842,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3767 canUseImproved = false; 3842 canUseImproved = false;
3768 } 3843 }
3769 } 3844 }
3770 3845
3771 #endregion UpdateFlags to packet type conversion 3846 #endregion UpdateFlags to packet type conversion
3772 3847
3773 #region Block Construction 3848 #region Block Construction
3774 3849
3775 // TODO: Remove this once we can build compressed updates 3850 // TODO: Remove this once we can build compressed updates
3776 canUseCompressed = false; 3851 canUseCompressed = false;
3777 3852
3778 if (!canUseImproved && !canUseCompressed) 3853 if (!canUseImproved && !canUseCompressed)
3779 { 3854 {
3780 if (update.Entity is ScenePresence) 3855 if (update.Entity is ScenePresence)
@@ -3783,7 +3858,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3783 } 3858 }
3784 else 3859 else
3785 { 3860 {
3786 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); 3861 // if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment)
3862 // {
3863 // SceneObjectPart sop = (SceneObjectPart)update.Entity;
3864 // string text = sop.Text;
3865 // if (text.IndexOf("\n") >= 0)
3866 // text = text.Remove(text.IndexOf("\n"));
3867 //
3868 // if (m_attachmentsSent.Contains(sop.ParentID))
3869 // {
3870 //// m_log.DebugFormat(
3871 //// "[CLIENT]: Sending full info about attached prim {0} text {1}",
3872 //// sop.LocalId, text);
3873 //
3874 // objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId));
3875 //
3876 // m_attachmentsSent.Add(sop.LocalId);
3877 // }
3878 // else
3879 // {
3880 // m_log.DebugFormat(
3881 // "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet",
3882 // sop.LocalId, text, sop.ParentID);
3883 //
3884 // m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId);
3885 // }
3886 // }
3887 // else
3888 // {
3889 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3890 // }
3787 } 3891 }
3788 } 3892 }
3789 else if (!canUseImproved) 3893 else if (!canUseImproved)
@@ -3799,77 +3903,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3799 // Everything else goes here 3903 // Everything else goes here
3800 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 3904 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3801 } 3905 }
3802 3906
3803 #endregion Block Construction 3907 #endregion Block Construction
3804 } 3908 }
3909 }
3910
3911 #region Packet Sending
3805 3912
3806 #region Packet Sending 3913 const float TIME_DILATION = 1.0f;
3807 3914 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3808 //const float TIME_DILATION = 1.0f; 3915
3916 if (terseAgentUpdateBlocks.IsValueCreated)
3917 {
3918 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3919
3920 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3921 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3922 packet.RegionData.TimeDilation = timeDilation;
3923 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3809 3924
3925 for (int i = 0; i < blocks.Count; i++)
3926 packet.ObjectData[i] = blocks[i];
3810 3927
3811 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3928 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3929 }
3930
3931 if (objectUpdateBlocks.IsValueCreated)
3932 {
3933 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3812 3934
3813 if (terseAgentUpdateBlocks.IsValueCreated) 3935 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3814 { 3936 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3815 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3937 packet.RegionData.TimeDilation = timeDilation;
3938 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3816 3939
3817 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3940 for (int i = 0; i < blocks.Count; i++)
3818 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3941 packet.ObjectData[i] = blocks[i];
3819 packet.RegionData.TimeDilation = timeDilation;
3820 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3821 3942
3822 for (int i = 0; i < blocks.Count; i++) 3943 OutPacket(packet, ThrottleOutPacketType.Task, true);
3823 packet.ObjectData[i] = blocks[i]; 3944 }
3945
3946 if (compressedUpdateBlocks.IsValueCreated)
3947 {
3948 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3949
3950 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3951 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3952 packet.RegionData.TimeDilation = timeDilation;
3953 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3824 3954
3825 3955 for (int i = 0; i < blocks.Count; i++)
3826 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 3956 packet.ObjectData[i] = blocks[i];
3827 }
3828 3957
3829 if (objectUpdateBlocks.IsValueCreated) 3958 OutPacket(packet, ThrottleOutPacketType.Task, true);
3830 { 3959 }
3831 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3960
3832 3961 if (terseUpdateBlocks.IsValueCreated)
3833 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3962 {
3834 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3963 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3835 packet.RegionData.TimeDilation = timeDilation; 3964
3836 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3965 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3837 3966 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3838 for (int i = 0; i < blocks.Count; i++) 3967 packet.RegionData.TimeDilation = timeDilation;
3839 packet.ObjectData[i] = blocks[i]; 3968 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3840 3969
3841 OutPacket(packet, ThrottleOutPacketType.Task, true); 3970 for (int i = 0; i < blocks.Count; i++)
3842 } 3971 packet.ObjectData[i] = blocks[i];
3843 3972
3844 if (compressedUpdateBlocks.IsValueCreated) 3973 OutPacket(packet, ThrottleOutPacketType.Task, true);
3845 {
3846 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3847
3848 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3849 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3850 packet.RegionData.TimeDilation = timeDilation;
3851 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3852
3853 for (int i = 0; i < blocks.Count; i++)
3854 packet.ObjectData[i] = blocks[i];
3855
3856 OutPacket(packet, ThrottleOutPacketType.Task, true);
3857 }
3858
3859 if (terseUpdateBlocks.IsValueCreated)
3860 {
3861 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3862
3863 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3864 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3865 packet.RegionData.TimeDilation = timeDilation;
3866 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3867
3868 for (int i = 0; i < blocks.Count; i++)
3869 packet.ObjectData[i] = blocks[i];
3870
3871 OutPacket(packet, ThrottleOutPacketType.Task, true);
3872 }
3873 } 3974 }
3874 3975
3875 #endregion Packet Sending 3976 #endregion Packet Sending
@@ -4133,6 +4234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4133 { 4234 {
4134 m_propertiesPacketTimer.Stop(); 4235 m_propertiesPacketTimer.Stop();
4135 4236
4237 if (m_propertiesBlocks.Count == 0)
4238 return;
4239
4136 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count]; 4240 proper.ObjectData = new ObjectPropertiesPacket.ObjectDataBlock[m_propertiesBlocks.Count];
4137 4241
4138 int index = 0; 4242 int index = 0;
@@ -4541,14 +4645,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4541 4645
4542 if (notifyCount > 0) 4646 if (notifyCount > 0)
4543 { 4647 {
4544 if (notifyCount > 32) 4648// if (notifyCount > 32)
4545 { 4649// {
4546 m_log.InfoFormat( 4650// m_log.InfoFormat(
4547 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4651// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4548 + " - a developer might want to investigate whether this is a hard limit", 32); 4652// + " - a developer might want to investigate whether this is a hard limit", 32);
4549 4653//
4550 notifyCount = 32; 4654// notifyCount = 32;
4551 } 4655// }
4552 4656
4553 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4657 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4554 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4658 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -5056,6 +5160,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5056 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5160 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5057 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5161 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5058 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5162 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5163 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5059 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5164 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5060 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5165 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5061 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5166 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5155,6 +5260,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5155 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5260 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5156 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5261 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5157 (x.ControlFlags != lastarg.ControlFlags) || 5262 (x.ControlFlags != lastarg.ControlFlags) ||
5263 (x.ControlFlags != 0) ||
5158 (x.Far != lastarg.Far) || 5264 (x.Far != lastarg.Far) ||
5159 (x.Flags != lastarg.Flags) || 5265 (x.Flags != lastarg.Flags) ||
5160 (x.State != lastarg.State) || 5266 (x.State != lastarg.State) ||
@@ -5528,7 +5634,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5528 args.Channel = ch; 5634 args.Channel = ch;
5529 args.From = String.Empty; 5635 args.From = String.Empty;
5530 args.Message = Utils.BytesToString(msg); 5636 args.Message = Utils.BytesToString(msg);
5531 args.Type = ChatTypeEnum.Shout; 5637 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5532 args.Position = new Vector3(); 5638 args.Position = new Vector3();
5533 args.Scene = Scene; 5639 args.Scene = Scene;
5534 args.Sender = this; 5640 args.Sender = this;
@@ -9516,7 +9622,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9516 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9622 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9517 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9623 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9518 UpdateMuteListEntry.MuteData.MuteType, 9624 UpdateMuteListEntry.MuteData.MuteType,
9519 UpdateMuteListEntry.AgentData.AgentID); 9625 UpdateMuteListEntry.MuteData.MuteFlags);
9520 return true; 9626 return true;
9521 } 9627 }
9522 return false; 9628 return false;
@@ -9531,8 +9637,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9531 { 9637 {
9532 handlerRemoveMuteListEntry(this, 9638 handlerRemoveMuteListEntry(this,
9533 RemoveMuteListEntry.MuteData.MuteID, 9639 RemoveMuteListEntry.MuteData.MuteID,
9534 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9640 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9535 RemoveMuteListEntry.AgentData.AgentID);
9536 return true; 9641 return true;
9537 } 9642 }
9538 return false; 9643 return false;
@@ -9580,6 +9685,37 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9580 { 9685 {
9581 return true; 9686 return true;
9582 } 9687 }
9688
9689 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9690 {
9691 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9692
9693 #region Packet Session and User Check
9694 if (m_checkPackets)
9695 {
9696 if (packet.AgentData.SessionID != SessionId ||
9697 packet.AgentData.AgentID != AgentId)
9698 return true;
9699 }
9700 #endregion
9701 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9702 List<InventoryItemBase> items = new List<InventoryItemBase>();
9703 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9704 {
9705 InventoryItemBase b = new InventoryItemBase();
9706 b.ID = n.OldItemID;
9707 b.Folder = n.OldFolderID;
9708 items.Add(b);
9709 }
9710
9711 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9712 if (handlerMoveItemsAndLeaveCopy != null)
9713 {
9714 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9715 }
9716
9717 return true;
9718 }
9583 9719
9584 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9720 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9585 { 9721 {
@@ -10006,6 +10142,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10006 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10142 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10007 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10143 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10008 10144
10145 Scene scene = (Scene)m_scene;
10146 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10147 {
10148 ScenePresence p;
10149 if (scene.TryGetScenePresence(sender.AgentId, out p))
10150 {
10151 if (p.GodLevel >= 200)
10152 {
10153 groupProfileReply.GroupData.OpenEnrollment = true;
10154 groupProfileReply.GroupData.MembershipFee = 0;
10155 }
10156 }
10157 }
10158
10009 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10159 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10010 } 10160 }
10011 return true; 10161 return true;
@@ -10578,11 +10728,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10578 10728
10579 StartLure handlerStartLure = OnStartLure; 10729 StartLure handlerStartLure = OnStartLure;
10580 if (handlerStartLure != null) 10730 if (handlerStartLure != null)
10581 handlerStartLure(startLureRequest.Info.LureType, 10731 {
10582 Utils.BytesToString( 10732 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10583 startLureRequest.Info.Message), 10733 {
10584 startLureRequest.TargetData[0].TargetID, 10734 handlerStartLure(startLureRequest.Info.LureType,
10585 this); 10735 Utils.BytesToString(
10736 startLureRequest.Info.Message),
10737 startLureRequest.TargetData[i].TargetID,
10738 this);
10739 }
10740 }
10586 return true; 10741 return true;
10587 } 10742 }
10588 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10743 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11077,7 +11232,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11077 { 11232 {
11078 // It's a ghost! tell the client to delete it from view. 11233 // It's a ghost! tell the client to delete it from view.
11079 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 11234 simClient.SendKillObject(Scene.RegionInfo.RegionHandle,
11080 localId); 11235 new List<uint>() { localId });
11081 } 11236 }
11082 else 11237 else
11083 { 11238 {
@@ -11450,22 +11605,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11450 /// <param name="Pack">OpenMetaverse.packet</param> 11605 /// <param name="Pack">OpenMetaverse.packet</param>
11451 public void ProcessInPacket(Packet packet) 11606 public void ProcessInPacket(Packet packet)
11452 { 11607 {
11453 if (m_debugPacketLevel > 0) 11608 if (m_debugPacketLevel >= 255)
11454 { 11609 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11455 bool outputPacket = true;
11456
11457 if (m_debugPacketLevel <= 255 && packet.Type == PacketType.AgentUpdate)
11458 outputPacket = false;
11459
11460 if (m_debugPacketLevel <= 200 && packet.Type == PacketType.RequestImage)
11461 outputPacket = false;
11462
11463 if (m_debugPacketLevel <= 100 && (packet.Type == PacketType.ViewerEffect || packet.Type == PacketType.AgentAnimation))
11464 outputPacket = false;
11465
11466 if (outputPacket)
11467 m_log.DebugFormat("[CLIENT]: Packet IN {0}", packet.Type);
11468 }
11469 11610
11470 if (!ProcessPacketMethod(packet)) 11611 if (!ProcessPacketMethod(packet))
11471 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); 11612 m_log.Warn("[CLIENT]: unhandled packet " + packet.Type);
@@ -11707,7 +11848,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11707 11848
11708// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 11849// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11709 11850
11851
11852 //Note, the bool returned from the below function is useless since it is always false.
11710 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 11853 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
11854
11711 } 11855 }
11712 11856
11713 /// <summary> 11857 /// <summary>