aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs3
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs1500
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs115
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs229
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs4
5 files changed, 1234 insertions, 617 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
index afbe56b..3995620 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs
@@ -234,6 +234,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
234 m_stopPacket = TexturePacketCount(); 234 m_stopPacket = TexturePacketCount();
235 } 235 }
236 236
237 //Give them at least two packets, to play nice with some broken viewers (SL also behaves this way)
238 if (m_stopPacket == 1 && m_layers[0].End > FIRST_PACKET_SIZE) m_stopPacket++;
239
237 m_currentPacket = StartPacket; 240 m_currentPacket = StartPacket;
238 } 241 }
239 } 242 }
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 0ccd69a..bae41fb 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -99,6 +99,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
99 public event AvatarPickerRequest OnAvatarPickerRequest; 99 public event AvatarPickerRequest OnAvatarPickerRequest;
100 public event StartAnim OnStartAnim; 100 public event StartAnim OnStartAnim;
101 public event StopAnim OnStopAnim; 101 public event StopAnim OnStopAnim;
102 public event ChangeAnim OnChangeAnim;
102 public event Action<IClientAPI> OnRequestAvatarsData; 103 public event Action<IClientAPI> OnRequestAvatarsData;
103 public event LinkObjects OnLinkObjects; 104 public event LinkObjects OnLinkObjects;
104 public event DelinkObjects OnDelinkObjects; 105 public event DelinkObjects OnDelinkObjects;
@@ -126,6 +127,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
126 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily; 127 public event RequestObjectPropertiesFamily OnRequestObjectPropertiesFamily;
127 public event UpdatePrimFlags OnUpdatePrimFlags; 128 public event UpdatePrimFlags OnUpdatePrimFlags;
128 public event UpdatePrimTexture OnUpdatePrimTexture; 129 public event UpdatePrimTexture OnUpdatePrimTexture;
130 public event ClientChangeObject onClientChangeObject;
129 public event UpdateVector OnUpdatePrimGroupPosition; 131 public event UpdateVector OnUpdatePrimGroupPosition;
130 public event UpdateVector OnUpdatePrimSinglePosition; 132 public event UpdateVector OnUpdatePrimSinglePosition;
131 public event UpdatePrimRotation OnUpdatePrimGroupRotation; 133 public event UpdatePrimRotation OnUpdatePrimGroupRotation;
@@ -159,6 +161,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
159 public event RequestTaskInventory OnRequestTaskInventory; 161 public event RequestTaskInventory OnRequestTaskInventory;
160 public event UpdateInventoryItem OnUpdateInventoryItem; 162 public event UpdateInventoryItem OnUpdateInventoryItem;
161 public event CopyInventoryItem OnCopyInventoryItem; 163 public event CopyInventoryItem OnCopyInventoryItem;
164 public event MoveItemsAndLeaveCopy OnMoveItemsAndLeaveCopy;
162 public event MoveInventoryItem OnMoveInventoryItem; 165 public event MoveInventoryItem OnMoveInventoryItem;
163 public event RemoveInventoryItem OnRemoveInventoryItem; 166 public event RemoveInventoryItem OnRemoveInventoryItem;
164 public event RemoveInventoryFolder OnRemoveInventoryFolder; 167 public event RemoveInventoryFolder OnRemoveInventoryFolder;
@@ -257,7 +260,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 public event ClassifiedInfoRequest OnClassifiedInfoRequest; 260 public event ClassifiedInfoRequest OnClassifiedInfoRequest;
258 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate; 261 public event ClassifiedInfoUpdate OnClassifiedInfoUpdate;
259 public event ClassifiedDelete OnClassifiedDelete; 262 public event ClassifiedDelete OnClassifiedDelete;
260 public event ClassifiedDelete OnClassifiedGodDelete; 263 public event ClassifiedGodDelete OnClassifiedGodDelete;
261 public event EventNotificationAddRequest OnEventNotificationAddRequest; 264 public event EventNotificationAddRequest OnEventNotificationAddRequest;
262 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest; 265 public event EventNotificationRemoveRequest OnEventNotificationRemoveRequest;
263 public event EventGodDelete OnEventGodDelete; 266 public event EventGodDelete OnEventGodDelete;
@@ -288,10 +291,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
288 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest; 291 public event GroupVoteHistoryRequest OnGroupVoteHistoryRequest;
289 public event SimWideDeletesDelegate OnSimWideDeletes; 292 public event SimWideDeletesDelegate OnSimWideDeletes;
290 public event SendPostcard OnSendPostcard; 293 public event SendPostcard OnSendPostcard;
294 public event ChangeInventoryItemFlags OnChangeInventoryItemFlags;
291 public event MuteListEntryUpdate OnUpdateMuteListEntry; 295 public event MuteListEntryUpdate OnUpdateMuteListEntry;
292 public event MuteListEntryRemove OnRemoveMuteListEntry; 296 public event MuteListEntryRemove OnRemoveMuteListEntry;
293 public event GodlikeMessage onGodlikeMessage; 297 public event GodlikeMessage onGodlikeMessage;
294 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate; 298 public event GodUpdateRegionInfoUpdate OnGodUpdateRegionInfoUpdate;
299 public event GenericCall2 OnUpdateThrottles;
295 300
296 #endregion Events 301 #endregion Events
297 302
@@ -326,6 +331,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
326 private Prioritizer m_prioritizer; 331 private Prioritizer m_prioritizer;
327 private bool m_disableFacelights = false; 332 private bool m_disableFacelights = false;
328 333
334 private bool m_VelocityInterpolate = false;
335 private const uint MaxTransferBytesPerPacket = 600;
336
337
329 /// <value> 338 /// <value>
330 /// List used in construction of data blocks for an object update packet. This is to stop us having to 339 /// List used in construction of data blocks for an object update packet. This is to stop us having to
331 /// continually recreate it. 340 /// continually recreate it.
@@ -337,14 +346,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 346 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
338 /// ownerless phantom. 347 /// ownerless phantom.
339 /// 348 ///
340 /// All manipulation of this set has to occur under a lock 349 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
341 /// 350 ///
342 /// </value> 351 /// </value>
343 protected HashSet<uint> m_killRecord; 352// protected HashSet<uint> m_killRecord;
344 353
345// protected HashSet<uint> m_attachmentsSent; 354// protected HashSet<uint> m_attachmentsSent;
346 355
347 private int m_moneyBalance; 356 private int m_moneyBalance;
357 private bool m_deliverPackets = true;
348 private int m_animationSequenceNumber = 1; 358 private int m_animationSequenceNumber = 1;
349 private bool m_SendLogoutPacketWhenClosing = true; 359 private bool m_SendLogoutPacketWhenClosing = true;
350 360
@@ -391,6 +401,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
391 get { return m_startpos; } 401 get { return m_startpos; }
392 set { m_startpos = value; } 402 set { m_startpos = value; }
393 } 403 }
404 public bool DeliverPackets
405 {
406 get { return m_deliverPackets; }
407 set {
408 m_deliverPackets = value;
409 m_udpClient.m_deliverPackets = value;
410 }
411 }
394 public UUID AgentId { get { return m_agentId; } } 412 public UUID AgentId { get { return m_agentId; } }
395 public ISceneAgent SceneAgent { get; set; } 413 public ISceneAgent SceneAgent { get; set; }
396 public UUID ActiveGroupId { get { return m_activeGroupID; } } 414 public UUID ActiveGroupId { get { return m_activeGroupID; } }
@@ -442,6 +460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
442 } 460 }
443 461
444 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } 462 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
463
445 464
446 #endregion Properties 465 #endregion Properties
447 466
@@ -468,7 +487,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
468 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 487 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
469 m_entityProps = new PriorityQueue(m_scene.Entities.Count); 488 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
470 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 489 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
471 m_killRecord = new HashSet<uint>(); 490// m_killRecord = new HashSet<uint>();
472// m_attachmentsSent = new HashSet<uint>(); 491// m_attachmentsSent = new HashSet<uint>();
473 492
474 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 493 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
@@ -498,12 +517,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
498 517
499 #region Client Methods 518 #region Client Methods
500 519
520
521 /// <summary>
522 /// Close down the client view
523 /// </summary>
501 public void Close() 524 public void Close()
502 { 525 {
503 Close(false); 526 Close(true, false);
504 } 527 }
505 528
506 public void Close(bool force) 529 public void Close(bool sendStop, bool force)
507 { 530 {
508 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 531 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g.
509 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. 532 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
@@ -515,7 +538,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
515 return; 538 return;
516 539
517 IsActive = false; 540 IsActive = false;
518 CloseWithoutChecks(); 541 CloseWithoutChecks(sendStop);
519 } 542 }
520 } 543 }
521 544
@@ -528,12 +551,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
528 /// 551 ///
529 /// Callers must lock ClosingSyncLock before calling. 552 /// Callers must lock ClosingSyncLock before calling.
530 /// </remarks> 553 /// </remarks>
531 public void CloseWithoutChecks() 554 public void CloseWithoutChecks(bool sendStop)
532 { 555 {
533 m_log.DebugFormat( 556 m_log.DebugFormat(
534 "[CLIENT]: Close has been called for {0} attached to scene {1}", 557 "[CLIENT]: Close has been called for {0} attached to scene {1}",
535 Name, m_scene.RegionInfo.RegionName); 558 Name, m_scene.RegionInfo.RegionName);
536 559
560 if (sendStop)
561 {
562 // Send the STOP packet
563 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
564 OutPacket(disable, ThrottleOutPacketType.Unknown);
565 }
566
537 // Shutdown the image manager 567 // Shutdown the image manager
538 ImageManager.Close(); 568 ImageManager.Close();
539 569
@@ -556,6 +586,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
556 // Disable UDP handling for this client 586 // Disable UDP handling for this client
557 m_udpClient.Shutdown(); 587 m_udpClient.Shutdown();
558 588
589
559 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 590 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
560 //GC.Collect(); 591 //GC.Collect();
561 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true)); 592 //m_log.InfoFormat("[CLIENTVIEW] Memory post GC {0}", System.GC.GetTotalMemory(true));
@@ -791,7 +822,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
791 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 822 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
792 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 823 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
793 824
794 OutPacket(handshake, ThrottleOutPacketType.Task); 825// OutPacket(handshake, ThrottleOutPacketType.Task);
826 // use same as MoveAgentIntoRegion (both should be task )
827 OutPacket(handshake, ThrottleOutPacketType.Unknown);
795 } 828 }
796 829
797 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 830 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
@@ -831,7 +864,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
831 reply.ChatData.OwnerID = ownerID; 864 reply.ChatData.OwnerID = ownerID;
832 reply.ChatData.SourceID = fromAgentID; 865 reply.ChatData.SourceID = fromAgentID;
833 866
834 OutPacket(reply, ThrottleOutPacketType.Task); 867 OutPacket(reply, ThrottleOutPacketType.Unknown);
835 } 868 }
836 869
837 /// <summary> 870 /// <summary>
@@ -864,32 +897,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
864 msg.MessageBlock.Message = Util.StringToBytes1024(im.message); 897 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
865 msg.MessageBlock.BinaryBucket = im.binaryBucket; 898 msg.MessageBlock.BinaryBucket = im.binaryBucket;
866 899
867 if (im.message.StartsWith("[grouptest]")) 900 OutPacket(msg, ThrottleOutPacketType.Task);
868 { // this block is test code for implementing group IM - delete when group IM is finished
869 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
870 if (eq != null)
871 {
872 im.dialog = 17;
873
874 //eq.ChatterboxInvitation(
875 // new UUID("00000000-68f9-1111-024e-222222111123"),
876 // "OpenSimulator Testing", im.fromAgentID, im.message, im.toAgentID, im.fromAgentName, im.dialog, 0,
877 // false, 0, new Vector3(), 1, im.imSessionID, im.fromGroup, im.binaryBucket);
878
879 eq.ChatterboxInvitation(
880 new UUID("00000000-68f9-1111-024e-222222111123"),
881 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
882 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
883
884 eq.ChatterBoxSessionAgentListUpdates(
885 new UUID("00000000-68f9-1111-024e-222222111123"),
886 new UUID(im.fromAgentID), new UUID(im.toAgentID), false, false, false);
887 }
888
889 Console.WriteLine("SendInstantMessage: " + msg);
890 }
891 else
892 OutPacket(msg, ThrottleOutPacketType.Task);
893 } 901 }
894 } 902 }
895 903
@@ -1117,6 +1125,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1117 public virtual void SendLayerData(float[] map) 1125 public virtual void SendLayerData(float[] map)
1118 { 1126 {
1119 Util.FireAndForget(DoSendLayerData, map); 1127 Util.FireAndForget(DoSendLayerData, map);
1128
1129 // Send it sync, and async. It's not that much data
1130 // and it improves user experience just so much!
1131 DoSendLayerData(map);
1120 } 1132 }
1121 1133
1122 /// <summary> 1134 /// <summary>
@@ -1129,16 +1141,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1129 1141
1130 try 1142 try
1131 { 1143 {
1132 //for (int y = 0; y < 16; y++) 1144 for (int y = 0; y < 16; y++)
1133 //{ 1145 {
1134 // for (int x = 0; x < 16; x++) 1146 for (int x = 0; x < 16; x+=4)
1135 // { 1147 {
1136 // SendLayerData(x, y, map); 1148 SendLayerPacket(x, y, map);
1137 // } 1149 }
1138 //} 1150 }
1139
1140 // Send LayerData in a spiral pattern. Fun!
1141 SendLayerTopRight(map, 0, 0, 15, 15);
1142 } 1151 }
1143 catch (Exception e) 1152 catch (Exception e)
1144 { 1153 {
@@ -1146,51 +1155,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1146 } 1155 }
1147 } 1156 }
1148 1157
1149 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1150 {
1151 // Row
1152 for (int i = x1; i <= x2; i++)
1153 SendLayerData(i, y1, map);
1154
1155 // Column
1156 for (int j = y1 + 1; j <= y2; j++)
1157 SendLayerData(x2, j, map);
1158
1159 if (x2 - x1 > 0)
1160 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1161 }
1162
1163 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1164 {
1165 // Row in reverse
1166 for (int i = x2; i >= x1; i--)
1167 SendLayerData(i, y2, map);
1168
1169 // Column in reverse
1170 for (int j = y2 - 1; j >= y1; j--)
1171 SendLayerData(x1, j, map);
1172
1173 if (x2 - x1 > 0)
1174 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1175 }
1176
1177 /// <summary> 1158 /// <summary>
1178 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1159 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1179 /// </summary> 1160 /// </summary>
1180 /// <param name="map">heightmap</param> 1161 /// <param name="map">heightmap</param>
1181 /// <param name="px">X coordinate for patches 0..12</param> 1162 /// <param name="px">X coordinate for patches 0..12</param>
1182 /// <param name="py">Y coordinate for patches 0..15</param> 1163 /// <param name="py">Y coordinate for patches 0..15</param>
1183 // private void SendLayerPacket(float[] map, int y, int x) 1164 private void SendLayerPacket(int x, int y, float[] map)
1184 // { 1165 {
1185 // int[] patches = new int[4]; 1166 int[] patches = new int[4];
1186 // patches[0] = x + 0 + y * 16; 1167 patches[0] = x + 0 + y * 16;
1187 // patches[1] = x + 1 + y * 16; 1168 patches[1] = x + 1 + y * 16;
1188 // patches[2] = x + 2 + y * 16; 1169 patches[2] = x + 2 + y * 16;
1189 // patches[3] = x + 3 + y * 16; 1170 patches[3] = x + 3 + y * 16;
1190 1171
1191 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1172 float[] heightmap = (map.Length == 65536) ?
1192 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1173 map :
1193 // } 1174 LLHeightFieldMoronize(map);
1175
1176 try
1177 {
1178 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1179 OutPacket(layerpack, ThrottleOutPacketType.Land);
1180 }
1181 catch
1182 {
1183 for (int px = x ; px < x + 4 ; px++)
1184 SendLayerData(px, y, map);
1185 }
1186 }
1194 1187
1195 /// <summary> 1188 /// <summary>
1196 /// Sends a specified patch to a client 1189 /// Sends a specified patch to a client
@@ -1210,7 +1203,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1210 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1203 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1211 layerpack.Header.Reliable = true; 1204 layerpack.Header.Reliable = true;
1212 1205
1213 OutPacket(layerpack, ThrottleOutPacketType.Land); 1206 OutPacket(layerpack, ThrottleOutPacketType.Task);
1214 } 1207 }
1215 catch (Exception e) 1208 catch (Exception e)
1216 { 1209 {
@@ -1573,7 +1566,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1573 1566
1574 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1567 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1575 { 1568 {
1576// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1569// foreach (uint id in localIDs)
1570// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1577 1571
1578 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1572 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1579 // TODO: don't create new blocks if recycling an old packet 1573 // TODO: don't create new blocks if recycling an old packet
@@ -1595,17 +1589,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1595 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race 1589 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1596 // condition where a kill can be processed before an out-of-date update for the same object. 1590 // condition where a kill can be processed before an out-of-date update for the same object.
1597 // ProcessEntityUpdates() also takes the m_killRecord lock. 1591 // ProcessEntityUpdates() also takes the m_killRecord lock.
1598 lock (m_killRecord) 1592// lock (m_killRecord)
1599 { 1593// {
1600 foreach (uint localID in localIDs) 1594// foreach (uint localID in localIDs)
1601 m_killRecord.Add(localID); 1595// m_killRecord.Add(localID);
1602 1596
1603 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1597 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1604 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1598 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1605 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1599 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1606 // scene objects in a viewer until that viewer is relogged in. 1600 // scene objects in a viewer until that viewer is relogged in.
1607 OutPacket(kill, ThrottleOutPacketType.Task); 1601 OutPacket(kill, ThrottleOutPacketType.Task);
1608 } 1602// }
1609 } 1603 }
1610 } 1604 }
1611 1605
@@ -2063,9 +2057,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2063 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2057 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2064 } 2058 }
2065 2059
2066 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2067 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2060 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2068 { 2061 {
2062 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2063 }
2064
2065 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2066 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2067 {
2069 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; 2068 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
2070 2069
2071 UpdateCreateInventoryItemPacket InventoryReply 2070 UpdateCreateInventoryItemPacket InventoryReply
@@ -2075,6 +2074,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2075 // TODO: don't create new blocks if recycling an old packet 2074 // TODO: don't create new blocks if recycling an old packet
2076 InventoryReply.AgentData.AgentID = AgentId; 2075 InventoryReply.AgentData.AgentID = AgentId;
2077 InventoryReply.AgentData.SimApproved = true; 2076 InventoryReply.AgentData.SimApproved = true;
2077 InventoryReply.AgentData.TransactionID = transactionID;
2078 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2078 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2079 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2079 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2080 InventoryReply.InventoryData[0].ItemID = Item.ID; 2080 InventoryReply.InventoryData[0].ItemID = Item.ID;
@@ -2144,16 +2144,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2144 replytask.InventoryData.TaskID = taskID; 2144 replytask.InventoryData.TaskID = taskID;
2145 replytask.InventoryData.Serial = serial; 2145 replytask.InventoryData.Serial = serial;
2146 replytask.InventoryData.Filename = fileName; 2146 replytask.InventoryData.Filename = fileName;
2147 OutPacket(replytask, ThrottleOutPacketType.Asset); 2147 OutPacket(replytask, ThrottleOutPacketType.Task);
2148 } 2148 }
2149 2149
2150 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2150 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2151 { 2151 {
2152 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2153 if (isTaskInventory)
2154 type = ThrottleOutPacketType.Task;
2155
2152 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2156 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2153 sendXfer.XferID.ID = xferID; 2157 sendXfer.XferID.ID = xferID;
2154 sendXfer.XferID.Packet = packet; 2158 sendXfer.XferID.Packet = packet;
2155 sendXfer.DataPacket.Data = data; 2159 sendXfer.DataPacket.Data = data;
2156 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2160 OutPacket(sendXfer, type);
2157 } 2161 }
2158 2162
2159 public void SendAbortXferPacket(ulong xferID) 2163 public void SendAbortXferPacket(ulong xferID)
@@ -2335,6 +2339,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2335 OutPacket(sound, ThrottleOutPacketType.Task); 2339 OutPacket(sound, ThrottleOutPacketType.Task);
2336 } 2340 }
2337 2341
2342 public void SendTransferAbort(TransferRequestPacket transferRequest)
2343 {
2344 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2345 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2346 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2347 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2348 OutPacket(abort, ThrottleOutPacketType.Task);
2349 }
2350
2338 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2351 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2339 { 2352 {
2340 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2353 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2627,6 +2640,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2627 } 2640 }
2628 } 2641 }
2629 2642
2643 public void SendPartPhysicsProprieties(ISceneEntity entity)
2644 {
2645 SceneObjectPart part = (SceneObjectPart)entity;
2646 if (part != null && AgentId != UUID.Zero)
2647 {
2648 try
2649 {
2650 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2651 if (eq != null)
2652 {
2653 uint localid = part.LocalId;
2654 byte physshapetype = part.PhysicsShapeType;
2655 float density = part.Density;
2656 float friction = part.Friction;
2657 float bounce = part.Bounciness;
2658 float gravmod = part.GravityModifier;
2659
2660 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2661 }
2662 }
2663 catch (Exception ex)
2664 {
2665 m_log.Error("Unable to send part Physics Proprieties - exception: " + ex.ToString());
2666 }
2667 part.UpdatePhysRequired = false;
2668 }
2669 }
2670
2671
2630 2672
2631 public void SendGroupNameReply(UUID groupLLUID, string GroupName) 2673 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2632 { 2674 {
@@ -2685,8 +2727,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2685 req.AssetInf.ID, req.AssetInf.Metadata.ContentType); 2727 req.AssetInf.ID, req.AssetInf.Metadata.ContentType);
2686 return; 2728 return;
2687 } 2729 }
2730 int WearableOut = 0;
2731 bool isWearable = false;
2688 2732
2689 //m_log.Debug("sending asset " + req.RequestAssetID); 2733 if (req.AssetInf != null)
2734 isWearable =
2735 ((AssetType) req.AssetInf.Type ==
2736 AssetType.Bodypart || (AssetType) req.AssetInf.Type == AssetType.Clothing);
2737
2738
2739 //m_log.Debug("sending asset " + req.RequestAssetID + ", iswearable: " + isWearable);
2740
2741
2742 //if (isWearable)
2743 // m_log.Debug((AssetType)req.AssetInf.Type);
2744
2690 TransferInfoPacket Transfer = new TransferInfoPacket(); 2745 TransferInfoPacket Transfer = new TransferInfoPacket();
2691 Transfer.TransferInfo.ChannelType = 2; 2746 Transfer.TransferInfo.ChannelType = 2;
2692 Transfer.TransferInfo.Status = 0; 2747 Transfer.TransferInfo.Status = 0;
@@ -2708,7 +2763,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2708 Transfer.TransferInfo.Size = req.AssetInf.Data.Length; 2763 Transfer.TransferInfo.Size = req.AssetInf.Data.Length;
2709 Transfer.TransferInfo.TransferID = req.TransferRequestID; 2764 Transfer.TransferInfo.TransferID = req.TransferRequestID;
2710 Transfer.Header.Zerocoded = true; 2765 Transfer.Header.Zerocoded = true;
2711 OutPacket(Transfer, ThrottleOutPacketType.Asset); 2766 OutPacket(Transfer, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2712 2767
2713 if (req.NumPackets == 1) 2768 if (req.NumPackets == 1)
2714 { 2769 {
@@ -2719,12 +2774,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2719 TransferPacket.TransferData.Data = req.AssetInf.Data; 2774 TransferPacket.TransferData.Data = req.AssetInf.Data;
2720 TransferPacket.TransferData.Status = 1; 2775 TransferPacket.TransferData.Status = 1;
2721 TransferPacket.Header.Zerocoded = true; 2776 TransferPacket.Header.Zerocoded = true;
2722 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 2777 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2723 } 2778 }
2724 else 2779 else
2725 { 2780 {
2726 int processedLength = 0; 2781 int processedLength = 0;
2727 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 2782// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2783
2784 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2728 int packetNumber = 0; 2785 int packetNumber = 0;
2729 2786
2730 while (processedLength < req.AssetInf.Data.Length) 2787 while (processedLength < req.AssetInf.Data.Length)
@@ -2750,7 +2807,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2750 TransferPacket.TransferData.Status = 1; 2807 TransferPacket.TransferData.Status = 1;
2751 } 2808 }
2752 TransferPacket.Header.Zerocoded = true; 2809 TransferPacket.Header.Zerocoded = true;
2753 OutPacket(TransferPacket, ThrottleOutPacketType.Asset); 2810 OutPacket(TransferPacket, isWearable ? ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority : ThrottleOutPacketType.Asset);
2754 2811
2755 processedLength += chunkSize; 2812 processedLength += chunkSize;
2756 packetNumber++; 2813 packetNumber++;
@@ -2795,7 +2852,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2795 reply.Data.ParcelID = parcelID; 2852 reply.Data.ParcelID = parcelID;
2796 reply.Data.OwnerID = land.OwnerID; 2853 reply.Data.OwnerID = land.OwnerID;
2797 reply.Data.Name = Utils.StringToBytes(land.Name); 2854 reply.Data.Name = Utils.StringToBytes(land.Name);
2798 reply.Data.Desc = Utils.StringToBytes(land.Description); 2855 if (land != null && land.Description != null && land.Description != String.Empty)
2856 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
2857 else
2858 reply.Data.Desc = new Byte[0];
2799 reply.Data.ActualArea = land.Area; 2859 reply.Data.ActualArea = land.Area;
2800 reply.Data.BillableArea = land.Area; // TODO: what is this? 2860 reply.Data.BillableArea = land.Area; // TODO: what is this?
2801 2861
@@ -3502,24 +3562,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3502 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count]; 3562 aw.WearableData = new AgentWearablesUpdatePacket.WearableDataBlock[count];
3503 AgentWearablesUpdatePacket.WearableDataBlock awb; 3563 AgentWearablesUpdatePacket.WearableDataBlock awb;
3504 int idx = 0; 3564 int idx = 0;
3505 for (int i = 0; i < wearables.Length; i++) 3565
3506 { 3566 for (int i = 0; i < wearables.Length; i++)
3507 for (int j = 0; j < wearables[i].Count; j++) 3567 {
3508 { 3568 for (int j = 0; j < wearables[i].Count; j++)
3509 awb = new AgentWearablesUpdatePacket.WearableDataBlock(); 3569 {
3510 awb.WearableType = (byte)i; 3570 awb = new AgentWearablesUpdatePacket.WearableDataBlock();
3511 awb.AssetID = wearables[i][j].AssetID; 3571 awb.WearableType = (byte) i;
3512 awb.ItemID = wearables[i][j].ItemID; 3572 awb.AssetID = wearables[i][j].AssetID;
3513 aw.WearableData[idx] = awb; 3573 awb.ItemID = wearables[i][j].ItemID;
3514 idx++; 3574 aw.WearableData[idx] = awb;
3515 3575 idx++;
3516// m_log.DebugFormat( 3576
3517// "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}", 3577 // m_log.DebugFormat(
3518// awb.ItemID, awb.AssetID, i, Name); 3578 // "[APPEARANCE]: Sending wearable item/asset {0} {1} (index {2}) for {3}",
3519 } 3579 // awb.ItemID, awb.AssetID, i, Name);
3520 } 3580 }
3581 }
3521 3582
3522 OutPacket(aw, ThrottleOutPacketType.Task); 3583 OutPacket(aw, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3523 } 3584 }
3524 3585
3525 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) 3586 public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry)
@@ -3530,7 +3591,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3530 3591
3531 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); 3592 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
3532 // TODO: don't create new blocks if recycling an old packet 3593 // TODO: don't create new blocks if recycling an old packet
3533 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; 3594 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[visualParams.Length];
3534 avp.ObjectData.TextureEntry = textureEntry; 3595 avp.ObjectData.TextureEntry = textureEntry;
3535 3596
3536 AvatarAppearancePacket.VisualParamBlock avblock = null; 3597 AvatarAppearancePacket.VisualParamBlock avblock = null;
@@ -3543,7 +3604,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3543 3604
3544 avp.Sender.IsTrial = false; 3605 avp.Sender.IsTrial = false;
3545 avp.Sender.ID = agentID; 3606 avp.Sender.ID = agentID;
3546 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); 3607 m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3547 OutPacket(avp, ThrottleOutPacketType.Task); 3608 OutPacket(avp, ThrottleOutPacketType.Task);
3548 } 3609 }
3549 3610
@@ -3660,7 +3721,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3660 /// </summary> 3721 /// </summary>
3661 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3722 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3662 { 3723 {
3663 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3724 if (entity is SceneObjectPart)
3725 {
3726 SceneObjectPart e = (SceneObjectPart)entity;
3727 SceneObjectGroup g = e.ParentGroup;
3728 if (g.RootPart.Shape.State > 30) // HUD
3729 if (g.OwnerID != AgentId)
3730 return; // Don't send updates for other people's HUDs
3731 }
3732
3664 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3733 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3665 3734
3666 lock (m_entityUpdates.SyncRoot) 3735 lock (m_entityUpdates.SyncRoot)
@@ -3727,27 +3796,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3727 3796
3728 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3797 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3729 // condition where a kill can be processed before an out-of-date update for the same object. 3798 // condition where a kill can be processed before an out-of-date update for the same object.
3730 lock (m_killRecord) 3799 float avgTimeDilation = 1.0f;
3800 IEntityUpdate iupdate;
3801 Int32 timeinqueue; // this is just debugging code & can be dropped later
3802
3803 while (updatesThisCall < maxUpdates)
3731 { 3804 {
3732 float avgTimeDilation = 1.0f; 3805 lock (m_entityUpdates.SyncRoot)
3733 IEntityUpdate iupdate; 3806 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3734 Int32 timeinqueue; // this is just debugging code & can be dropped later 3807 break;
3808
3809 EntityUpdate update = (EntityUpdate)iupdate;
3810
3811 avgTimeDilation += update.TimeDilation;
3812 avgTimeDilation *= 0.5f;
3735 3813
3736 while (updatesThisCall < maxUpdates) 3814 if (update.Entity is SceneObjectPart)
3737 { 3815 {
3738 lock (m_entityUpdates.SyncRoot) 3816 SceneObjectPart part = (SceneObjectPart)update.Entity;
3739 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3740 break;
3741 3817
3742 EntityUpdate update = (EntityUpdate)iupdate; 3818 if (part.ParentGroup.IsDeleted)
3743 3819 continue;
3744 avgTimeDilation += update.TimeDilation;
3745 avgTimeDilation *= 0.5f;
3746 3820
3747 if (update.Entity is SceneObjectPart) 3821 if (part.ParentGroup.IsAttachment)
3822 { // Someone else's HUD, why are we getting these?
3823 if (part.ParentGroup.OwnerID != AgentId &&
3824 part.ParentGroup.RootPart.Shape.State > 30)
3825 continue;
3826 ScenePresence sp;
3827 // Owner is not in the sim, don't update it to
3828 // anyone
3829 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3830 continue;
3831
3832 List<SceneObjectGroup> atts = sp.GetAttachments();
3833 bool found = false;
3834 foreach (SceneObjectGroup att in atts)
3835 {
3836 if (att == part.ParentGroup)
3837 {
3838 found = true;
3839 break;
3840 }
3841 }
3842
3843 // It's an attachment of a valid avatar, but
3844 // doesn't seem to be attached, skip
3845 if (!found)
3846 continue;
3847
3848 // On vehicle crossing, the attachments are received
3849 // while the avatar is still a child. Don't send
3850 // updates here because the LocalId has not yet
3851 // been updated and the viewer will derender the
3852 // attachments until the avatar becomes root.
3853 if (sp.IsChildAgent)
3854 continue;
3855
3856 // If the object is an attachment we don't want it to be in the kill
3857 // record. Else attaching from inworld and subsequently dropping
3858 // it will no longer work.
3859// lock (m_killRecord)
3860// {
3861// m_killRecord.Remove(part.LocalId);
3862// m_killRecord.Remove(part.ParentGroup.RootPart.LocalId);
3863// }
3864 }
3865 else
3748 { 3866 {
3749 SceneObjectPart part = (SceneObjectPart)update.Entity;
3750
3751 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3867 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3752 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3868 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3753 // safety measure. 3869 // safety measure.
@@ -3758,241 +3874,177 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3758 // 3874 //
3759 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3875 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3760 // after the root prim has been deleted. 3876 // after the root prim has been deleted.
3761 if (m_killRecord.Contains(part.LocalId)) 3877 //
3762 { 3878 // We ignore this for attachments because attaching something from inworld breaks unless we do.
3763 // m_log.WarnFormat( 3879// lock (m_killRecord)
3764 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", 3880// {
3765 // part.LocalId, Name); 3881// if (m_killRecord.Contains(part.LocalId))
3766 continue; 3882// continue;
3767 } 3883// if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3768 3884// continue;
3769 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3885// }
3886 }
3887
3888 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3889 {
3890 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3891 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3770 { 3892 {
3771 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3893 part.Shape.LightEntry = false;
3772 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3773 {
3774 part.Shape.LightEntry = false;
3775 }
3776 } 3894 }
3777 } 3895 }
3778 3896 }
3779 #region UpdateFlags to packet type conversion 3897
3780 3898 ++updatesThisCall;
3781 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; 3899
3782 3900 #region UpdateFlags to packet type conversion
3783 bool canUseCompressed = true; 3901
3784 bool canUseImproved = true; 3902 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3785 3903
3786 // Compressed object updates only make sense for LL primitives 3904 bool canUseCompressed = true;
3787 if (!(update.Entity is SceneObjectPart)) 3905 bool canUseImproved = true;
3906
3907 // Compressed object updates only make sense for LL primitives
3908 if (!(update.Entity is SceneObjectPart))
3909 {
3910 canUseCompressed = false;
3911 }
3912
3913 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3914 {
3915 canUseCompressed = false;
3916 canUseImproved = false;
3917 }
3918 else
3919 {
3920 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3921 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3922 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3923 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3788 { 3924 {
3789 canUseCompressed = false; 3925 canUseCompressed = false;
3790 } 3926 }
3791 3927
3792 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3928 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3929 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3930 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3931 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3932 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3933 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3934 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3935 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3936 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3937 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3938 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3939 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3940 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3941 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3793 { 3942 {
3794 canUseCompressed = false;
3795 canUseImproved = false; 3943 canUseImproved = false;
3796 } 3944 }
3797 else 3945 }
3798 {
3799 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3800 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3801 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3802 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3803 {
3804 canUseCompressed = false;
3805 }
3806
3807 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3808 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3809 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3810 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3811 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3812 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3813 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3814 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3815 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3816 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3817 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3818 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3819 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3820 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3821 {
3822 canUseImproved = false;
3823 }
3824 }
3825
3826 #endregion UpdateFlags to packet type conversion
3827
3828 #region Block Construction
3829
3830 // TODO: Remove this once we can build compressed updates
3831 canUseCompressed = false;
3832 3946
3833 if (!canUseImproved && !canUseCompressed) 3947 #endregion UpdateFlags to packet type conversion
3834 {
3835 ObjectUpdatePacket.ObjectDataBlock updateBlock;
3836 3948
3837 if (update.Entity is ScenePresence) 3949 #region Block Construction
3838 {
3839 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
3840 }
3841 else
3842 {
3843 SceneObjectPart part = (SceneObjectPart)update.Entity;
3844 updateBlock = CreatePrimUpdateBlock(part, AgentId);
3845
3846 // If the part has become a private hud since the update was scheduled then we do not
3847 // want to send it to other avatars.
3848 if (part.ParentGroup.IsAttachment
3849 && part.ParentGroup.HasPrivateAttachmentPoint
3850 && part.ParentGroup.AttachedAvatar != AgentId)
3851 continue;
3852
3853 // If the part has since been deleted, then drop the update. In the case of attachments,
3854 // this is to avoid spurious updates to other viewers since post-processing of attachments
3855 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3856 // of the test above).
3857 //
3858 // Actual deletions (kills) happen in another method.
3859 if (part.ParentGroup.IsDeleted)
3860 continue;
3861 }
3862 3950
3863 objectUpdateBlocks.Value.Add(updateBlock); 3951 // TODO: Remove this once we can build compressed updates
3864 objectUpdates.Value.Add(update); 3952 canUseCompressed = false;
3865 }
3866 else if (!canUseImproved)
3867 {
3868 SceneObjectPart part = (SceneObjectPart)update.Entity;
3869 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
3870 = CreateCompressedUpdateBlock(part, updateFlags);
3871
3872 // If the part has since been deleted, then drop the update. In the case of attachments,
3873 // this is to avoid spurious updates to other viewers since post-processing of attachments
3874 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3875 // of the test above).
3876 //
3877 // Actual deletions (kills) happen in another method.
3878 if (part.ParentGroup.IsDeleted)
3879 continue;
3880 3953
3881 compressedUpdateBlocks.Value.Add(compressedBlock); 3954 if (!canUseImproved && !canUseCompressed)
3882 compressedUpdates.Value.Add(update); 3955 {
3956 if (update.Entity is ScenePresence)
3957 {
3958 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3883 } 3959 }
3884 else 3960 else
3885 { 3961 {
3886 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3962 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3887 {
3888 // Self updates go into a special list
3889 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3890 terseAgentUpdates.Value.Add(update);
3891 }
3892 else
3893 {
3894 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
3895 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
3896
3897 // Everything else goes here
3898 if (update.Entity is SceneObjectPart)
3899 {
3900 SceneObjectPart part = (SceneObjectPart)update.Entity;
3901
3902 // If the part has become a private hud since the update was scheduled then we do not
3903 // want to send it to other avatars.
3904 if (part.ParentGroup.IsAttachment
3905 && part.ParentGroup.HasPrivateAttachmentPoint
3906 && part.ParentGroup.AttachedAvatar != AgentId)
3907 continue;
3908
3909 // If the part has since been deleted, then drop the update. In the case of attachments,
3910 // this is to avoid spurious updates to other viewers since post-processing of attachments
3911 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3912 // of the test above).
3913 //
3914 // Actual deletions (kills) happen in another method.
3915 if (part.ParentGroup.IsDeleted)
3916 continue;
3917 }
3918
3919 terseUpdateBlocks.Value.Add(terseUpdateBlock);
3920 terseUpdates.Value.Add(update);
3921 }
3922 } 3963 }
3923
3924 ++updatesThisCall;
3925
3926 #endregion Block Construction
3927 } 3964 }
3928 3965 else if (!canUseImproved)
3929 #region Packet Sending 3966 {
3930 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3967 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3931 3968 }
3932 if (terseAgentUpdateBlocks.IsValueCreated) 3969 else
3933 { 3970 {
3934 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3971 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3972 // Self updates go into a special list
3973 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3974 else
3975 // Everything else goes here
3976 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3977 }
3935 3978
3936 ImprovedTerseObjectUpdatePacket packet 3979 #endregion Block Construction
3937 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3980 }
3938 3981
3939 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3982 #region Packet Sending
3940 packet.RegionData.TimeDilation = timeDilation; 3983
3941 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3984 const float TIME_DILATION = 1.0f;
3985 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3986
3987 if (terseAgentUpdateBlocks.IsValueCreated)
3988 {
3989 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3942 3990
3943 for (int i = 0; i < blocks.Count; i++) 3991 ImprovedTerseObjectUpdatePacket packet
3944 packet.ObjectData[i] = blocks[i]; 3992 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3945 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 3993 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3946 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 3994 packet.RegionData.TimeDilation = timeDilation;
3947 } 3995 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3948 3996
3949 if (objectUpdateBlocks.IsValueCreated) 3997 for (int i = 0; i < blocks.Count; i++)
3950 { 3998 packet.ObjectData[i] = blocks[i];
3951 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3952
3953 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3954 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3955 packet.RegionData.TimeDilation = timeDilation;
3956 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3957
3958 for (int i = 0; i < blocks.Count; i++)
3959 packet.ObjectData[i] = blocks[i];
3960 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3961 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3962 }
3963
3964 if (compressedUpdateBlocks.IsValueCreated)
3965 {
3966 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3967
3968 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3969 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3970 packet.RegionData.TimeDilation = timeDilation;
3971 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3972
3973 for (int i = 0; i < blocks.Count; i++)
3974 packet.ObjectData[i] = blocks[i];
3975 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3976 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3977 }
3978 3999
3979 if (terseUpdateBlocks.IsValueCreated) 4000 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3980 { 4001 }
3981 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3982
3983 ImprovedTerseObjectUpdatePacket packet
3984 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
3985 PacketType.ImprovedTerseObjectUpdate);
3986 4002
3987 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4003 if (objectUpdateBlocks.IsValueCreated)
3988 packet.RegionData.TimeDilation = timeDilation; 4004 {
3989 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4005 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3990 4006
3991 for (int i = 0; i < blocks.Count; i++) 4007 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3992 packet.ObjectData[i] = blocks[i]; 4008 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3993 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4009 packet.RegionData.TimeDilation = timeDilation;
3994 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4010 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3995 } 4011
4012 for (int i = 0; i < blocks.Count; i++)
4013 packet.ObjectData[i] = blocks[i];
4014
4015 OutPacket(packet, ThrottleOutPacketType.Task, true);
4016 }
4017
4018 if (compressedUpdateBlocks.IsValueCreated)
4019 {
4020 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4021
4022 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4023 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4024 packet.RegionData.TimeDilation = timeDilation;
4025 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4026
4027 for (int i = 0; i < blocks.Count; i++)
4028 packet.ObjectData[i] = blocks[i];
4029
4030 OutPacket(packet, ThrottleOutPacketType.Task, true);
4031 }
4032
4033 if (terseUpdateBlocks.IsValueCreated)
4034 {
4035 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4036
4037 ImprovedTerseObjectUpdatePacket packet
4038 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4039 PacketType.ImprovedTerseObjectUpdate);
4040 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4041 packet.RegionData.TimeDilation = timeDilation;
4042 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4043
4044 for (int i = 0; i < blocks.Count; i++)
4045 packet.ObjectData[i] = blocks[i];
4046
4047 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3996 } 4048 }
3997 4049
3998 #endregion Packet Sending 4050 #endregion Packet Sending
@@ -4285,11 +4337,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4285 4337
4286 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4338 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4287 // of the object rather than the properties when the packet was created 4339 // of the object rather than the properties when the packet was created
4288 OutPacket(packet, ThrottleOutPacketType.Task, true, 4340 // HACK : Remove intelligent resending until it's fixed in core
4289 delegate(OutgoingPacket oPacket) 4341 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4290 { 4342 // delegate(OutgoingPacket oPacket)
4291 ResendPropertyUpdates(updates, oPacket); 4343 // {
4292 }); 4344 // ResendPropertyUpdates(updates, oPacket);
4345 // });
4346 OutPacket(packet, ThrottleOutPacketType.Task, true);
4293 4347
4294 // pbcnt += blocks.Count; 4348 // pbcnt += blocks.Count;
4295 // ppcnt++; 4349 // ppcnt++;
@@ -4315,11 +4369,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4315 // of the object rather than the properties when the packet was created 4369 // of the object rather than the properties when the packet was created
4316 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4370 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4317 updates.Add(familyUpdates.Value[i]); 4371 updates.Add(familyUpdates.Value[i]);
4318 OutPacket(packet, ThrottleOutPacketType.Task, true, 4372 // HACK : Remove intelligent resending until it's fixed in core
4319 delegate(OutgoingPacket oPacket) 4373 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4320 { 4374 // delegate(OutgoingPacket oPacket)
4321 ResendPropertyUpdates(updates, oPacket); 4375 // {
4322 }); 4376 // ResendPropertyUpdates(updates, oPacket);
4377 // });
4378 OutPacket(packet, ThrottleOutPacketType.Task, true);
4323 4379
4324 // fpcnt++; 4380 // fpcnt++;
4325 // fbcnt++; 4381 // fbcnt++;
@@ -4691,7 +4747,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4691 4747
4692 if (landData.SimwideArea > 0) 4748 if (landData.SimwideArea > 0)
4693 { 4749 {
4694 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4750 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
4751 // Never report more than sim total capacity
4752 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4753 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4695 updateMessage.SimWideMaxPrims = simulatorCapacity; 4754 updateMessage.SimWideMaxPrims = simulatorCapacity;
4696 } 4755 }
4697 else 4756 else
@@ -4820,14 +4879,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4820 4879
4821 if (notifyCount > 0) 4880 if (notifyCount > 0)
4822 { 4881 {
4823 if (notifyCount > 32) 4882// if (notifyCount > 32)
4824 { 4883// {
4825 m_log.InfoFormat( 4884// m_log.InfoFormat(
4826 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4885// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4827 + " - a developer might want to investigate whether this is a hard limit", 32); 4886// + " - a developer might want to investigate whether this is a hard limit", 32);
4828 4887//
4829 notifyCount = 32; 4888// notifyCount = 32;
4830 } 4889// }
4831 4890
4832 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4891 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4833 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4892 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4882,9 +4941,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4882 { 4941 {
4883 ScenePresence presence = (ScenePresence)entity; 4942 ScenePresence presence = (ScenePresence)entity;
4884 4943
4944 position = presence.OffsetPosition;
4945 rotation = presence.Rotation;
4946
4947 if (presence.ParentID != 0)
4948 {
4949 SceneObjectPart part = m_scene.GetSceneObjectPart(presence.ParentID);
4950 if (part != null && part != part.ParentGroup.RootPart)
4951 {
4952 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4953 rotation = part.RotationOffset * presence.Rotation;
4954 }
4955 }
4956
4885 attachPoint = 0; 4957 attachPoint = 0;
4886 collisionPlane = presence.CollisionPlane; 4958 collisionPlane = presence.CollisionPlane;
4887 position = presence.OffsetPosition;
4888 velocity = presence.Velocity; 4959 velocity = presence.Velocity;
4889 acceleration = Vector3.Zero; 4960 acceleration = Vector3.Zero;
4890 4961
@@ -4892,9 +4963,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4892 // in that direction, even though we don't model this on the server. Implementing this in the future 4963 // in that direction, even though we don't model this on the server. Implementing this in the future
4893 // may improve movement smoothness. 4964 // may improve movement smoothness.
4894// acceleration = new Vector3(1, 0, 0); 4965// acceleration = new Vector3(1, 0, 0);
4895 4966
4896 angularVelocity = Vector3.Zero; 4967 angularVelocity = Vector3.Zero;
4897 rotation = presence.Rotation;
4898 4968
4899 if (sendTexture) 4969 if (sendTexture)
4900 textureEntry = presence.Appearance.Texture.GetBytes(); 4970 textureEntry = presence.Appearance.Texture.GetBytes();
@@ -5001,13 +5071,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5001 5071
5002 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5072 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5003 { 5073 {
5074 Vector3 offsetPosition = data.OffsetPosition;
5075 Quaternion rotation = data.Rotation;
5076 uint parentID = data.ParentID;
5077
5078 if (parentID != 0)
5079 {
5080 SceneObjectPart part = m_scene.GetSceneObjectPart(parentID);
5081 if (part != null && part != part.ParentGroup.RootPart)
5082 {
5083 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
5084 rotation = part.RotationOffset * data.Rotation;
5085 parentID = part.ParentGroup.RootPart.LocalId;
5086 }
5087 }
5088
5004 byte[] objectData = new byte[76]; 5089 byte[] objectData = new byte[76];
5005 5090
5006 data.CollisionPlane.ToBytes(objectData, 0); 5091 data.CollisionPlane.ToBytes(objectData, 0);
5007 data.OffsetPosition.ToBytes(objectData, 16); 5092 offsetPosition.ToBytes(objectData, 16);
5008// data.Velocity.ToBytes(objectData, 28); 5093// data.Velocity.ToBytes(objectData, 28);
5009// data.Acceleration.ToBytes(objectData, 40); 5094// data.Acceleration.ToBytes(objectData, 40);
5010 data.Rotation.ToBytes(objectData, 52); 5095 rotation.ToBytes(objectData, 52);
5011 //data.AngularVelocity.ToBytes(objectData, 64); 5096 //data.AngularVelocity.ToBytes(objectData, 64);
5012 5097
5013 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5098 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5021,14 +5106,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5021 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5106 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5022 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5107 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5023 update.ObjectData = objectData; 5108 update.ObjectData = objectData;
5024 update.ParentID = data.ParentID; 5109 update.ParentID = parentID;
5025 update.PathCurve = 16; 5110 update.PathCurve = 16;
5026 update.PathScaleX = 100; 5111 update.PathScaleX = 100;
5027 update.PathScaleY = 100; 5112 update.PathScaleY = 100;
5028 update.PCode = (byte)PCode.Avatar; 5113 update.PCode = (byte)PCode.Avatar;
5029 update.ProfileCurve = 1; 5114 update.ProfileCurve = 1;
5030 update.PSBlock = Utils.EmptyBytes; 5115 update.PSBlock = Utils.EmptyBytes;
5031 update.Scale = new Vector3(0.45f, 0.6f, 1.9f); 5116 update.Scale = data.Appearance.AvatarSize;
5117// update.Scale.Z -= 0.2f;
5118
5032 update.Text = Utils.EmptyBytes; 5119 update.Text = Utils.EmptyBytes;
5033 update.TextColor = new byte[4]; 5120 update.TextColor = new byte[4];
5034 5121
@@ -5039,10 +5126,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5039 update.TextureEntry = Utils.EmptyBytes; 5126 update.TextureEntry = Utils.EmptyBytes;
5040// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5127// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5041 5128
5129/* all this flags seem related to prims and not avatars. This allow for wrong viewer side move of a avatar in prim edition mode (anv mantis 854)
5042 update.UpdateFlags = (uint)( 5130 update.UpdateFlags = (uint)(
5043 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5131 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5044 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5132 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5045 PrimFlags.ObjectOwnerModify); 5133 PrimFlags.ObjectOwnerModify);
5134*/
5135 update.UpdateFlags = 0;
5046 5136
5047 return update; 5137 return update;
5048 } 5138 }
@@ -5213,8 +5303,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5213 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs 5303 // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs
5214 // for each AgentUpdate packet. 5304 // for each AgentUpdate packet.
5215 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); 5305 AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false);
5216 5306
5217 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); 5307 AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false);
5308 AddLocalPacketHandler(PacketType.VelocityInterpolateOff, HandleVelocityInterpolateOff, false);
5309 AddLocalPacketHandler(PacketType.VelocityInterpolateOn, HandleVelocityInterpolateOn, false);
5218 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); 5310 AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false);
5219 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); 5311 AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false);
5220 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); 5312 AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false);
@@ -5366,6 +5458,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5366 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5458 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5367 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5459 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5368 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5460 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5461 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5369 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5462 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5370 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5463 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5371 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5464 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5432,6 +5525,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5432 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5525 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5433 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5526 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5434 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5527 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5528 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5435 5529
5436 AddGenericPacketHandler("autopilot", HandleAutopilot); 5530 AddGenericPacketHandler("autopilot", HandleAutopilot);
5437 } 5531 }
@@ -5470,6 +5564,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5470 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || 5564 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5471 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || 5565 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5472 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || 5566 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5567 (x.ControlFlags != 0) ||
5473 (x.Far != m_lastAgentUpdateArgs.Far) || 5568 (x.Far != m_lastAgentUpdateArgs.Far) ||
5474 (x.Flags != m_lastAgentUpdateArgs.Flags) || 5569 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5475 (x.State != m_lastAgentUpdateArgs.State) || 5570 (x.State != m_lastAgentUpdateArgs.State) ||
@@ -5729,6 +5824,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5729 return true; 5824 return true;
5730 } 5825 }
5731 5826
5827 private bool HandleVelocityInterpolateOff(IClientAPI sender, Packet Pack)
5828 {
5829 VelocityInterpolateOffPacket p = (VelocityInterpolateOffPacket)Pack;
5830 if (p.AgentData.SessionID != SessionId ||
5831 p.AgentData.AgentID != AgentId)
5832 return true;
5833
5834 m_VelocityInterpolate = false;
5835 return true;
5836 }
5837
5838 private bool HandleVelocityInterpolateOn(IClientAPI sender, Packet Pack)
5839 {
5840 VelocityInterpolateOnPacket p = (VelocityInterpolateOnPacket)Pack;
5841 if (p.AgentData.SessionID != SessionId ||
5842 p.AgentData.AgentID != AgentId)
5843 return true;
5844
5845 m_VelocityInterpolate = true;
5846 return true;
5847 }
5848
5849
5732 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack) 5850 private bool HandleAvatarPropertiesRequest(IClientAPI sender, Packet Pack)
5733 { 5851 {
5734 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack; 5852 AvatarPropertiesRequestPacket avatarProperties = (AvatarPropertiesRequestPacket)Pack;
@@ -6149,17 +6267,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6149 // Temporarily protect ourselves from the mantis #951 failure. 6267 // Temporarily protect ourselves from the mantis #951 failure.
6150 // However, we could do this for several other handlers where a failure isn't terminal 6268 // However, we could do this for several other handlers where a failure isn't terminal
6151 // for the client session anyway, in order to protect ourselves against bad code in plugins 6269 // for the client session anyway, in order to protect ourselves against bad code in plugins
6270 Vector3 avSize = appear.AgentData.Size;
6152 try 6271 try
6153 { 6272 {
6154 byte[] visualparams = new byte[appear.VisualParam.Length]; 6273 byte[] visualparams = new byte[appear.VisualParam.Length];
6155 for (int i = 0; i < appear.VisualParam.Length; i++) 6274 for (int i = 0; i < appear.VisualParam.Length; i++)
6156 visualparams[i] = appear.VisualParam[i].ParamValue; 6275 visualparams[i] = appear.VisualParam[i].ParamValue;
6157 6276 //var b = appear.WearableData[0];
6277
6158 Primitive.TextureEntry te = null; 6278 Primitive.TextureEntry te = null;
6159 if (appear.ObjectData.TextureEntry.Length > 1) 6279 if (appear.ObjectData.TextureEntry.Length > 1)
6160 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); 6280 te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length);
6281
6282 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
6283 for (int i=0; i<appear.WearableData.Length;i++)
6284 cacheitems[i] = new WearableCacheItem(){CacheId = appear.WearableData[i].CacheID,TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)};
6161 6285
6162 handlerSetAppearance(sender, te, visualparams); 6286
6287
6288 handlerSetAppearance(sender, te, visualparams,avSize, cacheitems);
6163 } 6289 }
6164 catch (Exception e) 6290 catch (Exception e)
6165 { 6291 {
@@ -6368,6 +6494,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6368 { 6494 {
6369 handlerCompleteMovementToRegion(sender, true); 6495 handlerCompleteMovementToRegion(sender, true);
6370 } 6496 }
6497 else
6498 m_log.Debug("HandleCompleteAgentMovement NULL handler");
6499
6371 handlerCompleteMovementToRegion = null; 6500 handlerCompleteMovementToRegion = null;
6372 6501
6373 return true; 6502 return true;
@@ -6385,7 +6514,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6385 return true; 6514 return true;
6386 } 6515 }
6387 #endregion 6516 #endregion
6388 6517/*
6389 StartAnim handlerStartAnim = null; 6518 StartAnim handlerStartAnim = null;
6390 StopAnim handlerStopAnim = null; 6519 StopAnim handlerStopAnim = null;
6391 6520
@@ -6409,6 +6538,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6409 } 6538 }
6410 } 6539 }
6411 return true; 6540 return true;
6541*/
6542 ChangeAnim handlerChangeAnim = null;
6543
6544 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6545 {
6546 handlerChangeAnim = OnChangeAnim;
6547 if (handlerChangeAnim != null)
6548 {
6549 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
6550 }
6551 }
6552
6553 handlerChangeAnim = OnChangeAnim;
6554 if (handlerChangeAnim != null)
6555 {
6556 handlerChangeAnim(UUID.Zero, false, true);
6557 }
6558
6559 return true;
6412 } 6560 }
6413 6561
6414 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 6562 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -6634,6 +6782,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6634 #endregion 6782 #endregion
6635 6783
6636 m_udpClient.SetThrottles(atpack.Throttle.Throttles); 6784 m_udpClient.SetThrottles(atpack.Throttle.Throttles);
6785 GenericCall2 handler = OnUpdateThrottles;
6786 if (handler != null)
6787 {
6788 handler();
6789 }
6637 return true; 6790 return true;
6638 } 6791 }
6639 6792
@@ -7035,10 +7188,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7035 // 46,47,48 are special positions within the packet 7188 // 46,47,48 are special positions within the packet
7036 // This may change so perhaps we need a better way 7189 // This may change so perhaps we need a better way
7037 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) 7190 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
7038 bool UsePhysics = (data[46] != 0) ? true : false; 7191 /*
7039 bool IsTemporary = (data[47] != 0) ? true : false; 7192 bool UsePhysics = (data[46] != 0) ? true : false;
7040 bool IsPhantom = (data[48] != 0) ? true : false; 7193 bool IsTemporary = (data[47] != 0) ? true : false;
7041 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); 7194 bool IsPhantom = (data[48] != 0) ? true : false;
7195 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
7196 */
7197 bool UsePhysics = flags.AgentData.UsePhysics;
7198 bool IsPhantom = flags.AgentData.IsPhantom;
7199 bool IsTemporary = flags.AgentData.IsTemporary;
7200 ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics;
7201 ExtraPhysicsData physdata = new ExtraPhysicsData();
7202
7203 if (blocks == null || blocks.Length == 0)
7204 {
7205 physdata.PhysShapeType = PhysShapeType.invalid;
7206 }
7207 else
7208 {
7209 ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0];
7210 physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType;
7211 physdata.Bounce = phsblock.Restitution;
7212 physdata.Density = phsblock.Density;
7213 physdata.Friction = phsblock.Friction;
7214 physdata.GravitationModifier = phsblock.GravityMultiplier;
7215 }
7216
7217 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
7042 } 7218 }
7043 return true; 7219 return true;
7044 } 7220 }
@@ -7621,6 +7797,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7621 // surrounding scene 7797 // surrounding scene
7622 if ((ImageType)block.Type == ImageType.Baked) 7798 if ((ImageType)block.Type == ImageType.Baked)
7623 args.Priority *= 2.0f; 7799 args.Priority *= 2.0f;
7800 int wearableout = 0;
7624 7801
7625 ImageManager.EnqueueReq(args); 7802 ImageManager.EnqueueReq(args);
7626 } 7803 }
@@ -8639,16 +8816,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8639 8816
8640 #region Parcel related packets 8817 #region Parcel related packets
8641 8818
8819 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
8820 // to be done with minimal resources as possible
8821 // variables temporary here while in test
8822
8823 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
8824 bool RegionHandleRequestsInService = false;
8825
8642 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 8826 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
8643 { 8827 {
8644 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 8828 UUID currentUUID;
8645 8829
8646 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 8830 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
8647 if (handlerRegionHandleRequest != null) 8831
8832 if (handlerRegionHandleRequest == null)
8833 return true;
8834
8835 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
8836
8837 lock (RegionHandleRequests)
8838 {
8839 if (RegionHandleRequestsInService)
8840 {
8841 // we are already busy doing a previus request
8842 // so enqueue it
8843 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
8844 return true;
8845 }
8846
8847 // else do it
8848 currentUUID = rhrPack.RequestBlock.RegionID;
8849 RegionHandleRequestsInService = true;
8850 }
8851
8852 while (true)
8648 { 8853 {
8649 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 8854 handlerRegionHandleRequest(this, currentUUID);
8855
8856 lock (RegionHandleRequests)
8857 {
8858 // exit condition, nothing to do or closed
8859 // current code seems to assume we may loose the handler at anytime,
8860 // so keep checking it
8861 handlerRegionHandleRequest = OnRegionHandleRequest;
8862
8863 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
8864 {
8865 RegionHandleRequests.Clear();
8866 RegionHandleRequestsInService = false;
8867 return true;
8868 }
8869 currentUUID = RegionHandleRequests.Dequeue();
8870 }
8650 } 8871 }
8651 return true; 8872
8873 return true; // actually unreached
8652 } 8874 }
8653 8875
8654 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 8876 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -9904,7 +10126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9904 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10126 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9905 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10127 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9906 UpdateMuteListEntry.MuteData.MuteType, 10128 UpdateMuteListEntry.MuteData.MuteType,
9907 UpdateMuteListEntry.AgentData.AgentID); 10129 UpdateMuteListEntry.MuteData.MuteFlags);
9908 return true; 10130 return true;
9909 } 10131 }
9910 return false; 10132 return false;
@@ -9919,8 +10141,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9919 { 10141 {
9920 handlerRemoveMuteListEntry(this, 10142 handlerRemoveMuteListEntry(this,
9921 RemoveMuteListEntry.MuteData.MuteID, 10143 RemoveMuteListEntry.MuteData.MuteID,
9922 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10144 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9923 RemoveMuteListEntry.AgentData.AgentID);
9924 return true; 10145 return true;
9925 } 10146 }
9926 return false; 10147 return false;
@@ -9964,10 +10185,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9964 return false; 10185 return false;
9965 } 10186 }
9966 10187
10188 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10189 {
10190 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10191 (ChangeInventoryItemFlagsPacket)packet;
10192 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10193 if (handlerChangeInventoryItemFlags != null)
10194 {
10195 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10196 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10197 return true;
10198 }
10199 return false;
10200 }
10201
9967 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10202 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9968 { 10203 {
9969 return true; 10204 return true;
9970 } 10205 }
10206
10207 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10208 {
10209 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10210
10211 #region Packet Session and User Check
10212 if (m_checkPackets)
10213 {
10214 if (packet.AgentData.SessionID != SessionId ||
10215 packet.AgentData.AgentID != AgentId)
10216 return true;
10217 }
10218 #endregion
10219 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10220 List<InventoryItemBase> items = new List<InventoryItemBase>();
10221 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10222 {
10223 InventoryItemBase b = new InventoryItemBase();
10224 b.ID = n.OldItemID;
10225 b.Folder = n.OldFolderID;
10226 items.Add(b);
10227 }
10228
10229 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10230 if (handlerMoveItemsAndLeaveCopy != null)
10231 {
10232 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10233 }
10234
10235 return true;
10236 }
9971 10237
9972 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10238 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9973 { 10239 {
@@ -10394,6 +10660,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10394 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10660 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10395 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10661 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10396 10662
10663 Scene scene = (Scene)m_scene;
10664 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10665 {
10666 ScenePresence p;
10667 if (scene.TryGetScenePresence(sender.AgentId, out p))
10668 {
10669 if (p.GodLevel >= 200)
10670 {
10671 groupProfileReply.GroupData.OpenEnrollment = true;
10672 groupProfileReply.GroupData.MembershipFee = 0;
10673 }
10674 }
10675 }
10676
10397 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10677 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10398 } 10678 }
10399 return true; 10679 return true;
@@ -10967,11 +11247,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10967 11247
10968 StartLure handlerStartLure = OnStartLure; 11248 StartLure handlerStartLure = OnStartLure;
10969 if (handlerStartLure != null) 11249 if (handlerStartLure != null)
10970 handlerStartLure(startLureRequest.Info.LureType, 11250 {
10971 Utils.BytesToString( 11251 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10972 startLureRequest.Info.Message), 11252 {
10973 startLureRequest.TargetData[0].TargetID, 11253 handlerStartLure(startLureRequest.Info.LureType,
10974 this); 11254 Utils.BytesToString(
11255 startLureRequest.Info.Message),
11256 startLureRequest.TargetData[i].TargetID,
11257 this);
11258 }
11259 }
10975 return true; 11260 return true;
10976 } 11261 }
10977 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11262 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11085,10 +11370,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11085 } 11370 }
11086 #endregion 11371 #endregion
11087 11372
11088 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11373 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11089 if (handlerClassifiedGodDelete != null) 11374 if (handlerClassifiedGodDelete != null)
11090 handlerClassifiedGodDelete( 11375 handlerClassifiedGodDelete(
11091 classifiedGodDelete.Data.ClassifiedID, 11376 classifiedGodDelete.Data.ClassifiedID,
11377 classifiedGodDelete.Data.QueryID,
11092 this); 11378 this);
11093 return true; 11379 return true;
11094 } 11380 }
@@ -11401,6 +11687,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11401 11687
11402 if (cachedtex.AgentData.SessionID != SessionId) 11688 if (cachedtex.AgentData.SessionID != SessionId)
11403 return false; 11689 return false;
11690
11404 11691
11405 // TODO: don't create new blocks if recycling an old packet 11692 // TODO: don't create new blocks if recycling an old packet
11406 cachedresp.AgentData.AgentID = AgentId; 11693 cachedresp.AgentData.AgentID = AgentId;
@@ -11410,14 +11697,140 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11410 cachedresp.WearableData = 11697 cachedresp.WearableData =
11411 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; 11698 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
11412 11699
11413 for (int i = 0; i < cachedtex.WearableData.Length; i++) 11700 //IAvatarFactoryModule fac = m_scene.RequestModuleInterface<IAvatarFactoryModule>();
11701 // var item = fac.GetBakedTextureFaces(AgentId);
11702 //WearableCacheItem[] items = fac.GetCachedItems(AgentId);
11703
11704 IAssetService cache = m_scene.AssetService;
11705 IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
11706 //bakedTextureModule = null;
11707 int maxWearablesLoop = cachedtex.WearableData.Length;
11708 if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES)
11709 maxWearablesLoop = AvatarWearable.MAX_WEARABLES;
11710
11711 if (bakedTextureModule != null && cache != null)
11414 { 11712 {
11415 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 11713 // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
11416 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 11714
11417 cachedresp.WearableData[i].TextureID = UUID.Zero; 11715 WearableCacheItem[] cacheItems = null;
11418 cachedresp.WearableData[i].HostName = new byte[0]; 11716 ScenePresence p = m_scene.GetScenePresence(AgentId);
11717 if (p.Appearance != null)
11718 if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty)
11719 {
11720 try
11721 {
11722 cacheItems = bakedTextureModule.Get(AgentId);
11723 p.Appearance.WearableCacheItems = cacheItems;
11724 p.Appearance.WearableCacheItemsDirty = false;
11725 }
11726
11727 /*
11728 * The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception!
11729 *
11730 catch (System.Net.Sockets.SocketException)
11731 {
11732 cacheItems = null;
11733 }
11734 catch (WebException)
11735 {
11736 cacheItems = null;
11737 }
11738 catch (InvalidOperationException)
11739 {
11740 cacheItems = null;
11741 } */
11742 catch (Exception)
11743 {
11744 cacheItems = null;
11745 }
11746
11747 }
11748 else if (p.Appearance.WearableCacheItems != null)
11749 {
11750 cacheItems = p.Appearance.WearableCacheItems;
11751 }
11752
11753 if (cache != null && cacheItems != null)
11754 {
11755 foreach (WearableCacheItem item in cacheItems)
11756 {
11757
11758 if (cache.GetCached(item.TextureID.ToString()) == null)
11759 {
11760 item.TextureAsset.Temporary = true;
11761 cache.Store(item.TextureAsset);
11762 }
11763
11764
11765 }
11766 }
11767
11768 if (cacheItems != null)
11769 {
11770
11771 for (int i = 0; i < maxWearablesLoop; i++)
11772 {
11773 WearableCacheItem item =
11774 WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems);
11775
11776 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11777 cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex;
11778 cachedresp.WearableData[i].HostName = new byte[0];
11779 if (item != null && cachedtex.WearableData[i].ID == item.CacheId)
11780 {
11781
11782 cachedresp.WearableData[i].TextureID = item.TextureID;
11783 }
11784 else
11785 {
11786 cachedresp.WearableData[i].TextureID = UUID.Zero;
11787 }
11788 }
11789 }
11790 else
11791 {
11792 for (int i = 0; i < maxWearablesLoop; i++)
11793 {
11794 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11795 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11796 cachedresp.WearableData[i].TextureID = UUID.Zero;
11797 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11798 cachedresp.WearableData[i].HostName = new byte[0];
11799 }
11800 }
11419 } 11801 }
11802 else
11803 {
11804 if (cache == null)
11805 {
11806 for (int i = 0; i < maxWearablesLoop; i++)
11807 {
11808 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11809 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11810 cachedresp.WearableData[i].TextureID = UUID.Zero;
11811 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11812 cachedresp.WearableData[i].HostName = new byte[0];
11813 }
11814 }
11815 else
11816 {
11817 for (int i = 0; i < maxWearablesLoop; i++)
11818 {
11819 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11820 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11821
11420 11822
11823
11824 if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null)
11825 cachedresp.WearableData[i].TextureID = UUID.Zero;
11826 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11827 else
11828 cachedresp.WearableData[i].TextureID = UUID.Zero;
11829 // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11830 cachedresp.WearableData[i].HostName = new byte[0];
11831 }
11832 }
11833 }
11421 cachedresp.Header.Zerocoded = true; 11834 cachedresp.Header.Zerocoded = true;
11422 OutPacket(cachedresp, ThrottleOutPacketType.Task); 11835 OutPacket(cachedresp, ThrottleOutPacketType.Task);
11423 11836
@@ -11454,209 +11867,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11454 } 11867 }
11455 else 11868 else
11456 { 11869 {
11457// m_log.DebugFormat( 11870 ClientChangeObject updatehandler = onClientChangeObject;
11458// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
11459// i, block.Type, part.Name, part.LocalId);
11460 11871
11461// // Do this once since fetch parts creates a new array. 11872 if (updatehandler != null)
11462// SceneObjectPart[] parts = part.ParentGroup.Parts; 11873 {
11463// for (int j = 0; j < parts.Length; j++) 11874 ObjectChangeData udata = new ObjectChangeData();
11464// {
11465// part.StoreUndoState();
11466// parts[j].IgnoreUndoUpdate = true;
11467// }
11468 11875
11469 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 11876 /*ubit from ll JIRA:
11877 * 0x01 position
11878 * 0x02 rotation
11879 * 0x04 scale
11880
11881 * 0x08 LINK_SET
11882 * 0x10 UNIFORM for scale
11883 */
11470 11884
11471 switch (block.Type) 11885 // translate to internal changes
11472 { 11886 // not all cases .. just the ones older code did
11473 case 1:
11474 Vector3 pos1 = new Vector3(block.Data, 0);
11475 11887
11476 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11888 switch (block.Type)
11477 if (handlerUpdatePrimSinglePosition != null) 11889 {
11478 { 11890 case 1: //change position sp
11479 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11891 udata.position = new Vector3(block.Data, 0);
11480 handlerUpdatePrimSinglePosition(localId, pos1, this);
11481 }
11482 break;
11483 11892
11484 case 2: 11893 udata.change = ObjectChangeType.primP;
11485 Quaternion rot1 = new Quaternion(block.Data, 0, true); 11894 updatehandler(localId, udata, this);
11895 break;
11486 11896
11487 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 11897 case 2: // rotation sp
11488 if (handlerUpdatePrimSingleRotation != null) 11898 udata.rotation = new Quaternion(block.Data, 0, true);
11489 {
11490 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
11491 handlerUpdatePrimSingleRotation(localId, rot1, this);
11492 }
11493 break;
11494 11899
11495 case 3: 11900 udata.change = ObjectChangeType.primR;
11496 Vector3 rotPos = new Vector3(block.Data, 0); 11901 updatehandler(localId, udata, this);
11497 Quaternion rot2 = new Quaternion(block.Data, 12, true); 11902 break;
11498 11903
11499 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 11904 case 3: // position plus rotation
11500 if (handlerUpdatePrimSingleRotationPosition != null) 11905 udata.position = new Vector3(block.Data, 0);
11501 { 11906 udata.rotation = new Quaternion(block.Data, 12, true);
11502 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
11503 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
11504 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
11505 }
11506 break;
11507 11907
11508 case 4: 11908 udata.change = ObjectChangeType.primPR;
11509 case 20: 11909 updatehandler(localId, udata, this);
11510 Vector3 scale4 = new Vector3(block.Data, 0); 11910 break;
11511 11911
11512 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 11912 case 4: // scale sp
11513 if (handlerUpdatePrimScale != null) 11913 udata.scale = new Vector3(block.Data, 0);
11514 { 11914 udata.change = ObjectChangeType.primS;
11515 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
11516 handlerUpdatePrimScale(localId, scale4, this);
11517 }
11518 break;
11519 11915
11520 case 5: 11916 updatehandler(localId, udata, this);
11521 Vector3 scale1 = new Vector3(block.Data, 12); 11917 break;
11522 Vector3 pos11 = new Vector3(block.Data, 0);
11523 11918
11524 handlerUpdatePrimScale = OnUpdatePrimScale; 11919 case 0x14: // uniform scale sp
11525 if (handlerUpdatePrimScale != null) 11920 udata.scale = new Vector3(block.Data, 0);
11526 {
11527 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11528 handlerUpdatePrimScale(localId, scale1, this);
11529 11921
11530 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11922 udata.change = ObjectChangeType.primUS;
11531 if (handlerUpdatePrimSinglePosition != null) 11923 updatehandler(localId, udata, this);
11532 { 11924 break;
11533 handlerUpdatePrimSinglePosition(localId, pos11, this);
11534 }
11535 }
11536 break;
11537 11925
11538 case 9: 11926 case 5: // scale and position sp
11539 Vector3 pos2 = new Vector3(block.Data, 0); 11927 udata.position = new Vector3(block.Data, 0);
11928 udata.scale = new Vector3(block.Data, 12);
11540 11929
11541 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 11930 udata.change = ObjectChangeType.primPS;
11931 updatehandler(localId, udata, this);
11932 break;
11542 11933
11543 if (handlerUpdateVector != null) 11934 case 0x15: //uniform scale and position
11544 { 11935 udata.position = new Vector3(block.Data, 0);
11545 handlerUpdateVector(localId, pos2, this); 11936 udata.scale = new Vector3(block.Data, 12);
11546 }
11547 break;
11548 11937
11549 case 10: 11938 udata.change = ObjectChangeType.primPUS;
11550 Quaternion rot3 = new Quaternion(block.Data, 0, true); 11939 updatehandler(localId, udata, this);
11940 break;
11551 11941
11552 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 11942 // now group related (bit 4)
11553 if (handlerUpdatePrimRotation != null) 11943 case 9: //( 8 + 1 )group position
11554 { 11944 udata.position = new Vector3(block.Data, 0);
11555 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11556 handlerUpdatePrimRotation(localId, rot3, this);
11557 }
11558 break;
11559 11945
11560 case 11: 11946 udata.change = ObjectChangeType.groupP;
11561 Vector3 pos3 = new Vector3(block.Data, 0); 11947 updatehandler(localId, udata, this);
11562 Quaternion rot4 = new Quaternion(block.Data, 12, true); 11948 break;
11563 11949
11564 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 11950 case 0x0A: // (8 + 2) group rotation
11565 if (handlerUpdatePrimGroupRotation != null) 11951 udata.rotation = new Quaternion(block.Data, 0, true);
11566 {
11567 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11568 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11569 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
11570 }
11571 break;
11572 case 12:
11573 case 28:
11574 Vector3 scale7 = new Vector3(block.Data, 0);
11575 11952
11576 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11953 udata.change = ObjectChangeType.groupR;
11577 if (handlerUpdatePrimGroupScale != null) 11954 updatehandler(localId, udata, this);
11578 { 11955 break;
11579 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11580 handlerUpdatePrimGroupScale(localId, scale7, this);
11581 }
11582 break;
11583 11956
11584 case 13: 11957 case 0x0B: //( 8 + 2 + 1) group rotation and position
11585 Vector3 scale2 = new Vector3(block.Data, 12); 11958 udata.position = new Vector3(block.Data, 0);
11586 Vector3 pos4 = new Vector3(block.Data, 0); 11959 udata.rotation = new Quaternion(block.Data, 12, true);
11587 11960
11588 handlerUpdatePrimScale = OnUpdatePrimScale; 11961 udata.change = ObjectChangeType.groupPR;
11589 if (handlerUpdatePrimScale != null) 11962 updatehandler(localId, udata, this);
11590 { 11963 break;
11591 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11592 handlerUpdatePrimScale(localId, scale2, this);
11593 11964
11594 // Change the position based on scale (for bug number 246) 11965 case 0x0C: // (8 + 4) group scale
11595 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11966 // only afects root prim and only sent by viewer editor object tab scaling
11596 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11967 // mouse edition only allows uniform scaling
11597 if (handlerUpdatePrimSinglePosition != null) 11968 // SL MAY CHANGE THIS in viewers
11598 {
11599 handlerUpdatePrimSinglePosition(localId, pos4, this);
11600 }
11601 }
11602 break;
11603 11969
11604 case 29: 11970 udata.scale = new Vector3(block.Data, 0);
11605 Vector3 scale5 = new Vector3(block.Data, 12);
11606 Vector3 pos5 = new Vector3(block.Data, 0);
11607 11971
11608 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11972 udata.change = ObjectChangeType.groupS;
11609 if (handlerUpdatePrimGroupScale != null) 11973 updatehandler(localId, udata, this);
11610 {
11611 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11612 part.StoreUndoState(true);
11613 part.IgnoreUndoUpdate = true;
11614 handlerUpdatePrimGroupScale(localId, scale5, this);
11615 handlerUpdateVector = OnUpdatePrimGroupPosition;
11616 11974
11617 if (handlerUpdateVector != null) 11975 break;
11618 {
11619 handlerUpdateVector(localId, pos5, this);
11620 }
11621 11976
11622 part.IgnoreUndoUpdate = false; 11977 case 0x0D: //(8 + 4 + 1) group scale and position
11623 } 11978 // exception as above
11624 11979
11625 break; 11980 udata.position = new Vector3(block.Data, 0);
11981 udata.scale = new Vector3(block.Data, 12);
11626 11982
11627 case 21: 11983 udata.change = ObjectChangeType.groupPS;
11628 Vector3 scale6 = new Vector3(block.Data, 12); 11984 updatehandler(localId, udata, this);
11629 Vector3 pos6 = new Vector3(block.Data, 0); 11985 break;
11630 11986
11631 handlerUpdatePrimScale = OnUpdatePrimScale; 11987 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
11632 if (handlerUpdatePrimScale != null) 11988 udata.scale = new Vector3(block.Data, 0);
11633 {
11634 part.StoreUndoState(false);
11635 part.IgnoreUndoUpdate = true;
11636 11989
11637 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11990 udata.change = ObjectChangeType.groupUS;
11638 handlerUpdatePrimScale(localId, scale6, this); 11991 updatehandler(localId, udata, this);
11639 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11992 break;
11640 if (handlerUpdatePrimSinglePosition != null)
11641 {
11642 handlerUpdatePrimSinglePosition(localId, pos6, this);
11643 }
11644 11993
11645 part.IgnoreUndoUpdate = false; 11994 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
11646 } 11995 udata.position = new Vector3(block.Data, 0);
11647 break; 11996 udata.scale = new Vector3(block.Data, 12);
11648 11997
11649 default: 11998 udata.change = ObjectChangeType.groupPUS;
11650 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 11999 updatehandler(localId, udata, this);
11651 break; 12000 break;
12001
12002 default:
12003 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
12004 break;
12005 }
11652 } 12006 }
11653 12007
11654// for (int j = 0; j < parts.Length; j++)
11655// parts[j].IgnoreUndoUpdate = false;
11656 } 12008 }
11657 } 12009 }
11658 } 12010 }
11659
11660 return true; 12011 return true;
11661 } 12012 }
11662 12013
@@ -11717,9 +12068,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11717 public void SetChildAgentThrottle(byte[] throttles) 12068 public void SetChildAgentThrottle(byte[] throttles)
11718 { 12069 {
11719 m_udpClient.SetThrottles(throttles); 12070 m_udpClient.SetThrottles(throttles);
12071 GenericCall2 handler = OnUpdateThrottles;
12072 if (handler != null)
12073 {
12074 handler();
12075 }
11720 } 12076 }
11721 12077
11722 /// <summary> 12078 /// <summary>
12079 /// Sets the throttles from values supplied by the client
12080 /// </summary>
12081 /// <param name="throttles"></param>
12082 public void SetAgentThrottleSilent(int throttle, int setting)
12083 {
12084 m_udpClient.ForceThrottleSetting(throttle,setting);
12085 //m_udpClient.SetThrottles(throttles);
12086
12087 }
12088
12089
12090 /// <summary>
11723 /// Get the current throttles for this client as a packed byte array 12091 /// Get the current throttles for this client as a packed byte array
11724 /// </summary> 12092 /// </summary>
11725 /// <param name="multiplier">Unused</param> 12093 /// <param name="multiplier">Unused</param>
@@ -12106,7 +12474,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12106// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 12474// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12107// requestID, taskID, (SourceType)sourceType, Name); 12475// requestID, taskID, (SourceType)sourceType, Name);
12108 12476
12477
12478 //Note, the bool returned from the below function is useless since it is always false.
12109 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12479 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12480
12110 } 12481 }
12111 12482
12112 /// <summary> 12483 /// <summary>
@@ -12172,7 +12543,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12172 /// <returns></returns> 12543 /// <returns></returns>
12173 private static int CalculateNumPackets(byte[] data) 12544 private static int CalculateNumPackets(byte[] data)
12174 { 12545 {
12175 const uint m_maxPacketSize = 600; 12546// const uint m_maxPacketSize = 600;
12547 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12176 int numPackets = 1; 12548 int numPackets = 1;
12177 12549
12178 if (data == null) 12550 if (data == null)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 621e0fd..e52ac37 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -92,7 +92,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
92 /// <summary>Packets we have sent that need to be ACKed by the client</summary> 92 /// <summary>Packets we have sent that need to be ACKed by the client</summary>
93 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection(); 93 public readonly UnackedPacketCollection NeedAcks = new UnackedPacketCollection();
94 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary> 94 /// <summary>ACKs that are queued up, waiting to be sent to the client</summary>
95 public readonly OpenSim.Framework.LocklessQueue<uint> PendingAcks = new OpenSim.Framework.LocklessQueue<uint>(); 95 public readonly DoubleLocklessQueue<uint> PendingAcks = new DoubleLocklessQueue<uint>();
96 96
97 /// <summary>Current packet sequence number</summary> 97 /// <summary>Current packet sequence number</summary>
98 public int CurrentSequence; 98 public int CurrentSequence;
@@ -146,7 +146,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
146 /// <summary>Throttle buckets for each packet category</summary> 146 /// <summary>Throttle buckets for each packet category</summary>
147 private readonly TokenBucket[] m_throttleCategories; 147 private readonly TokenBucket[] m_throttleCategories;
148 /// <summary>Outgoing queues for throttled packets</summary> 148 /// <summary>Outgoing queues for throttled packets</summary>
149 private readonly OpenSim.Framework.LocklessQueue<OutgoingPacket>[] m_packetOutboxes = new OpenSim.Framework.LocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT]; 149 private readonly DoubleLocklessQueue<OutgoingPacket>[] m_packetOutboxes = new DoubleLocklessQueue<OutgoingPacket>[THROTTLE_CATEGORY_COUNT];
150 /// <summary>A container that can hold one packet for each outbox, used to store 150 /// <summary>A container that can hold one packet for each outbox, used to store
151 /// dequeued packets that are being held for throttling</summary> 151 /// dequeued packets that are being held for throttling</summary>
152 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT]; 152 private readonly OutgoingPacket[] m_nextPackets = new OutgoingPacket[THROTTLE_CATEGORY_COUNT];
@@ -158,6 +158,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
158 158
159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC 159 private int m_defaultRTO = 1000; // 1sec is the recommendation in the RFC
160 private int m_maxRTO = 60000; 160 private int m_maxRTO = 60000;
161 public bool m_deliverPackets = true;
161 162
162 /// <summary> 163 /// <summary>
163 /// Default constructor 164 /// Default constructor
@@ -201,7 +202,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
201 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 202 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
202 203
203 // Initialize the packet outboxes, where packets sit while they are waiting for tokens 204 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
204 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 205 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
205 // Initialize the token buckets that control the throttling for each category 206 // Initialize the token buckets that control the throttling for each category
206 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type)); 207 m_throttleCategories[i] = new TokenBucket(m_throttleCategory, rates.GetRate(type));
207 } 208 }
@@ -429,11 +430,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP
429 /// </returns> 430 /// </returns>
430 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue) 431 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue)
431 { 432 {
433 return EnqueueOutgoing(packet, forceQueue, false);
434 }
435
436 public bool EnqueueOutgoing(OutgoingPacket packet, bool forceQueue, bool highPriority)
437 {
432 int category = (int)packet.Category; 438 int category = (int)packet.Category;
433 439
434 if (category >= 0 && category < m_packetOutboxes.Length) 440 if (category >= 0 && category < m_packetOutboxes.Length)
435 { 441 {
436 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 442 DoubleLocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
443
444 if (m_deliverPackets == false)
445 {
446 queue.Enqueue(packet, highPriority);
447 return true;
448 }
449
437 TokenBucket bucket = m_throttleCategories[category]; 450 TokenBucket bucket = m_throttleCategories[category];
438 451
439 // Don't send this packet if there is already a packet waiting in the queue 452 // Don't send this packet if there is already a packet waiting in the queue
@@ -441,7 +454,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
441 // queued packets 454 // queued packets
442 if (queue.Count > 0) 455 if (queue.Count > 0)
443 { 456 {
444 queue.Enqueue(packet); 457 queue.Enqueue(packet, highPriority);
445 return true; 458 return true;
446 } 459 }
447 460
@@ -454,7 +467,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
454 else 467 else
455 { 468 {
456 // Force queue specified or not enough tokens in the bucket, queue this packet 469 // Force queue specified or not enough tokens in the bucket, queue this packet
457 queue.Enqueue(packet); 470 queue.Enqueue(packet, highPriority);
458 return true; 471 return true;
459 } 472 }
460 } 473 }
@@ -483,8 +496,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 /// <returns>True if any packets were sent, otherwise false</returns> 496 /// <returns>True if any packets were sent, otherwise false</returns>
484 public bool DequeueOutgoing() 497 public bool DequeueOutgoing()
485 { 498 {
486 OutgoingPacket packet; 499 if (m_deliverPackets == false) return false;
487 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 500
501 OutgoingPacket packet = null;
502 DoubleLocklessQueue<OutgoingPacket> queue;
488 TokenBucket bucket; 503 TokenBucket bucket;
489 bool packetSent = false; 504 bool packetSent = false;
490 ThrottleOutPacketTypeFlags emptyCategories = 0; 505 ThrottleOutPacketTypeFlags emptyCategories = 0;
@@ -515,32 +530,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
515 // No dequeued packet waiting to be sent, try to pull one off 530 // No dequeued packet waiting to be sent, try to pull one off
516 // this queue 531 // this queue
517 queue = m_packetOutboxes[i]; 532 queue = m_packetOutboxes[i];
518 if (queue.Dequeue(out packet)) 533 if (queue != null)
519 { 534 {
520 // A packet was pulled off the queue. See if we have 535 bool success = false;
521 // enough tokens in the bucket to send it out 536 try
522 if (bucket.RemoveTokens(packet.Buffer.DataLength))
523 { 537 {
524 // Send the packet 538 success = queue.Dequeue(out packet);
525 m_udpServer.SendPacketFinal(packet);
526 packetSent = true;
527 } 539 }
528 else 540 catch
529 { 541 {
530 // Save the dequeued packet for the next iteration 542 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
531 m_nextPackets[i] = packet;
532 } 543 }
533 544 if (success)
534 // If the queue is empty after this dequeue, fire the queue 545 {
535 // empty callback now so it has a chance to fill before we 546 // A packet was pulled off the queue. See if we have
536 // get back here 547 // enough tokens in the bucket to send it out
537 if (queue.Count == 0) 548 if (bucket.RemoveTokens(packet.Buffer.DataLength))
549 {
550 // Send the packet
551 m_udpServer.SendPacketFinal(packet);
552 packetSent = true;
553 }
554 else
555 {
556 // Save the dequeued packet for the next iteration
557 m_nextPackets[i] = packet;
558 }
559
560 // If the queue is empty after this dequeue, fire the queue
561 // empty callback now so it has a chance to fill before we
562 // get back here
563 if (queue.Count == 0)
564 emptyCategories |= CategoryToFlag(i);
565 }
566 else
567 {
568 // No packets in this queue. Fire the queue empty callback
569 // if it has not been called recently
538 emptyCategories |= CategoryToFlag(i); 570 emptyCategories |= CategoryToFlag(i);
571 }
539 } 572 }
540 else 573 else
541 { 574 {
542 // No packets in this queue. Fire the queue empty callback 575 m_packetOutboxes[i] = new DoubleLocklessQueue<OutgoingPacket>();
543 // if it has not been called recently
544 emptyCategories |= CategoryToFlag(i); 576 emptyCategories |= CategoryToFlag(i);
545 } 577 }
546 } 578 }
@@ -649,6 +681,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
649 if (m_nextOnQueueEmpty == 0) 681 if (m_nextOnQueueEmpty == 0)
650 m_nextOnQueueEmpty = 1; 682 m_nextOnQueueEmpty = 1;
651 } 683 }
684 internal void ForceThrottleSetting(int throttle, int setting)
685 {
686 m_throttleCategories[throttle].RequestedDripRate = Math.Max(setting, LLUDPServer.MTU); ;
687 }
652 688
653 /// <summary> 689 /// <summary>
654 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a 690 /// Converts a <seealso cref="ThrottleOutPacketType"/> integer to a
@@ -693,4 +729,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
693 } 729 }
694 } 730 }
695 } 731 }
732
733 public class DoubleLocklessQueue<T> : OpenSim.Framework.LocklessQueue<T>
734 {
735 OpenSim.Framework.LocklessQueue<T> highQueue = new OpenSim.Framework.LocklessQueue<T>();
736
737 public override int Count
738 {
739 get
740 {
741 return base.Count + highQueue.Count;
742 }
743 }
744
745 public override bool Dequeue(out T item)
746 {
747 if (highQueue.Dequeue(out item))
748 return true;
749
750 return base.Dequeue(out item);
751 }
752
753 public void Enqueue(T item, bool highPriority)
754 {
755 if (highPriority)
756 highQueue.Enqueue(item);
757 else
758 Enqueue(item);
759 }
760 }
696} 761}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index a7628d2..6c72edc 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -126,7 +126,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
126 /// <summary>Handlers for incoming packets</summary> 126 /// <summary>Handlers for incoming packets</summary>
127 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 127 //PacketEventDictionary packetEvents = new PacketEventDictionary();
128 /// <summary>Incoming packets that are awaiting handling</summary> 128 /// <summary>Incoming packets that are awaiting handling</summary>
129 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 129 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
130
131 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
130 132
131 /// <summary></summary> 133 /// <summary></summary>
132 //private UDPClientCollection m_clients = new UDPClientCollection(); 134 //private UDPClientCollection m_clients = new UDPClientCollection();
@@ -181,6 +183,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 /// <summary>Flag to signal when clients should send pings</summary> 183 /// <summary>Flag to signal when clients should send pings</summary>
182 protected bool m_sendPing; 184 protected bool m_sendPing;
183 185
186 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
184 private Pool<IncomingPacket> m_incomingPacketPool; 187 private Pool<IncomingPacket> m_incomingPacketPool;
185 188
186 /// <summary> 189 /// <summary>
@@ -800,6 +803,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
800 803
801 #region Queue or Send 804 #region Queue or Send
802 805
806 bool highPriority = false;
807
808 if (category != ThrottleOutPacketType.Unknown && (category & ThrottleOutPacketType.HighPriority) != 0)
809 {
810 category = (ThrottleOutPacketType)((int)category & 127);
811 highPriority = true;
812 }
813
803 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null); 814 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category, null);
804 // If we were not provided a method for handling unacked, use the UDPServer default method 815 // If we were not provided a method for handling unacked, use the UDPServer default method
805 outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method); 816 outgoingPacket.UnackedMethod = ((method == null) ? delegate(OutgoingPacket oPacket) { ResendUnacked(oPacket); } : method);
@@ -808,7 +819,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
808 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object 819 // continue to display the deleted object until relog. Therefore, we need to always queue a kill object
809 // packet so that it isn't sent before a queued update packet. 820 // packet so that it isn't sent before a queued update packet.
810 bool requestQueue = type == PacketType.KillObject; 821 bool requestQueue = type == PacketType.KillObject;
811 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue)) 822 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket, requestQueue, highPriority))
812 SendPacketFinal(outgoingPacket); 823 SendPacketFinal(outgoingPacket);
813 824
814 #endregion Queue or Send 825 #endregion Queue or Send
@@ -1093,21 +1104,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1093 1104
1094 #region Packet to Client Mapping 1105 #region Packet to Client Mapping
1095 1106
1096 // UseCircuitCode handling 1107 // If there is already a client for this endpoint, don't process UseCircuitCode
1097 if (packet.Type == PacketType.UseCircuitCode) 1108 IClientAPI client = null;
1109 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1098 { 1110 {
1099 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 1111 // UseCircuitCode handling
1100 // buffer. 1112 if (packet.Type == PacketType.UseCircuitCode)
1101 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 1113 {
1114 // And if there is a UseCircuitCode pending, also drop it
1115 lock (m_pendingCache)
1116 {
1117 if (m_pendingCache.Contains(endPoint))
1118 return;
1119
1120 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
1121 }
1102 1122
1103 Util.FireAndForget(HandleUseCircuitCode, array); 1123 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
1124 // buffer.
1125 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
1104 1126
1105 return; 1127 Util.FireAndForget(HandleUseCircuitCode, array);
1128
1129 return;
1130 }
1131 }
1132
1133 // If this is a pending connection, enqueue, don't process yet
1134 lock (m_pendingCache)
1135 {
1136 Queue<UDPPacketBuffer> queue;
1137 if (m_pendingCache.TryGetValue(endPoint, out queue))
1138 {
1139 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1140 queue.Enqueue(buffer);
1141 return;
1142 }
1106 } 1143 }
1107 1144
1108 // Determine which agent this packet came from 1145 // Determine which agent this packet came from
1109 IClientAPI client; 1146 if (client == null || !(client is LLClientView))
1110 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
1111 { 1147 {
1112 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1148 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
1113 return; 1149 return;
@@ -1116,7 +1152,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1116 udpClient = ((LLClientView)client).UDPClient; 1152 udpClient = ((LLClientView)client).UDPClient;
1117 1153
1118 if (!udpClient.IsConnected) 1154 if (!udpClient.IsConnected)
1155 {
1156// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
1119 return; 1157 return;
1158 }
1120 1159
1121 #endregion Packet to Client Mapping 1160 #endregion Packet to Client Mapping
1122 1161
@@ -1246,7 +1285,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1246 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1285 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1247 } 1286 }
1248 1287
1249 packetInbox.Enqueue(incomingPacket); 1288 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1289 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1290 packetInbox.EnqueueHigh(incomingPacket);
1291 else
1292 packetInbox.EnqueueLow(incomingPacket);
1250 } 1293 }
1251 1294
1252 #region BinaryStats 1295 #region BinaryStats
@@ -1366,6 +1409,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1366 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1409 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1367 if (client != null) 1410 if (client != null)
1368 client.SceneAgent.SendInitialDataToMe(); 1411 client.SceneAgent.SendInitialDataToMe();
1412
1413 // Now we know we can handle more data
1414 Thread.Sleep(200);
1415
1416 // Obtain the queue and remove it from the cache
1417 Queue<UDPPacketBuffer> queue = null;
1418
1419 lock (m_pendingCache)
1420 {
1421 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1422 {
1423 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1424 return;
1425 }
1426 m_pendingCache.Remove(endPoint);
1427 }
1428
1429 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1430
1431 // Reinject queued packets
1432 while(queue.Count > 0)
1433 {
1434 UDPPacketBuffer buf = queue.Dequeue();
1435 PacketReceived(buf);
1436 }
1437 queue = null;
1369 } 1438 }
1370 else 1439 else
1371 { 1440 {
@@ -1373,6 +1442,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1373 m_log.WarnFormat( 1442 m_log.WarnFormat(
1374 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1443 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1375 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1444 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1445 lock (m_pendingCache)
1446 m_pendingCache.Remove(endPoint);
1376 } 1447 }
1377 1448
1378 // m_log.DebugFormat( 1449 // m_log.DebugFormat(
@@ -1491,7 +1562,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1491 if (!client.SceneAgent.IsChildAgent) 1562 if (!client.SceneAgent.IsChildAgent)
1492 client.Kick("Simulator logged you out due to connection timeout"); 1563 client.Kick("Simulator logged you out due to connection timeout");
1493 1564
1494 client.CloseWithoutChecks(); 1565 client.CloseWithoutChecks(true);
1495 } 1566 }
1496 } 1567 }
1497 1568
@@ -1503,6 +1574,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1503 1574
1504 while (IsRunningInbound) 1575 while (IsRunningInbound)
1505 { 1576 {
1577 m_scene.ThreadAlive(1);
1506 try 1578 try
1507 { 1579 {
1508 IncomingPacket incomingPacket = null; 1580 IncomingPacket incomingPacket = null;
@@ -1550,6 +1622,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1550 1622
1551 while (base.IsRunningOutbound) 1623 while (base.IsRunningOutbound)
1552 { 1624 {
1625 m_scene.ThreadAlive(2);
1553 try 1626 try
1554 { 1627 {
1555 m_packetSent = false; 1628 m_packetSent = false;
@@ -1780,8 +1853,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1780 Packet packet = incomingPacket.Packet; 1853 Packet packet = incomingPacket.Packet;
1781 LLClientView client = incomingPacket.Client; 1854 LLClientView client = incomingPacket.Client;
1782 1855
1783 if (client.IsActive) 1856// if (client.IsActive)
1784 { 1857// {
1785 m_currentIncomingClient = client; 1858 m_currentIncomingClient = client;
1786 1859
1787 try 1860 try
@@ -1808,13 +1881,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1808 { 1881 {
1809 m_currentIncomingClient = null; 1882 m_currentIncomingClient = null;
1810 } 1883 }
1811 } 1884// }
1812 else 1885// else
1813 { 1886// {
1814 m_log.DebugFormat( 1887// m_log.DebugFormat(
1815 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1888// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1816 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1889// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1817 } 1890// }
1818 1891
1819 IncomingPacketsProcessed++; 1892 IncomingPacketsProcessed++;
1820 } 1893 }
@@ -1826,8 +1899,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1826 if (!client.IsLoggingOut) 1899 if (!client.IsLoggingOut)
1827 { 1900 {
1828 client.IsLoggingOut = true; 1901 client.IsLoggingOut = true;
1829 client.Close(); 1902 client.Close(false, false);
1903 }
1904 }
1905 }
1906
1907 internal class DoubleQueue<T> where T:class
1908 {
1909 private Queue<T> m_lowQueue = new Queue<T>();
1910 private Queue<T> m_highQueue = new Queue<T>();
1911
1912 private object m_syncRoot = new object();
1913 private Semaphore m_s = new Semaphore(0, 1);
1914
1915 public DoubleQueue()
1916 {
1917 }
1918
1919 public virtual int Count
1920 {
1921 get { return m_highQueue.Count + m_lowQueue.Count; }
1922 }
1923
1924 public virtual void Enqueue(T data)
1925 {
1926 Enqueue(m_lowQueue, data);
1927 }
1928
1929 public virtual void EnqueueLow(T data)
1930 {
1931 Enqueue(m_lowQueue, data);
1932 }
1933
1934 public virtual void EnqueueHigh(T data)
1935 {
1936 Enqueue(m_highQueue, data);
1937 }
1938
1939 private void Enqueue(Queue<T> q, T data)
1940 {
1941 lock (m_syncRoot)
1942 {
1943 m_lowQueue.Enqueue(data);
1944 m_s.WaitOne(0);
1945 m_s.Release();
1946 }
1947 }
1948
1949 public virtual T Dequeue()
1950 {
1951 return Dequeue(Timeout.Infinite);
1952 }
1953
1954 public virtual T Dequeue(int tmo)
1955 {
1956 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1957 }
1958
1959 public virtual T Dequeue(TimeSpan wait)
1960 {
1961 T res = null;
1962
1963 if (!Dequeue(wait, ref res))
1964 return null;
1965
1966 return res;
1967 }
1968
1969 public bool Dequeue(int timeout, ref T res)
1970 {
1971 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1972 }
1973
1974 public bool Dequeue(TimeSpan wait, ref T res)
1975 {
1976 if (!m_s.WaitOne(wait))
1977 return false;
1978
1979 lock (m_syncRoot)
1980 {
1981 if (m_highQueue.Count > 0)
1982 res = m_highQueue.Dequeue();
1983 else
1984 res = m_lowQueue.Dequeue();
1985
1986 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1987 return true;
1988
1989 try
1990 {
1991 m_s.Release();
1992 }
1993 catch
1994 {
1995 }
1996
1997 return true;
1998 }
1999 }
2000
2001 public virtual void Clear()
2002 {
2003
2004 lock (m_syncRoot)
2005 {
2006 // Make sure sem count is 0
2007 m_s.WaitOne(0);
2008
2009 m_lowQueue.Clear();
2010 m_highQueue.Clear();
1830 } 2011 }
1831 } 2012 }
1832 } 2013 }
1833} \ No newline at end of file 2014}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index f143c32..7035e38 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -114,10 +114,6 @@ namespace OpenMetaverse
114 const int SIO_UDP_CONNRESET = -1744830452; 114 const int SIO_UDP_CONNRESET = -1744830452;
115 115
116 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 116 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
117
118 m_log.DebugFormat(
119 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
120 ipep.Address, ipep.Port);
121 117
122 m_udpSocket = new Socket( 118 m_udpSocket = new Socket(
123 AddressFamily.InterNetwork, 119 AddressFamily.InterNetwork,