aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs972
1 files changed, 613 insertions, 359 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index b388b10..d973a06 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -158,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 public event RequestTaskInventory OnRequestTaskInventory; 158 public event RequestTaskInventory OnRequestTaskInventory;
159 public event UpdateInventoryItem OnUpdateInventoryItem; 159 public event UpdateInventoryItem OnUpdateInventoryItem;
160 public event CopyInventoryItem OnCopyInventoryItem; 160 public event CopyInventoryItem OnCopyInventoryItem;
161 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
161 public event MoveInventoryItem OnMoveInventoryItem; 162 public event MoveInventoryItem OnMoveInventoryItem;
162 public event RemoveInventoryItem OnRemoveInventoryItem; 163 public event RemoveInventoryItem OnRemoveInventoryItem;
163 public event RemoveInventoryFolder OnRemoveInventoryFolder; 164 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -256,7 +257,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
256 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 257 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
257 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 258 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
258 public event ClassifiedDelete OnClassifiedDelete; 259 public event ClassifiedDelete OnClassifiedDelete;
259 public event ClassifiedDelete OnClassifiedGodDelete; 260 public event ClassifiedGodDelete OnClassifiedGodDelete;
260 public event EventNotificationAddRequest OnEventNotificationAddRequest; 261 public event EventNotificationAddRequest OnEventNotificationAddRequest;
261 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 262 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
262 public event EventGodDelete OnEventGodDelete; 263 public event EventGodDelete OnEventGodDelete;
@@ -287,6 +288,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
287 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 288 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
288 public event SimWideDeletesDelegate OnSimWideDeletes; 289 public event SimWideDeletesDelegate OnSimWideDeletes;
289 public event SendPostcard OnSendPostcard; 290 public event SendPostcard OnSendPostcard;
291 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
290 public event MuteListEntryUpdate OnUpdateMuteListEntry; 292 public event MuteListEntryUpdate OnUpdateMuteListEntry;
291 public event MuteListEntryRemove OnRemoveMuteListEntry; 293 public event MuteListEntryRemove OnRemoveMuteListEntry;
292 public event GodlikeMessage onGodlikeMessage; 294 public event GodlikeMessage onGodlikeMessage;
@@ -336,7 +338,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
336 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 338 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
337 /// ownerless phantom. 339 /// ownerless phantom.
338 /// 340 ///
339 /// All manipulation of this set has to occur under a lock 341 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
340 /// 342 ///
341 /// </value> 343 /// </value>
342 protected HashSet<uint> m_killRecord; 344 protected HashSet<uint> m_killRecord;
@@ -344,6 +346,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
344// protected HashSet<uint> m_attachmentsSent; 346// protected HashSet<uint> m_attachmentsSent;
345 347
346 private int m_moneyBalance; 348 private int m_moneyBalance;
349 private bool m_deliverPackets = true;
347 private int m_animationSequenceNumber = 1; 350 private int m_animationSequenceNumber = 1;
348 private bool m_SendLogoutPacketWhenClosing = true; 351 private bool m_SendLogoutPacketWhenClosing = true;
349 private AgentUpdateArgs lastarg; 352 private AgentUpdateArgs lastarg;
@@ -383,6 +386,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
383 get { return m_startpos; } 386 get { return m_startpos; }
384 set { m_startpos = value; } 387 set { m_startpos = value; }
385 } 388 }
389 public bool DeliverPackets
390 {
391 get { return m_deliverPackets; }
392 set {
393 m_deliverPackets = value;
394 m_udpClient.m_deliverPackets = value;
395 }
396 }
386 public UUID AgentId { get { return m_agentId; } } 397 public UUID AgentId { get { return m_agentId; } }
387 public ISceneAgent SceneAgent { get; private set; } 398 public ISceneAgent SceneAgent { get; private set; }
388 public UUID ActiveGroupId { get { return m_activeGroupID; } } 399 public UUID ActiveGroupId { get { return m_activeGroupID; } }
@@ -484,18 +495,30 @@ namespace OpenSim.Region.ClientStack.LindenUDP
484 495
485 #region Client Methods 496 #region Client Methods
486 497
498
487 /// <summary> 499 /// <summary>
488 /// Shut down the client view 500 /// Shut down the client view
489 /// </summary> 501 /// </summary>
490 public void Close() 502 public void Close()
491 { 503 {
504 Close(true);
505 }
506
507 /// <summary>
508 /// Shut down the client view
509 /// </summary>
510 public void Close(bool sendStop)
511 {
492 m_log.DebugFormat( 512 m_log.DebugFormat(
493 "[CLIENT]: Close has been called for {0} attached to scene {1}", 513 "[CLIENT]: Close has been called for {0} attached to scene {1}",
494 Name, m_scene.RegionInfo.RegionName); 514 Name, m_scene.RegionInfo.RegionName);
495 515
496 // Send the STOP packet 516 if (sendStop)
497 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator); 517 {
498 OutPacket(disable, ThrottleOutPacketType.Unknown); 518 // Send the STOP packet
519 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
520 OutPacket(disable, ThrottleOutPacketType.Unknown);
521 }
499 522
500 IsActive = false; 523 IsActive = false;
501 524
@@ -795,7 +818,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
795 reply.ChatData.OwnerID = fromAgentID; 818 reply.ChatData.OwnerID = fromAgentID;
796 reply.ChatData.SourceID = fromAgentID; 819 reply.ChatData.SourceID = fromAgentID;
797 820
798 OutPacket(reply, ThrottleOutPacketType.Task); 821 OutPacket(reply, ThrottleOutPacketType.Unknown);
799 } 822 }
800 823
801 /// <summary> 824 /// <summary>
@@ -1081,6 +1104,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1081 public virtual void SendLayerData(float[] map) 1104 public virtual void SendLayerData(float[] map)
1082 { 1105 {
1083 Util.FireAndForget(DoSendLayerData, map); 1106 Util.FireAndForget(DoSendLayerData, map);
1107
1108 // Send it sync, and async. It's not that much data
1109 // and it improves user experience just so much!
1110 DoSendLayerData(map);
1084 } 1111 }
1085 1112
1086 /// <summary> 1113 /// <summary>
@@ -1093,16 +1120,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1093 1120
1094 try 1121 try
1095 { 1122 {
1096 //for (int y = 0; y < 16; y++) 1123 for (int y = 0; y < 16; y++)
1097 //{ 1124 {
1098 // for (int x = 0; x < 16; x++) 1125 for (int x = 0; x < 16; x+=4)
1099 // { 1126 {
1100 // SendLayerData(x, y, map); 1127 SendLayerPacket(x, y, map);
1101 // } 1128 }
1102 //} 1129 }
1103
1104 // Send LayerData in a spiral pattern. Fun!
1105 SendLayerTopRight(map, 0, 0, 15, 15);
1106 } 1130 }
1107 catch (Exception e) 1131 catch (Exception e)
1108 { 1132 {
@@ -1110,51 +1134,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1110 } 1134 }
1111 } 1135 }
1112 1136
1113 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1114 {
1115 // Row
1116 for (int i = x1; i <= x2; i++)
1117 SendLayerData(i, y1, map);
1118
1119 // Column
1120 for (int j = y1 + 1; j <= y2; j++)
1121 SendLayerData(x2, j, map);
1122
1123 if (x2 - x1 > 0)
1124 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1125 }
1126
1127 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1128 {
1129 // Row in reverse
1130 for (int i = x2; i >= x1; i--)
1131 SendLayerData(i, y2, map);
1132
1133 // Column in reverse
1134 for (int j = y2 - 1; j >= y1; j--)
1135 SendLayerData(x1, j, map);
1136
1137 if (x2 - x1 > 0)
1138 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1139 }
1140
1141 /// <summary> 1137 /// <summary>
1142 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1138 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1143 /// </summary> 1139 /// </summary>
1144 /// <param name="map">heightmap</param> 1140 /// <param name="map">heightmap</param>
1145 /// <param name="px">X coordinate for patches 0..12</param> 1141 /// <param name="px">X coordinate for patches 0..12</param>
1146 /// <param name="py">Y coordinate for patches 0..15</param> 1142 /// <param name="py">Y coordinate for patches 0..15</param>
1147 // private void SendLayerPacket(float[] map, int y, int x) 1143 private void SendLayerPacket(int x, int y, float[] map)
1148 // { 1144 {
1149 // int[] patches = new int[4]; 1145 int[] patches = new int[4];
1150 // patches[0] = x + 0 + y * 16; 1146 patches[0] = x + 0 + y * 16;
1151 // patches[1] = x + 1 + y * 16; 1147 patches[1] = x + 1 + y * 16;
1152 // patches[2] = x + 2 + y * 16; 1148 patches[2] = x + 2 + y * 16;
1153 // patches[3] = x + 3 + y * 16; 1149 patches[3] = x + 3 + y * 16;
1154 1150
1155 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1151 float[] heightmap = (map.Length == 65536) ?
1156 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1152 map :
1157 // } 1153 LLHeightFieldMoronize(map);
1154
1155 try
1156 {
1157 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1158 OutPacket(layerpack, ThrottleOutPacketType.Land);
1159 }
1160 catch
1161 {
1162 for (int px = x ; px < x + 4 ; px++)
1163 SendLayerData(px, y, map);
1164 }
1165 }
1158 1166
1159 /// <summary> 1167 /// <summary>
1160 /// Sends a specified patch to a client 1168 /// Sends a specified patch to a client
@@ -1174,7 +1182,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1174 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1182 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1175 layerpack.Header.Reliable = true; 1183 layerpack.Header.Reliable = true;
1176 1184
1177 OutPacket(layerpack, ThrottleOutPacketType.Land); 1185 OutPacket(layerpack, ThrottleOutPacketType.Task);
1178 } 1186 }
1179 catch (Exception e) 1187 catch (Exception e)
1180 { 1188 {
@@ -1537,7 +1545,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1537 1545
1538 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1546 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1539 { 1547 {
1540// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1548// foreach (uint id in localIDs)
1549// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1541 1550
1542 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1551 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1543 // TODO: don't create new blocks if recycling an old packet 1552 // TODO: don't create new blocks if recycling an old packet
@@ -2298,6 +2307,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2298 OutPacket(sound, ThrottleOutPacketType.Task); 2307 OutPacket(sound, ThrottleOutPacketType.Task);
2299 } 2308 }
2300 2309
2310 public void SendTransferAbort(TransferRequestPacket transferRequest)
2311 {
2312 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2313 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2314 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2315 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2316 OutPacket(abort, ThrottleOutPacketType.Task);
2317 }
2318
2301 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2319 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2302 { 2320 {
2303 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2321 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2745,7 +2763,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2745 reply.Data.ParcelID = parcelID; 2763 reply.Data.ParcelID = parcelID;
2746 reply.Data.OwnerID = land.OwnerID; 2764 reply.Data.OwnerID = land.OwnerID;
2747 reply.Data.Name = Utils.StringToBytes(land.Name); 2765 reply.Data.Name = Utils.StringToBytes(land.Name);
2748 reply.Data.Desc = Utils.StringToBytes(land.Description); 2766 if (land != null && land.Description != null && land.Description != String.Empty)
2767 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
2768 else
2769 reply.Data.Desc = new Byte[0];
2749 reply.Data.ActualArea = land.Area; 2770 reply.Data.ActualArea = land.Area;
2750 reply.Data.BillableArea = land.Area; // TODO: what is this? 2771 reply.Data.BillableArea = land.Area; // TODO: what is this?
2751 2772
@@ -3608,7 +3629,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3608 /// </summary> 3629 /// </summary>
3609 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3630 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3610 { 3631 {
3611 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3632 if (entity is SceneObjectPart)
3633 {
3634 SceneObjectPart e = (SceneObjectPart)entity;
3635 SceneObjectGroup g = e.ParentGroup;
3636 if (g.RootPart.Shape.State > 30) // HUD
3637 if (g.OwnerID != AgentId)
3638 return; // Don't send updates for other people's HUDs
3639 }
3640
3612 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3641 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3613 3642
3614 lock (m_entityUpdates.SyncRoot) 3643 lock (m_entityUpdates.SyncRoot)
@@ -3675,211 +3704,238 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3675 3704
3676 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3705 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3677 // condition where a kill can be processed before an out-of-date update for the same object. 3706 // condition where a kill can be processed before an out-of-date update for the same object.
3678 lock (m_killRecord) 3707 float avgTimeDilation = 1.0f;
3708 IEntityUpdate iupdate;
3709 Int32 timeinqueue; // this is just debugging code & can be dropped later
3710
3711 while (updatesThisCall < maxUpdates)
3679 { 3712 {
3680 float avgTimeDilation = 1.0f; 3713 lock (m_entityUpdates.SyncRoot)
3681 IEntityUpdate iupdate; 3714 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3682 Int32 timeinqueue; // this is just debugging code & can be dropped later 3715 break;
3683
3684 while (updatesThisCall < maxUpdates)
3685 {
3686 lock (m_entityUpdates.SyncRoot)
3687 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3688 break;
3689 3716
3690 EntityUpdate update = (EntityUpdate)iupdate; 3717 EntityUpdate update = (EntityUpdate)iupdate;
3691 3718
3692 avgTimeDilation += update.TimeDilation; 3719 avgTimeDilation += update.TimeDilation;
3693 avgTimeDilation *= 0.5f; 3720 avgTimeDilation *= 0.5f;
3694 3721
3695 if (update.Entity is SceneObjectPart) 3722 if (update.Entity is SceneObjectPart)
3723 {
3724 SceneObjectPart part = (SceneObjectPart)update.Entity;
3725
3726 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3727 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3728 // safety measure.
3729 //
3730 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3731 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3732 // updates and kills on different threads with different scheduling strategies, hence this protection.
3733 //
3734 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3735 // after the root prim has been deleted.
3736 lock (m_killRecord)
3696 { 3737 {
3697 SceneObjectPart part = (SceneObjectPart)update.Entity;
3698
3699 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3700 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3701 // safety measure.
3702 //
3703 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3704 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3705 // updates and kills on different threads with different scheduling strategies, hence this protection.
3706 //
3707 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3708 // after the root prim has been deleted.
3709 if (m_killRecord.Contains(part.LocalId)) 3738 if (m_killRecord.Contains(part.LocalId))
3710 {
3711 // m_log.WarnFormat(
3712 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted",
3713 // part.LocalId, Name);
3714 continue; 3739 continue;
3715 } 3740 if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3716 3741 continue;
3717 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3742 }
3743
3744 if (part.ParentGroup.IsDeleted)
3745 continue;
3746
3747 if (part.ParentGroup.IsAttachment)
3748 { // Someone else's HUD, why are we getting these?
3749 if (part.ParentGroup.OwnerID != AgentId &&
3750 part.ParentGroup.RootPart.Shape.State >= 30)
3751 continue;
3752 ScenePresence sp;
3753 // Owner is not in the sim, don't update it to
3754 // anyone
3755 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3756 continue;
3757
3758 List<SceneObjectGroup> atts = sp.GetAttachments();
3759 bool found = false;
3760 foreach (SceneObjectGroup att in atts)
3718 { 3761 {
3719 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3762 if (att == part.ParentGroup)
3720 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3721 { 3763 {
3722 part.Shape.LightEntry = false; 3764 found = true;
3765 break;
3723 } 3766 }
3724 } 3767 }
3768
3769 // It's an attachment of a valid avatar, but
3770 // doesn't seem to be attached, skip
3771 if (!found)
3772 continue;
3773
3774 // On vehicle crossing, the attachments are received
3775 // while the avatar is still a child. Don't send
3776 // updates here because the LocalId has not yet
3777 // been updated and the viewer will derender the
3778 // attachments until the avatar becomes root.
3779 if (sp.IsChildAgent)
3780 continue;
3725 } 3781 }
3726 3782 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3727 ++updatesThisCall;
3728
3729 #region UpdateFlags to packet type conversion
3730
3731 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3732
3733 bool canUseCompressed = true;
3734 bool canUseImproved = true;
3735
3736 // Compressed object updates only make sense for LL primitives
3737 if (!(update.Entity is SceneObjectPart))
3738 {
3739 canUseCompressed = false;
3740 }
3741
3742 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3743 { 3783 {
3744 canUseCompressed = false; 3784 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3745 canUseImproved = false; 3785 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3746 }
3747 else
3748 {
3749 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3750 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3751 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3752 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3753 {
3754 canUseCompressed = false;
3755 }
3756
3757 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3758 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3759 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3760 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3761 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3762 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3763 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3764 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3765 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3766 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3767 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3768 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3769 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3770 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3771 { 3786 {
3772 canUseImproved = false; 3787 part.Shape.LightEntry = false;
3773 } 3788 }
3774 } 3789 }
3775 3790 }
3776 #endregion UpdateFlags to packet type conversion 3791
3777 3792 ++updatesThisCall;
3778 #region Block Construction 3793
3779 3794 #region UpdateFlags to packet type conversion
3780 // TODO: Remove this once we can build compressed updates 3795
3796 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3797
3798 bool canUseCompressed = true;
3799 bool canUseImproved = true;
3800
3801 // Compressed object updates only make sense for LL primitives
3802 if (!(update.Entity is SceneObjectPart))
3803 {
3781 canUseCompressed = false; 3804 canUseCompressed = false;
3782 3805 }
3783 if (!canUseImproved && !canUseCompressed) 3806
3784 { 3807 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3785 if (update.Entity is ScenePresence) 3808 {
3786 { 3809 canUseCompressed = false;
3787 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); 3810 canUseImproved = false;
3788 objectUpdates.Value.Add(update); 3811 }
3789 } 3812 else
3790 else 3813 {
3791 { 3814 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3792 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); 3815 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3793 objectUpdates.Value.Add(update); 3816 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3794 } 3817 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3795 }
3796 else if (!canUseImproved)
3797 { 3818 {
3798 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); 3819 canUseCompressed = false;
3799 compressedUpdates.Value.Add(update);
3800 } 3820 }
3801 else 3821
3822 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3823 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3824 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3825 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3826 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3827 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3828 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3829 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3830 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3831 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3832 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3833 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3834 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3835 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3802 { 3836 {
3803 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3837 canUseImproved = false;
3804 {
3805 // Self updates go into a special list
3806 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3807 terseAgentUpdates.Value.Add(update);
3808 }
3809 else
3810 {
3811 // Everything else goes here
3812 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3813 terseUpdates.Value.Add(update);
3814 }
3815 } 3838 }
3816
3817 #endregion Block Construction
3818 } 3839 }
3819
3820
3821 #region Packet Sending
3822 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3823 3840
3824 if (terseAgentUpdateBlocks.IsValueCreated) 3841 #endregion UpdateFlags to packet type conversion
3825 {
3826 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3827 3842
3828 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3843 #region Block Construction
3829 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3830 packet.RegionData.TimeDilation = timeDilation;
3831 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3832 3844
3833 for (int i = 0; i < blocks.Count; i++) 3845 // TODO: Remove this once we can build compressed updates
3834 packet.ObjectData[i] = blocks[i]; 3846 canUseCompressed = false;
3835 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3836 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); });
3837 }
3838 3847
3839 if (objectUpdateBlocks.IsValueCreated) 3848 if (!canUseImproved && !canUseCompressed)
3840 { 3849 {
3841 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; 3850 if (update.Entity is ScenePresence)
3842 3851 {
3843 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3852 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3844 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3853 }
3845 packet.RegionData.TimeDilation = timeDilation; 3854 else
3846 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3855 {
3847 3856 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3848 for (int i = 0; i < blocks.Count; i++) 3857 }
3849 packet.ObjectData[i] = blocks[i];
3850 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3851 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3852 } 3858 }
3853 3859 else if (!canUseImproved)
3854 if (compressedUpdateBlocks.IsValueCreated)
3855 { 3860 {
3856 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; 3861 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3857
3858 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3859 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3860 packet.RegionData.TimeDilation = timeDilation;
3861 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3862
3863 for (int i = 0; i < blocks.Count; i++)
3864 packet.ObjectData[i] = blocks[i];
3865 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3866 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3867 } 3862 }
3868 3863 else
3869 if (terseUpdateBlocks.IsValueCreated)
3870 { 3864 {
3871 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; 3865 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3872 3866 // Self updates go into a special list
3873 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); 3867 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3874 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3868 else
3875 packet.RegionData.TimeDilation = timeDilation; 3869 // Everything else goes here
3876 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3870 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3877
3878 for (int i = 0; i < blocks.Count; i++)
3879 packet.ObjectData[i] = blocks[i];
3880 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3881 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3882 } 3871 }
3872
3873 #endregion Block Construction
3874 }
3875
3876 #region Packet Sending
3877
3878 const float TIME_DILATION = 1.0f;
3879 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3880
3881 if (terseAgentUpdateBlocks.IsValueCreated)
3882 {
3883 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3884
3885 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3886 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3887 packet.RegionData.TimeDilation = timeDilation;
3888 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3889
3890 for (int i = 0; i < blocks.Count; i++)
3891 packet.ObjectData[i] = blocks[i];
3892
3893 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3894 }
3895
3896 if (objectUpdateBlocks.IsValueCreated)
3897 {
3898 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3899
3900 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3901 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3902 packet.RegionData.TimeDilation = timeDilation;
3903 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3904
3905 for (int i = 0; i < blocks.Count; i++)
3906 packet.ObjectData[i] = blocks[i];
3907
3908 OutPacket(packet, ThrottleOutPacketType.Task, true);
3909 }
3910
3911 if (compressedUpdateBlocks.IsValueCreated)
3912 {
3913 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3914
3915 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3916 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3917 packet.RegionData.TimeDilation = timeDilation;
3918 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3919
3920 for (int i = 0; i < blocks.Count; i++)
3921 packet.ObjectData[i] = blocks[i];
3922
3923 OutPacket(packet, ThrottleOutPacketType.Task, true);
3924 }
3925
3926 if (terseUpdateBlocks.IsValueCreated)
3927 {
3928 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3929
3930 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3931 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3932 packet.RegionData.TimeDilation = timeDilation;
3933 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3934
3935 for (int i = 0; i < blocks.Count; i++)
3936 packet.ObjectData[i] = blocks[i];
3937
3938 OutPacket(packet, ThrottleOutPacketType.Task, true);
3883 } 3939 }
3884 3940
3885 #endregion Packet Sending 3941 #endregion Packet Sending
@@ -4172,11 +4228,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4172 4228
4173 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4229 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4174 // of the object rather than the properties when the packet was created 4230 // of the object rather than the properties when the packet was created
4175 OutPacket(packet, ThrottleOutPacketType.Task, true, 4231 // HACK : Remove intelligent resending until it's fixed in core
4176 delegate(OutgoingPacket oPacket) 4232 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4177 { 4233 // delegate(OutgoingPacket oPacket)
4178 ResendPropertyUpdates(updates, oPacket); 4234 // {
4179 }); 4235 // ResendPropertyUpdates(updates, oPacket);
4236 // });
4237 OutPacket(packet, ThrottleOutPacketType.Task, true);
4180 4238
4181 // pbcnt += blocks.Count; 4239 // pbcnt += blocks.Count;
4182 // ppcnt++; 4240 // ppcnt++;
@@ -4202,11 +4260,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4202 // of the object rather than the properties when the packet was created 4260 // of the object rather than the properties when the packet was created
4203 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4261 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4204 updates.Add(familyUpdates.Value[i]); 4262 updates.Add(familyUpdates.Value[i]);
4205 OutPacket(packet, ThrottleOutPacketType.Task, true, 4263 // HACK : Remove intelligent resending until it's fixed in core
4206 delegate(OutgoingPacket oPacket) 4264 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4207 { 4265 // delegate(OutgoingPacket oPacket)
4208 ResendPropertyUpdates(updates, oPacket); 4266 // {
4209 }); 4267 // ResendPropertyUpdates(updates, oPacket);
4268 // });
4269 OutPacket(packet, ThrottleOutPacketType.Task, true);
4210 4270
4211 // fpcnt++; 4271 // fpcnt++;
4212 // fbcnt++; 4272 // fbcnt++;
@@ -4355,37 +4415,44 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4355 if (bl[i].BannedUserID == UUID.Zero) 4415 if (bl[i].BannedUserID == UUID.Zero)
4356 continue; 4416 continue;
4357 BannedUsers.Add(bl[i].BannedUserID); 4417 BannedUsers.Add(bl[i].BannedUserID);
4358 }
4359 4418
4360 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket(); 4419 if (BannedUsers.Count >= 50 || (i == (bl.Length - 1) && BannedUsers.Count > 0))
4361 packet.AgentData.TransactionID = UUID.Random(); 4420 {
4362 packet.AgentData.AgentID = AgentId; 4421 EstateOwnerMessagePacket packet = new EstateOwnerMessagePacket();
4363 packet.AgentData.SessionID = SessionId; 4422 packet.AgentData.TransactionID = UUID.Random();
4364 packet.MethodData.Invoice = invoice; 4423 packet.AgentData.AgentID = AgentId;
4365 packet.MethodData.Method = Utils.StringToBytes("setaccess"); 4424 packet.AgentData.SessionID = SessionId;
4425 packet.MethodData.Invoice = invoice;
4426 packet.MethodData.Method = Utils.StringToBytes("setaccess");
4366 4427
4367 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count]; 4428 EstateOwnerMessagePacket.ParamListBlock[] returnblock = new EstateOwnerMessagePacket.ParamListBlock[6 + BannedUsers.Count];
4368 4429
4369 for (int i = 0; i < (6 + BannedUsers.Count); i++) 4430 int j;
4370 { 4431 for (j = 0; j < (6 + BannedUsers.Count); j++)
4371 returnblock[i] = new EstateOwnerMessagePacket.ParamListBlock(); 4432 {
4372 } 4433 returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock();
4373 int j = 0; 4434 }
4435 j = 0;
4374 4436
4375 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; 4437 returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++;
4376 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; 4438 returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++;
4377 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4439 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4378 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4440 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4379 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++; 4441 returnblock[j].Parameter = Utils.StringToBytes(BannedUsers.Count.ToString()); j++;
4380 returnblock[j].Parameter = Utils.StringToBytes("0"); j++; 4442 returnblock[j].Parameter = Utils.StringToBytes("0"); j++;
4381 4443
4382 foreach (UUID banned in BannedUsers) 4444 foreach (UUID banned in BannedUsers)
4383 { 4445 {
4384 returnblock[j].Parameter = banned.GetBytes(); j++; 4446 returnblock[j].Parameter = banned.GetBytes(); j++;
4447 }
4448 packet.ParamList = returnblock;
4449 packet.Header.Reliable = true;
4450 OutPacket(packet, ThrottleOutPacketType.Task);
4451
4452 BannedUsers.Clear();
4453 }
4385 } 4454 }
4386 packet.ParamList = returnblock; 4455
4387 packet.Header.Reliable = false;
4388 OutPacket(packet, ThrottleOutPacketType.Task);
4389 } 4456 }
4390 4457
4391 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args) 4458 public void SendRegionInfoToEstateMenu(RegionInfoForEstateMenuArgs args)
@@ -4571,7 +4638,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4571 4638
4572 if (landData.SimwideArea > 0) 4639 if (landData.SimwideArea > 0)
4573 { 4640 {
4574 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4641 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
4642 // Never report more than sim total capacity
4643 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4644 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4575 updateMessage.SimWideMaxPrims = simulatorCapacity; 4645 updateMessage.SimWideMaxPrims = simulatorCapacity;
4576 } 4646 }
4577 else 4647 else
@@ -4700,14 +4770,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4700 4770
4701 if (notifyCount > 0) 4771 if (notifyCount > 0)
4702 { 4772 {
4703 if (notifyCount > 32) 4773// if (notifyCount > 32)
4704 { 4774// {
4705 m_log.InfoFormat( 4775// m_log.InfoFormat(
4706 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4776// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4707 + " - a developer might want to investigate whether this is a hard limit", 32); 4777// + " - a developer might want to investigate whether this is a hard limit", 32);
4708 4778//
4709 notifyCount = 32; 4779// notifyCount = 32;
4710 } 4780// }
4711 4781
4712 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4782 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4713 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4783 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4762,9 +4832,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4762 { 4832 {
4763 ScenePresence presence = (ScenePresence)entity; 4833 ScenePresence presence = (ScenePresence)entity;
4764 4834
4835 position = presence.OffsetPosition;
4836 rotation = presence.Rotation;
4837
4838 if (presence.ParentID != 0)
4839 {
4840 SceneObjectPart part = m_scene.GetSceneObjectPart(presence.ParentID);
4841 if (part != null && part != part.ParentGroup.RootPart)
4842 {
4843 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4844 rotation = part.RotationOffset * presence.Rotation;
4845 }
4846 }
4847
4765 attachPoint = 0; 4848 attachPoint = 0;
4766 collisionPlane = presence.CollisionPlane; 4849 collisionPlane = presence.CollisionPlane;
4767 position = presence.OffsetPosition;
4768 velocity = presence.Velocity; 4850 velocity = presence.Velocity;
4769 acceleration = Vector3.Zero; 4851 acceleration = Vector3.Zero;
4770 4852
@@ -4774,7 +4856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4774// acceleration = new Vector3(1, 0, 0); 4856// acceleration = new Vector3(1, 0, 0);
4775 4857
4776 angularVelocity = Vector3.Zero; 4858 angularVelocity = Vector3.Zero;
4777 rotation = presence.Rotation;
4778 4859
4779 if (sendTexture) 4860 if (sendTexture)
4780 textureEntry = presence.Appearance.Texture.GetBytes(); 4861 textureEntry = presence.Appearance.Texture.GetBytes();
@@ -4879,13 +4960,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4879 4960
4880 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 4961 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
4881 { 4962 {
4963 Vector3 offsetPosition = data.OffsetPosition;
4964 Quaternion rotation = data.Rotation;
4965 uint parentID = data.ParentID;
4966
4967 if (parentID != 0)
4968 {
4969 SceneObjectPart part = m_scene.GetSceneObjectPart(parentID);
4970 if (part != null && part != part.ParentGroup.RootPart)
4971 {
4972 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
4973 rotation = part.RotationOffset * data.Rotation;
4974 parentID = part.ParentGroup.RootPart.LocalId;
4975 }
4976 }
4977
4882 byte[] objectData = new byte[76]; 4978 byte[] objectData = new byte[76];
4883 4979
4884 data.CollisionPlane.ToBytes(objectData, 0); 4980 data.CollisionPlane.ToBytes(objectData, 0);
4885 data.OffsetPosition.ToBytes(objectData, 16); 4981 offsetPosition.ToBytes(objectData, 16);
4886// data.Velocity.ToBytes(objectData, 28); 4982// data.Velocity.ToBytes(objectData, 28);
4887// data.Acceleration.ToBytes(objectData, 40); 4983// data.Acceleration.ToBytes(objectData, 40);
4888 data.Rotation.ToBytes(objectData, 52); 4984 rotation.ToBytes(objectData, 52);
4889 //data.AngularVelocity.ToBytes(objectData, 64); 4985 //data.AngularVelocity.ToBytes(objectData, 64);
4890 4986
4891 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 4987 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -4899,7 +4995,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4899 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 4995 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
4900 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 4996 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
4901 update.ObjectData = objectData; 4997 update.ObjectData = objectData;
4902 update.ParentID = data.ParentID; 4998 update.ParentID = parentID;
4903 update.PathCurve = 16; 4999 update.PathCurve = 16;
4904 update.PathScaleX = 100; 5000 update.PathScaleX = 100;
4905 update.PathScaleY = 100; 5001 update.PathScaleY = 100;
@@ -5240,6 +5336,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5240 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5336 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5241 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5337 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5242 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5338 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5339 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5243 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5340 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5244 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5341 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5245 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5342 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5306,6 +5403,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5306 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5403 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5307 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5404 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5308 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5405 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5406 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5309 5407
5310 AddGenericPacketHandler("autopilot", HandleAutopilot); 5408 AddGenericPacketHandler("autopilot", HandleAutopilot);
5311 } 5409 }
@@ -5341,6 +5439,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5341 (x.CameraLeftAxis != lastarg.CameraLeftAxis) || 5439 (x.CameraLeftAxis != lastarg.CameraLeftAxis) ||
5342 (x.CameraUpAxis != lastarg.CameraUpAxis) || 5440 (x.CameraUpAxis != lastarg.CameraUpAxis) ||
5343 (x.ControlFlags != lastarg.ControlFlags) || 5441 (x.ControlFlags != lastarg.ControlFlags) ||
5442 (x.ControlFlags != 0) ||
5344 (x.Far != lastarg.Far) || 5443 (x.Far != lastarg.Far) ||
5345 (x.Flags != lastarg.Flags) || 5444 (x.Flags != lastarg.Flags) ||
5346 (x.State != lastarg.State) || 5445 (x.State != lastarg.State) ||
@@ -5718,7 +5817,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5718 args.Channel = ch; 5817 args.Channel = ch;
5719 args.From = String.Empty; 5818 args.From = String.Empty;
5720 args.Message = Utils.BytesToString(msg); 5819 args.Message = Utils.BytesToString(msg);
5721 args.Type = ChatTypeEnum.Shout; 5820 args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance
5722 args.Position = new Vector3(); 5821 args.Position = new Vector3();
5723 args.Scene = Scene; 5822 args.Scene = Scene;
5724 args.Sender = this; 5823 args.Sender = this;
@@ -9763,7 +9862,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9763 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 9862 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9764 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 9863 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9765 UpdateMuteListEntry.MuteData.MuteType, 9864 UpdateMuteListEntry.MuteData.MuteType,
9766 UpdateMuteListEntry.AgentData.AgentID); 9865 UpdateMuteListEntry.MuteData.MuteFlags);
9767 return true; 9866 return true;
9768 } 9867 }
9769 return false; 9868 return false;
@@ -9778,8 +9877,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9778 { 9877 {
9779 handlerRemoveMuteListEntry(this, 9878 handlerRemoveMuteListEntry(this,
9780 RemoveMuteListEntry.MuteData.MuteID, 9879 RemoveMuteListEntry.MuteData.MuteID,
9781 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 9880 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9782 RemoveMuteListEntry.AgentData.AgentID);
9783 return true; 9881 return true;
9784 } 9882 }
9785 return false; 9883 return false;
@@ -9823,10 +9921,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9823 return false; 9921 return false;
9824 } 9922 }
9825 9923
9924 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
9925 {
9926 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
9927 (ChangeInventoryItemFlagsPacket)packet;
9928 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
9929 if (handlerChangeInventoryItemFlags != null)
9930 {
9931 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
9932 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
9933 return true;
9934 }
9935 return false;
9936 }
9937
9826 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 9938 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9827 { 9939 {
9828 return true; 9940 return true;
9829 } 9941 }
9942
9943 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
9944 {
9945 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
9946
9947 #region Packet Session and User Check
9948 if (m_checkPackets)
9949 {
9950 if (packet.AgentData.SessionID != SessionId ||
9951 packet.AgentData.AgentID != AgentId)
9952 return true;
9953 }
9954 #endregion
9955 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
9956 List<InventoryItemBase> items = new List<InventoryItemBase>();
9957 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
9958 {
9959 InventoryItemBase b = new InventoryItemBase();
9960 b.ID = n.OldItemID;
9961 b.Folder = n.OldFolderID;
9962 items.Add(b);
9963 }
9964
9965 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
9966 if (handlerMoveItemsAndLeaveCopy != null)
9967 {
9968 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
9969 }
9970
9971 return true;
9972 }
9830 9973
9831 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 9974 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9832 { 9975 {
@@ -10253,6 +10396,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10253 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10396 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10254 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10397 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10255 10398
10399 Scene scene = (Scene)m_scene;
10400 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10401 {
10402 ScenePresence p;
10403 if (scene.TryGetScenePresence(sender.AgentId, out p))
10404 {
10405 if (p.GodLevel >= 200)
10406 {
10407 groupProfileReply.GroupData.OpenEnrollment = true;
10408 groupProfileReply.GroupData.MembershipFee = 0;
10409 }
10410 }
10411 }
10412
10256 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10413 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10257 } 10414 }
10258 return true; 10415 return true;
@@ -10826,11 +10983,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10826 10983
10827 StartLure handlerStartLure = OnStartLure; 10984 StartLure handlerStartLure = OnStartLure;
10828 if (handlerStartLure != null) 10985 if (handlerStartLure != null)
10829 handlerStartLure(startLureRequest.Info.LureType, 10986 {
10830 Utils.BytesToString( 10987 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10831 startLureRequest.Info.Message), 10988 {
10832 startLureRequest.TargetData[0].TargetID, 10989 handlerStartLure(startLureRequest.Info.LureType,
10833 this); 10990 Utils.BytesToString(
10991 startLureRequest.Info.Message),
10992 startLureRequest.TargetData[i].TargetID,
10993 this);
10994 }
10995 }
10834 return true; 10996 return true;
10835 } 10997 }
10836 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 10998 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -10944,10 +11106,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10944 } 11106 }
10945 #endregion 11107 #endregion
10946 11108
10947 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11109 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
10948 if (handlerClassifiedGodDelete != null) 11110 if (handlerClassifiedGodDelete != null)
10949 handlerClassifiedGodDelete( 11111 handlerClassifiedGodDelete(
10950 classifiedGodDelete.Data.ClassifiedID, 11112 classifiedGodDelete.Data.ClassifiedID,
11113 classifiedGodDelete.Data.QueryID,
10951 this); 11114 this);
10952 return true; 11115 return true;
10953 } 11116 }
@@ -11330,183 +11493,270 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11330// } 11493// }
11331 11494
11332 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 11495 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation;
11496 UpdateVector handlerUpdatePrimGroupScale;
11497
11498 Quaternion arot;
11499 Vector3 ascale;
11500 Vector3 apos;
11501/*ubit from ll JIRA:
11502 * 0x01 position
11503 * 0x02 rotation
11504 * 0x04 scale
11505
11506 * 0x08 LINK_SET
11507 * 0x10 UNIFORM for scale
11508 */
11509
11333 11510
11334 switch (block.Type) 11511 switch (block.Type)
11335 { 11512 {
11336 case 1: 11513 case 1: //change position sp
11337 Vector3 pos1 = new Vector3(block.Data, 0); 11514 apos = new Vector3(block.Data, 0);
11338 11515
11339 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11516 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11340 if (handlerUpdatePrimSinglePosition != null) 11517 if (handlerUpdatePrimSinglePosition != null)
11341 { 11518 {
11519 part.StoreUndoState();
11520 part.IgnoreUndoUpdate = true;
11521
11342 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11522 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11343 handlerUpdatePrimSinglePosition(localId, pos1, this); 11523 handlerUpdatePrimSinglePosition(localId, apos, this);
11524
11525 part.IgnoreUndoUpdate = false;
11344 } 11526 }
11345 break; 11527 break;
11346 11528
11347 case 2: 11529 case 2: // rotation sp
11348 Quaternion rot1 = new Quaternion(block.Data, 0, true); 11530 arot = new Quaternion(block.Data, 0, true);
11349 11531
11350 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 11532 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation;
11351 if (handlerUpdatePrimSingleRotation != null) 11533 if (handlerUpdatePrimSingleRotation != null)
11352 { 11534 {
11353 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W); 11535 part.StoreUndoState();
11354 handlerUpdatePrimSingleRotation(localId, rot1, this); 11536 part.IgnoreUndoUpdate = true;
11537
11538 handlerUpdatePrimSingleRotation(localId, arot, this);
11539
11540 part.IgnoreUndoUpdate = false;
11355 } 11541 }
11356 break; 11542 break;
11357 11543
11358 case 3: 11544 case 3: // position plus rotation
11359 Vector3 rotPos = new Vector3(block.Data, 0); 11545 apos = new Vector3(block.Data, 0);
11360 Quaternion rot2 = new Quaternion(block.Data, 12, true); 11546 arot = new Quaternion(block.Data, 12, true);
11361 11547
11362 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 11548 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition;
11363 if (handlerUpdatePrimSingleRotationPosition != null) 11549 if (handlerUpdatePrimSingleRotationPosition != null)
11364 { 11550 {
11365 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z); 11551 part.StoreUndoState();
11366 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W); 11552 part.IgnoreUndoUpdate = true;
11367 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this); 11553
11554 handlerUpdatePrimSingleRotationPosition(localId, arot, apos, this);
11555
11556 part.IgnoreUndoUpdate = false;
11368 } 11557 }
11369 break; 11558 break;
11370 11559
11371 case 4: 11560 case 4: // scale sp
11372 case 20: 11561 case 0x14: // uniform scale sp
11373 Vector3 scale4 = new Vector3(block.Data, 0); 11562 ascale = new Vector3(block.Data, 0);
11374 11563
11375 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 11564 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale;
11376 if (handlerUpdatePrimScale != null) 11565 if (handlerUpdatePrimScale != null)
11377 { 11566 {
11378 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z); 11567 part.StoreUndoState();
11379 handlerUpdatePrimScale(localId, scale4, this); 11568 part.IgnoreUndoUpdate = true;
11569
11570 handlerUpdatePrimScale(localId, ascale, this);
11571
11572 part.IgnoreUndoUpdate = false;
11380 } 11573 }
11381 break; 11574 break;
11382 11575
11383 case 5: 11576 case 5: // scale and position sp
11384 Vector3 scale1 = new Vector3(block.Data, 12); 11577 apos = new Vector3(block.Data, 0);
11385 Vector3 pos11 = new Vector3(block.Data, 0); 11578 ascale = new Vector3(block.Data, 12);
11579
11386 11580
11387 handlerUpdatePrimScale = OnUpdatePrimScale; 11581 handlerUpdatePrimScale = OnUpdatePrimScale;
11388 if (handlerUpdatePrimScale != null) 11582 if (handlerUpdatePrimScale != null)
11389 { 11583 {
11390 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11584 part.StoreUndoState();
11391 handlerUpdatePrimScale(localId, scale1, this); 11585 part.IgnoreUndoUpdate = true;
11586
11587 handlerUpdatePrimScale(localId, ascale, this);
11588
11589 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11590
11591 if (handlerUpdatePrimSinglePosition != null)
11592 {
11593 handlerUpdatePrimSinglePosition(localId, apos, this);
11594 }
11595 part.IgnoreUndoUpdate = false;
11596 }
11597 break;
11598
11599 case 0x15: //uniform scale and position
11600 apos = new Vector3(block.Data, 0);
11601 ascale = new Vector3(block.Data, 12);
11602
11603
11604 handlerUpdatePrimScale = OnUpdatePrimScale;
11605 if (handlerUpdatePrimScale != null)
11606 {
11607 part.StoreUndoState(false);
11608 part.IgnoreUndoUpdate = true;
11392 11609
11610 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11611 handlerUpdatePrimScale(localId, ascale, this);
11393 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11612 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11394 if (handlerUpdatePrimSinglePosition != null) 11613 if (handlerUpdatePrimSinglePosition != null)
11395 { 11614 {
11396 handlerUpdatePrimSinglePosition(localId, pos11, this); 11615 handlerUpdatePrimSinglePosition(localId, apos, this);
11397 } 11616 }
11617
11618 part.IgnoreUndoUpdate = false;
11398 } 11619 }
11399 break; 11620 break;
11400 11621
11401 case 9: 11622// now group related (bit 4)
11402 Vector3 pos2 = new Vector3(block.Data, 0); 11623 case 9: //( 8 + 1 )group position
11624 apos = new Vector3(block.Data, 0);
11403 11625
11404 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 11626 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition;
11405 11627
11406 if (handlerUpdateVector != null) 11628 if (handlerUpdateVector != null)
11407 { 11629 {
11408 handlerUpdateVector(localId, pos2, this); 11630 part.StoreUndoState(true);
11631 part.IgnoreUndoUpdate = true;
11632
11633 handlerUpdateVector(localId, apos, this);
11634
11635 part.IgnoreUndoUpdate = false;
11409 } 11636 }
11410 break; 11637 break;
11411 11638
11412 case 10: 11639 case 0x0A: // (8 + 2) group rotation
11413 Quaternion rot3 = new Quaternion(block.Data, 0, true); 11640 arot = new Quaternion(block.Data, 0, true);
11414 11641
11415 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 11642 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation;
11416 if (handlerUpdatePrimRotation != null) 11643 if (handlerUpdatePrimRotation != null)
11417 { 11644 {
11418 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W); 11645 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11419 handlerUpdatePrimRotation(localId, rot3, this); 11646 part.StoreUndoState(true);
11647 part.IgnoreUndoUpdate = true;
11648
11649 handlerUpdatePrimRotation(localId, arot, this);
11650
11651 part.IgnoreUndoUpdate = false;
11420 } 11652 }
11421 break; 11653 break;
11422 11654
11423 case 11: 11655 case 0x0B: //( 8 + 2 + 1) group rotation and position
11424 Vector3 pos3 = new Vector3(block.Data, 0); 11656 apos = new Vector3(block.Data, 0);
11425 Quaternion rot4 = new Quaternion(block.Data, 12, true); 11657 arot = new Quaternion(block.Data, 12, true);
11426 11658
11427 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 11659 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation;
11428 if (handlerUpdatePrimGroupRotation != null) 11660 if (handlerUpdatePrimGroupRotation != null)
11429 { 11661 {
11430 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11662 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11431 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W); 11663 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11432 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this); 11664 part.StoreUndoState(true);
11665 part.IgnoreUndoUpdate = true;
11666
11667 handlerUpdatePrimGroupRotation(localId, apos, arot, this);
11668
11669 part.IgnoreUndoUpdate = false;
11433 } 11670 }
11434 break; 11671 break;
11435 case 12:
11436 case 28:
11437 Vector3 scale7 = new Vector3(block.Data, 0);
11438 11672
11439 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11673 case 0x0C: // (8 + 4) group scale
11440 if (handlerUpdatePrimGroupScale != null) 11674 // only afects root prim and only sent by viewer editor object tab scaling
11675 // mouse edition only allows uniform scaling
11676 // SL MAY CHANGE THIS in viewers
11677
11678 ascale = new Vector3(block.Data, 0);
11679
11680 handlerUpdatePrimScale = OnUpdatePrimScale;
11681 if (handlerUpdatePrimScale != null)
11441 { 11682 {
11442 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z); 11683 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11443 handlerUpdatePrimGroupScale(localId, scale7, this); 11684 part.StoreUndoState(false); // <- SL Exception make it apply to root prim and not group
11685 part.IgnoreUndoUpdate = true;
11686
11687 handlerUpdatePrimScale(localId, ascale, this);
11688
11689 part.IgnoreUndoUpdate = false;
11444 } 11690 }
11445 break; 11691 break;
11446 11692
11447 case 13: 11693 case 0x0D: //(8 + 4 + 1) group scale and position
11448 Vector3 scale2 = new Vector3(block.Data, 12); 11694 // exception as above
11449 Vector3 pos4 = new Vector3(block.Data, 0);
11450 11695
11696 apos = new Vector3(block.Data, 0);
11697 ascale = new Vector3(block.Data, 12);
11698
11451 handlerUpdatePrimScale = OnUpdatePrimScale; 11699 handlerUpdatePrimScale = OnUpdatePrimScale;
11452 if (handlerUpdatePrimScale != null) 11700 if (handlerUpdatePrimScale != null)
11453 { 11701 {
11454 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11702 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11455 handlerUpdatePrimScale(localId, scale2, this); 11703 part.StoreUndoState(false); // <- make it apply to root prim and not group
11704 part.IgnoreUndoUpdate = true;
11705
11706 handlerUpdatePrimScale(localId, ascale, this);
11456 11707
11457 // Change the position based on scale (for bug number 246) 11708 // Change the position based on scale (for bug number 246)
11458 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11709 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition;
11459 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11710 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11460 if (handlerUpdatePrimSinglePosition != null) 11711 if (handlerUpdatePrimSinglePosition != null)
11461 { 11712 {
11462 handlerUpdatePrimSinglePosition(localId, pos4, this); 11713 handlerUpdatePrimSinglePosition(localId, apos, this);
11463 } 11714 }
11715
11716 part.IgnoreUndoUpdate = false;
11464 } 11717 }
11465 break; 11718 break;
11466 11719
11467 case 29: 11720 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
11468 Vector3 scale5 = new Vector3(block.Data, 12); 11721 ascale = new Vector3(block.Data, 0);
11469 Vector3 pos5 = new Vector3(block.Data, 0);
11470 11722
11471 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11723 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
11472 if (handlerUpdatePrimGroupScale != null) 11724 if (handlerUpdatePrimGroupScale != null)
11473 { 11725 {
11474 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11726 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11475 part.StoreUndoState(true); 11727 part.StoreUndoState(true);
11476 part.IgnoreUndoUpdate = true; 11728 part.IgnoreUndoUpdate = true;
11477 handlerUpdatePrimGroupScale(localId, scale5, this);
11478 handlerUpdateVector = OnUpdatePrimGroupPosition;
11479 11729
11480 if (handlerUpdateVector != null) 11730 handlerUpdatePrimGroupScale(localId, ascale, this);
11481 {
11482 handlerUpdateVector(localId, pos5, this);
11483 }
11484 11731
11485 part.IgnoreUndoUpdate = false; 11732 part.IgnoreUndoUpdate = false;
11486 } 11733 }
11487
11488 break; 11734 break;
11489 11735
11490 case 21: 11736 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
11491 Vector3 scale6 = new Vector3(block.Data, 12); 11737 apos = new Vector3(block.Data, 0);
11492 Vector3 pos6 = new Vector3(block.Data, 0); 11738 ascale = new Vector3(block.Data, 12);
11739
11493 11740
11494 handlerUpdatePrimScale = OnUpdatePrimScale; 11741 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale;
11495 if (handlerUpdatePrimScale != null) 11742 if (handlerUpdatePrimGroupScale != null)
11496 { 11743 {
11497 part.StoreUndoState(false); 11744 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11745 part.StoreUndoState(true);
11498 part.IgnoreUndoUpdate = true; 11746 part.IgnoreUndoUpdate = true;
11499 11747
11500 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11748 handlerUpdatePrimGroupScale(localId, ascale, this);
11501 handlerUpdatePrimScale(localId, scale6, this); 11749
11502 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11750 handlerUpdateVector = OnUpdatePrimGroupPosition;
11503 if (handlerUpdatePrimSinglePosition != null) 11751
11752 if (handlerUpdateVector != null)
11504 { 11753 {
11505 handlerUpdatePrimSinglePosition(localId, pos6, this); 11754 handlerUpdateVector(localId, apos, this);
11506 } 11755 }
11507 11756
11508 part.IgnoreUndoUpdate = false; 11757 part.IgnoreUndoUpdate = false;
11509 } 11758 }
11759
11510 break; 11760 break;
11511 11761
11512 default: 11762 default:
@@ -11516,6 +11766,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11516 11766
11517// for (int j = 0; j < parts.Length; j++) 11767// for (int j = 0; j < parts.Length; j++)
11518// parts[j].IgnoreUndoUpdate = false; 11768// parts[j].IgnoreUndoUpdate = false;
11769
11519 } 11770 }
11520 } 11771 }
11521 } 11772 }
@@ -11975,7 +12226,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11975 12226
11976// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); 12227// m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID);
11977 12228
12229
12230 //Note, the bool returned from the below function is useless since it is always false.
11978 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12231 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12232
11979 } 12233 }
11980 12234
11981 /// <summary> 12235 /// <summary>