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.cs1206
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs65
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs219
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs4
5 files changed, 945 insertions, 552 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 7427c59..67ce48e 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,6 +291,7 @@ 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;
@@ -326,6 +330,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
326 private Prioritizer m_prioritizer; 330 private Prioritizer m_prioritizer;
327 private bool m_disableFacelights = false; 331 private bool m_disableFacelights = false;
328 332
333 private const uint MaxTransferBytesPerPacket = 600;
334
335
329 /// <value> 336 /// <value>
330 /// List used in construction of data blocks for an object update packet. This is to stop us having to 337 /// List used in construction of data blocks for an object update packet. This is to stop us having to
331 /// continually recreate it. 338 /// continually recreate it.
@@ -337,14 +344,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
337 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an 344 /// thread servicing the m_primFullUpdates queue after a kill. If this happens the object persists as an
338 /// ownerless phantom. 345 /// ownerless phantom.
339 /// 346 ///
340 /// All manipulation of this set has to occur under a lock 347 /// All manipulation of this set has to occur under an m_entityUpdates.SyncRoot lock
341 /// 348 ///
342 /// </value> 349 /// </value>
343 protected HashSet<uint> m_killRecord; 350// protected HashSet<uint> m_killRecord;
344 351
345// protected HashSet<uint> m_attachmentsSent; 352// protected HashSet<uint> m_attachmentsSent;
346 353
347 private int m_moneyBalance; 354 private int m_moneyBalance;
355 private bool m_deliverPackets = true;
348 private int m_animationSequenceNumber = 1; 356 private int m_animationSequenceNumber = 1;
349 private bool m_SendLogoutPacketWhenClosing = true; 357 private bool m_SendLogoutPacketWhenClosing = true;
350 358
@@ -391,6 +399,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
391 get { return m_startpos; } 399 get { return m_startpos; }
392 set { m_startpos = value; } 400 set { m_startpos = value; }
393 } 401 }
402 public bool DeliverPackets
403 {
404 get { return m_deliverPackets; }
405 set {
406 m_deliverPackets = value;
407 m_udpClient.m_deliverPackets = value;
408 }
409 }
394 public UUID AgentId { get { return m_agentId; } } 410 public UUID AgentId { get { return m_agentId; } }
395 public ISceneAgent SceneAgent { get; set; } 411 public ISceneAgent SceneAgent { get; set; }
396 public UUID ActiveGroupId { get { return m_activeGroupID; } } 412 public UUID ActiveGroupId { get { return m_activeGroupID; } }
@@ -468,7 +484,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
468 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); 484 m_entityUpdates = new PriorityQueue(m_scene.Entities.Count);
469 m_entityProps = new PriorityQueue(m_scene.Entities.Count); 485 m_entityProps = new PriorityQueue(m_scene.Entities.Count);
470 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); 486 m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>();
471 m_killRecord = new HashSet<uint>(); 487// m_killRecord = new HashSet<uint>();
472// m_attachmentsSent = new HashSet<uint>(); 488// m_attachmentsSent = new HashSet<uint>();
473 489
474 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 490 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
@@ -498,12 +514,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
498 514
499 #region Client Methods 515 #region Client Methods
500 516
517
518 /// <summary>
519 /// Close down the client view
520 /// </summary>
501 public void Close() 521 public void Close()
502 { 522 {
503 Close(false); 523 Close(true, false);
504 } 524 }
505 525
506 public void Close(bool force) 526 public void Close(bool sendStop, bool force)
507 { 527 {
508 // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. 528 // 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. 529 // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection.
@@ -515,7 +535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
515 return; 535 return;
516 536
517 IsActive = false; 537 IsActive = false;
518 CloseWithoutChecks(); 538 CloseWithoutChecks(sendStop);
519 } 539 }
520 } 540 }
521 541
@@ -528,12 +548,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
528 /// 548 ///
529 /// Callers must lock ClosingSyncLock before calling. 549 /// Callers must lock ClosingSyncLock before calling.
530 /// </remarks> 550 /// </remarks>
531 public void CloseWithoutChecks() 551 public void CloseWithoutChecks(bool sendStop)
532 { 552 {
533 m_log.DebugFormat( 553 m_log.DebugFormat(
534 "[CLIENT]: Close has been called for {0} attached to scene {1}", 554 "[CLIENT]: Close has been called for {0} attached to scene {1}",
535 Name, m_scene.RegionInfo.RegionName); 555 Name, m_scene.RegionInfo.RegionName);
536 556
557 if (sendStop)
558 {
559 // Send the STOP packet
560 DisableSimulatorPacket disable = (DisableSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.DisableSimulator);
561 OutPacket(disable, ThrottleOutPacketType.Unknown);
562 }
563
537 // Shutdown the image manager 564 // Shutdown the image manager
538 ImageManager.Close(); 565 ImageManager.Close();
539 566
@@ -791,7 +818,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
791 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 818 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
792 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 819 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
793 820
794 OutPacket(handshake, ThrottleOutPacketType.Task); 821// OutPacket(handshake, ThrottleOutPacketType.Task);
822 // use same as MoveAgentIntoRegion (both should be task )
823 OutPacket(handshake, ThrottleOutPacketType.Unknown);
795 } 824 }
796 825
797 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 826 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
@@ -830,7 +859,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
830 reply.ChatData.OwnerID = fromAgentID; 859 reply.ChatData.OwnerID = fromAgentID;
831 reply.ChatData.SourceID = fromAgentID; 860 reply.ChatData.SourceID = fromAgentID;
832 861
833 OutPacket(reply, ThrottleOutPacketType.Task); 862 OutPacket(reply, ThrottleOutPacketType.Unknown);
834 } 863 }
835 864
836 /// <summary> 865 /// <summary>
@@ -1116,6 +1145,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1116 public virtual void SendLayerData(float[] map) 1145 public virtual void SendLayerData(float[] map)
1117 { 1146 {
1118 Util.FireAndForget(DoSendLayerData, map); 1147 Util.FireAndForget(DoSendLayerData, map);
1148
1149 // Send it sync, and async. It's not that much data
1150 // and it improves user experience just so much!
1151 DoSendLayerData(map);
1119 } 1152 }
1120 1153
1121 /// <summary> 1154 /// <summary>
@@ -1128,16 +1161,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1128 1161
1129 try 1162 try
1130 { 1163 {
1131 //for (int y = 0; y < 16; y++) 1164 for (int y = 0; y < 16; y++)
1132 //{ 1165 {
1133 // for (int x = 0; x < 16; x++) 1166 for (int x = 0; x < 16; x+=4)
1134 // { 1167 {
1135 // SendLayerData(x, y, map); 1168 SendLayerPacket(x, y, map);
1136 // } 1169 }
1137 //} 1170 }
1138
1139 // Send LayerData in a spiral pattern. Fun!
1140 SendLayerTopRight(map, 0, 0, 15, 15);
1141 } 1171 }
1142 catch (Exception e) 1172 catch (Exception e)
1143 { 1173 {
@@ -1145,51 +1175,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1145 } 1175 }
1146 } 1176 }
1147 1177
1148 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1149 {
1150 // Row
1151 for (int i = x1; i <= x2; i++)
1152 SendLayerData(i, y1, map);
1153
1154 // Column
1155 for (int j = y1 + 1; j <= y2; j++)
1156 SendLayerData(x2, j, map);
1157
1158 if (x2 - x1 > 0)
1159 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1160 }
1161
1162 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1163 {
1164 // Row in reverse
1165 for (int i = x2; i >= x1; i--)
1166 SendLayerData(i, y2, map);
1167
1168 // Column in reverse
1169 for (int j = y2 - 1; j >= y1; j--)
1170 SendLayerData(x1, j, map);
1171
1172 if (x2 - x1 > 0)
1173 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1174 }
1175
1176 /// <summary> 1178 /// <summary>
1177 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1179 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1178 /// </summary> 1180 /// </summary>
1179 /// <param name="map">heightmap</param> 1181 /// <param name="map">heightmap</param>
1180 /// <param name="px">X coordinate for patches 0..12</param> 1182 /// <param name="px">X coordinate for patches 0..12</param>
1181 /// <param name="py">Y coordinate for patches 0..15</param> 1183 /// <param name="py">Y coordinate for patches 0..15</param>
1182 // private void SendLayerPacket(float[] map, int y, int x) 1184 private void SendLayerPacket(int x, int y, float[] map)
1183 // { 1185 {
1184 // int[] patches = new int[4]; 1186 int[] patches = new int[4];
1185 // patches[0] = x + 0 + y * 16; 1187 patches[0] = x + 0 + y * 16;
1186 // patches[1] = x + 1 + y * 16; 1188 patches[1] = x + 1 + y * 16;
1187 // patches[2] = x + 2 + y * 16; 1189 patches[2] = x + 2 + y * 16;
1188 // patches[3] = x + 3 + y * 16; 1190 patches[3] = x + 3 + y * 16;
1189 1191
1190 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1192 float[] heightmap = (map.Length == 65536) ?
1191 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1193 map :
1192 // } 1194 LLHeightFieldMoronize(map);
1195
1196 try
1197 {
1198 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1199 OutPacket(layerpack, ThrottleOutPacketType.Land);
1200 }
1201 catch
1202 {
1203 for (int px = x ; px < x + 4 ; px++)
1204 SendLayerData(px, y, map);
1205 }
1206 }
1193 1207
1194 /// <summary> 1208 /// <summary>
1195 /// Sends a specified patch to a client 1209 /// Sends a specified patch to a client
@@ -1209,7 +1223,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1209 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1223 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1210 layerpack.Header.Reliable = true; 1224 layerpack.Header.Reliable = true;
1211 1225
1212 OutPacket(layerpack, ThrottleOutPacketType.Land); 1226 OutPacket(layerpack, ThrottleOutPacketType.Task);
1213 } 1227 }
1214 catch (Exception e) 1228 catch (Exception e)
1215 { 1229 {
@@ -1572,7 +1586,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1572 1586
1573 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1587 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1574 { 1588 {
1575// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1589// foreach (uint id in localIDs)
1590// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1576 1591
1577 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1592 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1578 // TODO: don't create new blocks if recycling an old packet 1593 // TODO: don't create new blocks if recycling an old packet
@@ -1594,17 +1609,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1594 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race 1609 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1595 // condition where a kill can be processed before an out-of-date update for the same object. 1610 // condition where a kill can be processed before an out-of-date update for the same object.
1596 // ProcessEntityUpdates() also takes the m_killRecord lock. 1611 // ProcessEntityUpdates() also takes the m_killRecord lock.
1597 lock (m_killRecord) 1612// lock (m_killRecord)
1598 { 1613// {
1599 foreach (uint localID in localIDs) 1614// foreach (uint localID in localIDs)
1600 m_killRecord.Add(localID); 1615// m_killRecord.Add(localID);
1601 1616
1602 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1617 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1603 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1618 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1604 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1619 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1605 // scene objects in a viewer until that viewer is relogged in. 1620 // scene objects in a viewer until that viewer is relogged in.
1606 OutPacket(kill, ThrottleOutPacketType.Task); 1621 OutPacket(kill, ThrottleOutPacketType.Task);
1607 } 1622// }
1608 } 1623 }
1609 } 1624 }
1610 1625
@@ -2062,9 +2077,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2062 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2077 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2063 } 2078 }
2064 2079
2065 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2066 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2080 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2067 { 2081 {
2082 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2083 }
2084
2085 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2086 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2087 {
2068 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; 2088 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
2069 2089
2070 UpdateCreateInventoryItemPacket InventoryReply 2090 UpdateCreateInventoryItemPacket InventoryReply
@@ -2074,6 +2094,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2074 // TODO: don't create new blocks if recycling an old packet 2094 // TODO: don't create new blocks if recycling an old packet
2075 InventoryReply.AgentData.AgentID = AgentId; 2095 InventoryReply.AgentData.AgentID = AgentId;
2076 InventoryReply.AgentData.SimApproved = true; 2096 InventoryReply.AgentData.SimApproved = true;
2097 InventoryReply.AgentData.TransactionID = transactionID;
2077 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2098 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2078 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2099 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2079 InventoryReply.InventoryData[0].ItemID = Item.ID; 2100 InventoryReply.InventoryData[0].ItemID = Item.ID;
@@ -2143,16 +2164,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2143 replytask.InventoryData.TaskID = taskID; 2164 replytask.InventoryData.TaskID = taskID;
2144 replytask.InventoryData.Serial = serial; 2165 replytask.InventoryData.Serial = serial;
2145 replytask.InventoryData.Filename = fileName; 2166 replytask.InventoryData.Filename = fileName;
2146 OutPacket(replytask, ThrottleOutPacketType.Asset); 2167 OutPacket(replytask, ThrottleOutPacketType.Task);
2147 } 2168 }
2148 2169
2149 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2170 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2150 { 2171 {
2172 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2173 if (isTaskInventory)
2174 type = ThrottleOutPacketType.Task;
2175
2151 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2176 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2152 sendXfer.XferID.ID = xferID; 2177 sendXfer.XferID.ID = xferID;
2153 sendXfer.XferID.Packet = packet; 2178 sendXfer.XferID.Packet = packet;
2154 sendXfer.DataPacket.Data = data; 2179 sendXfer.DataPacket.Data = data;
2155 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2180 OutPacket(sendXfer, type);
2156 } 2181 }
2157 2182
2158 public void SendAbortXferPacket(ulong xferID) 2183 public void SendAbortXferPacket(ulong xferID)
@@ -2334,6 +2359,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2334 OutPacket(sound, ThrottleOutPacketType.Task); 2359 OutPacket(sound, ThrottleOutPacketType.Task);
2335 } 2360 }
2336 2361
2362 public void SendTransferAbort(TransferRequestPacket transferRequest)
2363 {
2364 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2365 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2366 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2367 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2368 OutPacket(abort, ThrottleOutPacketType.Task);
2369 }
2370
2337 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2371 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2338 { 2372 {
2339 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2373 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2626,6 +2660,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2626 } 2660 }
2627 } 2661 }
2628 2662
2663 public void SendPartPhysicsProprieties(ISceneEntity entity)
2664 {
2665 SceneObjectPart part = (SceneObjectPart)entity;
2666 if (part != null && AgentId != UUID.Zero)
2667 {
2668 try
2669 {
2670 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2671 if (eq != null)
2672 {
2673 uint localid = part.LocalId;
2674 byte physshapetype = part.PhysicsShapeType;
2675 float density = part.Density;
2676 float friction = part.Friction;
2677 float bounce = part.Bounciness;
2678 float gravmod = part.GravityModifier;
2679
2680 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2681 }
2682 }
2683 catch (Exception ex)
2684 {
2685 m_log.Error("Unable to send part Physics Proprieties - exception: " + ex.ToString());
2686 }
2687 part.UpdatePhysRequired = false;
2688 }
2689 }
2690
2691
2629 2692
2630 public void SendGroupNameReply(UUID groupLLUID, string GroupName) 2693 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2631 { 2694 {
@@ -2723,7 +2786,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2723 else 2786 else
2724 { 2787 {
2725 int processedLength = 0; 2788 int processedLength = 0;
2726 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 2789// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2790
2791 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2727 int packetNumber = 0; 2792 int packetNumber = 0;
2728 2793
2729 while (processedLength < req.AssetInf.Data.Length) 2794 while (processedLength < req.AssetInf.Data.Length)
@@ -2794,7 +2859,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2794 reply.Data.ParcelID = parcelID; 2859 reply.Data.ParcelID = parcelID;
2795 reply.Data.OwnerID = land.OwnerID; 2860 reply.Data.OwnerID = land.OwnerID;
2796 reply.Data.Name = Utils.StringToBytes(land.Name); 2861 reply.Data.Name = Utils.StringToBytes(land.Name);
2797 reply.Data.Desc = Utils.StringToBytes(land.Description); 2862 if (land != null && land.Description != null && land.Description != String.Empty)
2863 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
2864 else
2865 reply.Data.Desc = new Byte[0];
2798 reply.Data.ActualArea = land.Area; 2866 reply.Data.ActualArea = land.Area;
2799 reply.Data.BillableArea = land.Area; // TODO: what is this? 2867 reply.Data.BillableArea = land.Area; // TODO: what is this?
2800 2868
@@ -3529,7 +3597,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3529 3597
3530 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); 3598 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
3531 // TODO: don't create new blocks if recycling an old packet 3599 // TODO: don't create new blocks if recycling an old packet
3532 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; 3600 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[visualParams.Length];
3533 avp.ObjectData.TextureEntry = textureEntry; 3601 avp.ObjectData.TextureEntry = textureEntry;
3534 3602
3535 AvatarAppearancePacket.VisualParamBlock avblock = null; 3603 AvatarAppearancePacket.VisualParamBlock avblock = null;
@@ -3659,7 +3727,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3659 /// </summary> 3727 /// </summary>
3660 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3728 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3661 { 3729 {
3662 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3730 if (entity is SceneObjectPart)
3731 {
3732 SceneObjectPart e = (SceneObjectPart)entity;
3733 SceneObjectGroup g = e.ParentGroup;
3734 if (g.RootPart.Shape.State > 30) // HUD
3735 if (g.OwnerID != AgentId)
3736 return; // Don't send updates for other people's HUDs
3737 }
3738
3663 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3739 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3664 3740
3665 lock (m_entityUpdates.SyncRoot) 3741 lock (m_entityUpdates.SyncRoot)
@@ -3726,27 +3802,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3726 3802
3727 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3803 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3728 // condition where a kill can be processed before an out-of-date update for the same object. 3804 // condition where a kill can be processed before an out-of-date update for the same object.
3729 lock (m_killRecord) 3805 float avgTimeDilation = 1.0f;
3806 IEntityUpdate iupdate;
3807 Int32 timeinqueue; // this is just debugging code & can be dropped later
3808
3809 while (updatesThisCall < maxUpdates)
3730 { 3810 {
3731 float avgTimeDilation = 1.0f; 3811 lock (m_entityUpdates.SyncRoot)
3732 IEntityUpdate iupdate; 3812 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3733 Int32 timeinqueue; // this is just debugging code & can be dropped later 3813 break;
3814
3815 EntityUpdate update = (EntityUpdate)iupdate;
3816
3817 avgTimeDilation += update.TimeDilation;
3818 avgTimeDilation *= 0.5f;
3734 3819
3735 while (updatesThisCall < maxUpdates) 3820 if (update.Entity is SceneObjectPart)
3736 { 3821 {
3737 lock (m_entityUpdates.SyncRoot) 3822 SceneObjectPart part = (SceneObjectPart)update.Entity;
3738 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3739 break;
3740 3823
3741 EntityUpdate update = (EntityUpdate)iupdate; 3824 if (part.ParentGroup.IsDeleted)
3742 3825 continue;
3743 avgTimeDilation += update.TimeDilation;
3744 avgTimeDilation *= 0.5f;
3745 3826
3746 if (update.Entity is SceneObjectPart) 3827 if (part.ParentGroup.IsAttachment)
3828 { // Someone else's HUD, why are we getting these?
3829 if (part.ParentGroup.OwnerID != AgentId &&
3830 part.ParentGroup.RootPart.Shape.State > 30)
3831 continue;
3832 ScenePresence sp;
3833 // Owner is not in the sim, don't update it to
3834 // anyone
3835 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3836 continue;
3837
3838 List<SceneObjectGroup> atts = sp.GetAttachments();
3839 bool found = false;
3840 foreach (SceneObjectGroup att in atts)
3841 {
3842 if (att == part.ParentGroup)
3843 {
3844 found = true;
3845 break;
3846 }
3847 }
3848
3849 // It's an attachment of a valid avatar, but
3850 // doesn't seem to be attached, skip
3851 if (!found)
3852 continue;
3853
3854 // On vehicle crossing, the attachments are received
3855 // while the avatar is still a child. Don't send
3856 // updates here because the LocalId has not yet
3857 // been updated and the viewer will derender the
3858 // attachments until the avatar becomes root.
3859 if (sp.IsChildAgent)
3860 continue;
3861
3862 // If the object is an attachment we don't want it to be in the kill
3863 // record. Else attaching from inworld and subsequently dropping
3864 // it will no longer work.
3865// lock (m_killRecord)
3866// {
3867// m_killRecord.Remove(part.LocalId);
3868// m_killRecord.Remove(part.ParentGroup.RootPart.LocalId);
3869// }
3870 }
3871 else
3747 { 3872 {
3748 SceneObjectPart part = (SceneObjectPart)update.Entity;
3749
3750 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3873 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3751 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3874 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3752 // safety measure. 3875 // safety measure.
@@ -3757,241 +3880,177 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3757 // 3880 //
3758 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3881 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3759 // after the root prim has been deleted. 3882 // after the root prim has been deleted.
3760 if (m_killRecord.Contains(part.LocalId)) 3883 //
3761 { 3884 // We ignore this for attachments because attaching something from inworld breaks unless we do.
3762 // m_log.WarnFormat( 3885// lock (m_killRecord)
3763 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", 3886// {
3764 // part.LocalId, Name); 3887// if (m_killRecord.Contains(part.LocalId))
3765 continue; 3888// continue;
3766 } 3889// if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3767 3890// continue;
3768 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3891// }
3892 }
3893
3894 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3895 {
3896 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3897 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3769 { 3898 {
3770 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3899 part.Shape.LightEntry = false;
3771 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3772 {
3773 part.Shape.LightEntry = false;
3774 }
3775 } 3900 }
3776 } 3901 }
3777 3902 }
3778 #region UpdateFlags to packet type conversion 3903
3779 3904 ++updatesThisCall;
3780 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; 3905
3781 3906 #region UpdateFlags to packet type conversion
3782 bool canUseCompressed = true; 3907
3783 bool canUseImproved = true; 3908 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3784 3909
3785 // Compressed object updates only make sense for LL primitives 3910 bool canUseCompressed = true;
3786 if (!(update.Entity is SceneObjectPart)) 3911 bool canUseImproved = true;
3912
3913 // Compressed object updates only make sense for LL primitives
3914 if (!(update.Entity is SceneObjectPart))
3915 {
3916 canUseCompressed = false;
3917 }
3918
3919 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3920 {
3921 canUseCompressed = false;
3922 canUseImproved = false;
3923 }
3924 else
3925 {
3926 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3927 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3928 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3929 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3787 { 3930 {
3788 canUseCompressed = false; 3931 canUseCompressed = false;
3789 } 3932 }
3790 3933
3791 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3934 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3935 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3936 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3937 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3938 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3939 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3940 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3941 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3942 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3943 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3944 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3945 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3946 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3947 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3792 { 3948 {
3793 canUseCompressed = false;
3794 canUseImproved = false; 3949 canUseImproved = false;
3795 } 3950 }
3796 else 3951 }
3797 {
3798 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3799 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3800 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3801 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3802 {
3803 canUseCompressed = false;
3804 }
3805
3806 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3807 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3808 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3809 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3810 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3811 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3812 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3813 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3814 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3815 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3816 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3817 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3818 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3819 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3820 {
3821 canUseImproved = false;
3822 }
3823 }
3824
3825 #endregion UpdateFlags to packet type conversion
3826
3827 #region Block Construction
3828
3829 // TODO: Remove this once we can build compressed updates
3830 canUseCompressed = false;
3831 3952
3832 if (!canUseImproved && !canUseCompressed) 3953 #endregion UpdateFlags to packet type conversion
3833 {
3834 ObjectUpdatePacket.ObjectDataBlock updateBlock;
3835 3954
3836 if (update.Entity is ScenePresence) 3955 #region Block Construction
3837 {
3838 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
3839 }
3840 else
3841 {
3842 SceneObjectPart part = (SceneObjectPart)update.Entity;
3843 updateBlock = CreatePrimUpdateBlock(part, AgentId);
3844
3845 // If the part has become a private hud since the update was scheduled then we do not
3846 // want to send it to other avatars.
3847 if (part.ParentGroup.IsAttachment
3848 && part.ParentGroup.HasPrivateAttachmentPoint
3849 && part.ParentGroup.AttachedAvatar != AgentId)
3850 continue;
3851
3852 // If the part has since been deleted, then drop the update. In the case of attachments,
3853 // this is to avoid spurious updates to other viewers since post-processing of attachments
3854 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3855 // of the test above).
3856 //
3857 // Actual deletions (kills) happen in another method.
3858 if (part.ParentGroup.IsDeleted)
3859 continue;
3860 }
3861 3956
3862 objectUpdateBlocks.Value.Add(updateBlock); 3957 // TODO: Remove this once we can build compressed updates
3863 objectUpdates.Value.Add(update); 3958 canUseCompressed = false;
3864 }
3865 else if (!canUseImproved)
3866 {
3867 SceneObjectPart part = (SceneObjectPart)update.Entity;
3868 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
3869 = CreateCompressedUpdateBlock(part, updateFlags);
3870
3871 // If the part has since been deleted, then drop the update. In the case of attachments,
3872 // this is to avoid spurious updates to other viewers since post-processing of attachments
3873 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3874 // of the test above).
3875 //
3876 // Actual deletions (kills) happen in another method.
3877 if (part.ParentGroup.IsDeleted)
3878 continue;
3879 3959
3880 compressedUpdateBlocks.Value.Add(compressedBlock); 3960 if (!canUseImproved && !canUseCompressed)
3881 compressedUpdates.Value.Add(update); 3961 {
3962 if (update.Entity is ScenePresence)
3963 {
3964 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3882 } 3965 }
3883 else 3966 else
3884 { 3967 {
3885 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3968 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3886 {
3887 // Self updates go into a special list
3888 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3889 terseAgentUpdates.Value.Add(update);
3890 }
3891 else
3892 {
3893 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
3894 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
3895
3896 // Everything else goes here
3897 if (update.Entity is SceneObjectPart)
3898 {
3899 SceneObjectPart part = (SceneObjectPart)update.Entity;
3900
3901 // If the part has become a private hud since the update was scheduled then we do not
3902 // want to send it to other avatars.
3903 if (part.ParentGroup.IsAttachment
3904 && part.ParentGroup.HasPrivateAttachmentPoint
3905 && part.ParentGroup.AttachedAvatar != AgentId)
3906 continue;
3907
3908 // If the part has since been deleted, then drop the update. In the case of attachments,
3909 // this is to avoid spurious updates to other viewers since post-processing of attachments
3910 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3911 // of the test above).
3912 //
3913 // Actual deletions (kills) happen in another method.
3914 if (part.ParentGroup.IsDeleted)
3915 continue;
3916 }
3917
3918 terseUpdateBlocks.Value.Add(terseUpdateBlock);
3919 terseUpdates.Value.Add(update);
3920 }
3921 } 3969 }
3922
3923 ++updatesThisCall;
3924
3925 #endregion Block Construction
3926 } 3970 }
3927 3971 else if (!canUseImproved)
3928 #region Packet Sending 3972 {
3929 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3973 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3930 3974 }
3931 if (terseAgentUpdateBlocks.IsValueCreated) 3975 else
3932 { 3976 {
3933 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3977 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3978 // Self updates go into a special list
3979 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3980 else
3981 // Everything else goes here
3982 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3983 }
3934 3984
3935 ImprovedTerseObjectUpdatePacket packet 3985 #endregion Block Construction
3936 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3986 }
3937 3987
3938 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3988 #region Packet Sending
3939 packet.RegionData.TimeDilation = timeDilation; 3989
3940 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3990 const float TIME_DILATION = 1.0f;
3991 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3992
3993 if (terseAgentUpdateBlocks.IsValueCreated)
3994 {
3995 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3941 3996
3942 for (int i = 0; i < blocks.Count; i++) 3997 ImprovedTerseObjectUpdatePacket packet
3943 packet.ObjectData[i] = blocks[i]; 3998 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3944 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 3999 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3945 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 4000 packet.RegionData.TimeDilation = timeDilation;
3946 } 4001 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3947 4002
3948 if (objectUpdateBlocks.IsValueCreated) 4003 for (int i = 0; i < blocks.Count; i++)
3949 { 4004 packet.ObjectData[i] = blocks[i];
3950 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3951
3952 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3953 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3954 packet.RegionData.TimeDilation = timeDilation;
3955 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3956
3957 for (int i = 0; i < blocks.Count; i++)
3958 packet.ObjectData[i] = blocks[i];
3959 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3960 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3961 }
3962
3963 if (compressedUpdateBlocks.IsValueCreated)
3964 {
3965 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3966
3967 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3968 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3969 packet.RegionData.TimeDilation = timeDilation;
3970 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3971
3972 for (int i = 0; i < blocks.Count; i++)
3973 packet.ObjectData[i] = blocks[i];
3974 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3975 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3976 }
3977 4005
3978 if (terseUpdateBlocks.IsValueCreated) 4006 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3979 { 4007 }
3980 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3981
3982 ImprovedTerseObjectUpdatePacket packet
3983 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
3984 PacketType.ImprovedTerseObjectUpdate);
3985 4008
3986 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4009 if (objectUpdateBlocks.IsValueCreated)
3987 packet.RegionData.TimeDilation = timeDilation; 4010 {
3988 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4011 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3989 4012
3990 for (int i = 0; i < blocks.Count; i++) 4013 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3991 packet.ObjectData[i] = blocks[i]; 4014 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3992 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4015 packet.RegionData.TimeDilation = timeDilation;
3993 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4016 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3994 } 4017
4018 for (int i = 0; i < blocks.Count; i++)
4019 packet.ObjectData[i] = blocks[i];
4020
4021 OutPacket(packet, ThrottleOutPacketType.Task, true);
4022 }
4023
4024 if (compressedUpdateBlocks.IsValueCreated)
4025 {
4026 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4027
4028 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4029 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4030 packet.RegionData.TimeDilation = timeDilation;
4031 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4032
4033 for (int i = 0; i < blocks.Count; i++)
4034 packet.ObjectData[i] = blocks[i];
4035
4036 OutPacket(packet, ThrottleOutPacketType.Task, true);
4037 }
4038
4039 if (terseUpdateBlocks.IsValueCreated)
4040 {
4041 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4042
4043 ImprovedTerseObjectUpdatePacket packet
4044 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4045 PacketType.ImprovedTerseObjectUpdate);
4046 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4047 packet.RegionData.TimeDilation = timeDilation;
4048 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4049
4050 for (int i = 0; i < blocks.Count; i++)
4051 packet.ObjectData[i] = blocks[i];
4052
4053 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3995 } 4054 }
3996 4055
3997 #endregion Packet Sending 4056 #endregion Packet Sending
@@ -4284,11 +4343,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4284 4343
4285 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4344 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4286 // of the object rather than the properties when the packet was created 4345 // of the object rather than the properties when the packet was created
4287 OutPacket(packet, ThrottleOutPacketType.Task, true, 4346 // HACK : Remove intelligent resending until it's fixed in core
4288 delegate(OutgoingPacket oPacket) 4347 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4289 { 4348 // delegate(OutgoingPacket oPacket)
4290 ResendPropertyUpdates(updates, oPacket); 4349 // {
4291 }); 4350 // ResendPropertyUpdates(updates, oPacket);
4351 // });
4352 OutPacket(packet, ThrottleOutPacketType.Task, true);
4292 4353
4293 // pbcnt += blocks.Count; 4354 // pbcnt += blocks.Count;
4294 // ppcnt++; 4355 // ppcnt++;
@@ -4314,11 +4375,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4314 // of the object rather than the properties when the packet was created 4375 // of the object rather than the properties when the packet was created
4315 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4376 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4316 updates.Add(familyUpdates.Value[i]); 4377 updates.Add(familyUpdates.Value[i]);
4317 OutPacket(packet, ThrottleOutPacketType.Task, true, 4378 // HACK : Remove intelligent resending until it's fixed in core
4318 delegate(OutgoingPacket oPacket) 4379 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4319 { 4380 // delegate(OutgoingPacket oPacket)
4320 ResendPropertyUpdates(updates, oPacket); 4381 // {
4321 }); 4382 // ResendPropertyUpdates(updates, oPacket);
4383 // });
4384 OutPacket(packet, ThrottleOutPacketType.Task, true);
4322 4385
4323 // fpcnt++; 4386 // fpcnt++;
4324 // fbcnt++; 4387 // fbcnt++;
@@ -4690,7 +4753,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4690 4753
4691 if (landData.SimwideArea > 0) 4754 if (landData.SimwideArea > 0)
4692 { 4755 {
4693 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4756 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
4757 // Never report more than sim total capacity
4758 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4759 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4694 updateMessage.SimWideMaxPrims = simulatorCapacity; 4760 updateMessage.SimWideMaxPrims = simulatorCapacity;
4695 } 4761 }
4696 else 4762 else
@@ -4819,14 +4885,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4819 4885
4820 if (notifyCount > 0) 4886 if (notifyCount > 0)
4821 { 4887 {
4822 if (notifyCount > 32) 4888// if (notifyCount > 32)
4823 { 4889// {
4824 m_log.InfoFormat( 4890// m_log.InfoFormat(
4825 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4891// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4826 + " - a developer might want to investigate whether this is a hard limit", 32); 4892// + " - a developer might want to investigate whether this is a hard limit", 32);
4827 4893//
4828 notifyCount = 32; 4894// notifyCount = 32;
4829 } 4895// }
4830 4896
4831 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4897 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4832 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4898 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4881,9 +4947,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4881 { 4947 {
4882 ScenePresence presence = (ScenePresence)entity; 4948 ScenePresence presence = (ScenePresence)entity;
4883 4949
4950 position = presence.OffsetPosition;
4951 rotation = presence.Rotation;
4952
4953 if (presence.ParentID != 0)
4954 {
4955 SceneObjectPart part = m_scene.GetSceneObjectPart(presence.ParentID);
4956 if (part != null && part != part.ParentGroup.RootPart)
4957 {
4958 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4959 rotation = part.RotationOffset * presence.Rotation;
4960 }
4961 }
4962
4884 attachPoint = 0; 4963 attachPoint = 0;
4885 collisionPlane = presence.CollisionPlane; 4964 collisionPlane = presence.CollisionPlane;
4886 position = presence.OffsetPosition;
4887 velocity = presence.Velocity; 4965 velocity = presence.Velocity;
4888 acceleration = Vector3.Zero; 4966 acceleration = Vector3.Zero;
4889 4967
@@ -4893,7 +4971,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4893// acceleration = new Vector3(1, 0, 0); 4971// acceleration = new Vector3(1, 0, 0);
4894 4972
4895 angularVelocity = Vector3.Zero; 4973 angularVelocity = Vector3.Zero;
4896 rotation = presence.Rotation;
4897 4974
4898 if (sendTexture) 4975 if (sendTexture)
4899 textureEntry = presence.Appearance.Texture.GetBytes(); 4976 textureEntry = presence.Appearance.Texture.GetBytes();
@@ -5000,13 +5077,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5000 5077
5001 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5078 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5002 { 5079 {
5080 Vector3 offsetPosition = data.OffsetPosition;
5081 Quaternion rotation = data.Rotation;
5082 uint parentID = data.ParentID;
5083
5084 if (parentID != 0)
5085 {
5086 SceneObjectPart part = m_scene.GetSceneObjectPart(parentID);
5087 if (part != null && part != part.ParentGroup.RootPart)
5088 {
5089 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
5090 rotation = part.RotationOffset * data.Rotation;
5091 parentID = part.ParentGroup.RootPart.LocalId;
5092 }
5093 }
5094
5003 byte[] objectData = new byte[76]; 5095 byte[] objectData = new byte[76];
5004 5096
5005 data.CollisionPlane.ToBytes(objectData, 0); 5097 data.CollisionPlane.ToBytes(objectData, 0);
5006 data.OffsetPosition.ToBytes(objectData, 16); 5098 offsetPosition.ToBytes(objectData, 16);
5007// data.Velocity.ToBytes(objectData, 28); 5099// data.Velocity.ToBytes(objectData, 28);
5008// data.Acceleration.ToBytes(objectData, 40); 5100// data.Acceleration.ToBytes(objectData, 40);
5009 data.Rotation.ToBytes(objectData, 52); 5101 rotation.ToBytes(objectData, 52);
5010 //data.AngularVelocity.ToBytes(objectData, 64); 5102 //data.AngularVelocity.ToBytes(objectData, 64);
5011 5103
5012 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5104 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5020,7 +5112,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5020 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5112 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5021 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5113 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5022 update.ObjectData = objectData; 5114 update.ObjectData = objectData;
5023 update.ParentID = data.ParentID; 5115 update.ParentID = parentID;
5024 update.PathCurve = 16; 5116 update.PathCurve = 16;
5025 update.PathScaleX = 100; 5117 update.PathScaleX = 100;
5026 update.PathScaleY = 100; 5118 update.PathScaleY = 100;
@@ -5038,10 +5130,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5038 update.TextureEntry = Utils.EmptyBytes; 5130 update.TextureEntry = Utils.EmptyBytes;
5039// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5131// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5040 5132
5133/* 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)
5041 update.UpdateFlags = (uint)( 5134 update.UpdateFlags = (uint)(
5042 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5135 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5043 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5136 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5044 PrimFlags.ObjectOwnerModify); 5137 PrimFlags.ObjectOwnerModify);
5138*/
5139 update.UpdateFlags = 0;
5045 5140
5046 return update; 5141 return update;
5047 } 5142 }
@@ -5365,6 +5460,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5365 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5460 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5366 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5461 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5367 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5462 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5463 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5368 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5464 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5369 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5465 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5370 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5466 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5431,6 +5527,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5431 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5527 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5432 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5528 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5433 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5529 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5530 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5434 5531
5435 AddGenericPacketHandler("autopilot", HandleAutopilot); 5532 AddGenericPacketHandler("autopilot", HandleAutopilot);
5436 } 5533 }
@@ -5469,6 +5566,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5469 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || 5566 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5470 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || 5567 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5471 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || 5568 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5569 (x.ControlFlags != 0) ||
5472 (x.Far != m_lastAgentUpdateArgs.Far) || 5570 (x.Far != m_lastAgentUpdateArgs.Far) ||
5473 (x.Flags != m_lastAgentUpdateArgs.Flags) || 5571 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5474 (x.State != m_lastAgentUpdateArgs.State) || 5572 (x.State != m_lastAgentUpdateArgs.State) ||
@@ -6367,6 +6465,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6367 { 6465 {
6368 handlerCompleteMovementToRegion(sender, true); 6466 handlerCompleteMovementToRegion(sender, true);
6369 } 6467 }
6468 else
6469 m_log.Debug("HandleCompleteAgentMovement NULL handler");
6470
6370 handlerCompleteMovementToRegion = null; 6471 handlerCompleteMovementToRegion = null;
6371 6472
6372 return true; 6473 return true;
@@ -6384,7 +6485,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6384 return true; 6485 return true;
6385 } 6486 }
6386 #endregion 6487 #endregion
6387 6488/*
6388 StartAnim handlerStartAnim = null; 6489 StartAnim handlerStartAnim = null;
6389 StopAnim handlerStopAnim = null; 6490 StopAnim handlerStopAnim = null;
6390 6491
@@ -6408,6 +6509,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6408 } 6509 }
6409 } 6510 }
6410 return true; 6511 return true;
6512*/
6513 ChangeAnim handlerChangeAnim = null;
6514
6515 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6516 {
6517 handlerChangeAnim = OnChangeAnim;
6518 if (handlerChangeAnim != null)
6519 {
6520 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
6521 }
6522 }
6523
6524 handlerChangeAnim = OnChangeAnim;
6525 if (handlerChangeAnim != null)
6526 {
6527 handlerChangeAnim(UUID.Zero, false, true);
6528 }
6529
6530 return true;
6411 } 6531 }
6412 6532
6413 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 6533 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -7033,10 +7153,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7033 // 46,47,48 are special positions within the packet 7153 // 46,47,48 are special positions within the packet
7034 // This may change so perhaps we need a better way 7154 // This may change so perhaps we need a better way
7035 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) 7155 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
7036 bool UsePhysics = (data[46] != 0) ? true : false; 7156 /*
7037 bool IsTemporary = (data[47] != 0) ? true : false; 7157 bool UsePhysics = (data[46] != 0) ? true : false;
7038 bool IsPhantom = (data[48] != 0) ? true : false; 7158 bool IsTemporary = (data[47] != 0) ? true : false;
7039 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); 7159 bool IsPhantom = (data[48] != 0) ? true : false;
7160 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
7161 */
7162 bool UsePhysics = flags.AgentData.UsePhysics;
7163 bool IsPhantom = flags.AgentData.IsPhantom;
7164 bool IsTemporary = flags.AgentData.IsTemporary;
7165 ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics;
7166 ExtraPhysicsData physdata = new ExtraPhysicsData();
7167
7168 if (blocks == null || blocks.Length == 0)
7169 {
7170 physdata.PhysShapeType = PhysShapeType.invalid;
7171 }
7172 else
7173 {
7174 ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0];
7175 physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType;
7176 physdata.Bounce = phsblock.Restitution;
7177 physdata.Density = phsblock.Density;
7178 physdata.Friction = phsblock.Friction;
7179 physdata.GravitationModifier = phsblock.GravityMultiplier;
7180 }
7181
7182 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
7040 } 7183 }
7041 return true; 7184 return true;
7042 } 7185 }
@@ -8637,16 +8780,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8637 8780
8638 #region Parcel related packets 8781 #region Parcel related packets
8639 8782
8783 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
8784 // to be done with minimal resources as possible
8785 // variables temporary here while in test
8786
8787 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
8788 bool RegionHandleRequestsInService = false;
8789
8640 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 8790 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
8641 { 8791 {
8642 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 8792 UUID currentUUID;
8643 8793
8644 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 8794 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
8645 if (handlerRegionHandleRequest != null) 8795
8796 if (handlerRegionHandleRequest == null)
8797 return true;
8798
8799 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
8800
8801 lock (RegionHandleRequests)
8646 { 8802 {
8647 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 8803 if (RegionHandleRequestsInService)
8804 {
8805 // we are already busy doing a previus request
8806 // so enqueue it
8807 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
8808 return true;
8809 }
8810
8811 // else do it
8812 currentUUID = rhrPack.RequestBlock.RegionID;
8813 RegionHandleRequestsInService = true;
8648 } 8814 }
8649 return true; 8815
8816 while (true)
8817 {
8818 handlerRegionHandleRequest(this, currentUUID);
8819
8820 lock (RegionHandleRequests)
8821 {
8822 // exit condition, nothing to do or closed
8823 // current code seems to assume we may loose the handler at anytime,
8824 // so keep checking it
8825 handlerRegionHandleRequest = OnRegionHandleRequest;
8826
8827 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
8828 {
8829 RegionHandleRequests.Clear();
8830 RegionHandleRequestsInService = false;
8831 return true;
8832 }
8833 currentUUID = RegionHandleRequests.Dequeue();
8834 }
8835 }
8836
8837 return true; // actually unreached
8650 } 8838 }
8651 8839
8652 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 8840 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -9902,7 +10090,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9902 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10090 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9903 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10091 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9904 UpdateMuteListEntry.MuteData.MuteType, 10092 UpdateMuteListEntry.MuteData.MuteType,
9905 UpdateMuteListEntry.AgentData.AgentID); 10093 UpdateMuteListEntry.MuteData.MuteFlags);
9906 return true; 10094 return true;
9907 } 10095 }
9908 return false; 10096 return false;
@@ -9917,8 +10105,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9917 { 10105 {
9918 handlerRemoveMuteListEntry(this, 10106 handlerRemoveMuteListEntry(this,
9919 RemoveMuteListEntry.MuteData.MuteID, 10107 RemoveMuteListEntry.MuteData.MuteID,
9920 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10108 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9921 RemoveMuteListEntry.AgentData.AgentID);
9922 return true; 10109 return true;
9923 } 10110 }
9924 return false; 10111 return false;
@@ -9962,10 +10149,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9962 return false; 10149 return false;
9963 } 10150 }
9964 10151
10152 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10153 {
10154 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10155 (ChangeInventoryItemFlagsPacket)packet;
10156 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10157 if (handlerChangeInventoryItemFlags != null)
10158 {
10159 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10160 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10161 return true;
10162 }
10163 return false;
10164 }
10165
9965 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10166 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9966 { 10167 {
9967 return true; 10168 return true;
9968 } 10169 }
10170
10171 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10172 {
10173 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10174
10175 #region Packet Session and User Check
10176 if (m_checkPackets)
10177 {
10178 if (packet.AgentData.SessionID != SessionId ||
10179 packet.AgentData.AgentID != AgentId)
10180 return true;
10181 }
10182 #endregion
10183 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10184 List<InventoryItemBase> items = new List<InventoryItemBase>();
10185 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10186 {
10187 InventoryItemBase b = new InventoryItemBase();
10188 b.ID = n.OldItemID;
10189 b.Folder = n.OldFolderID;
10190 items.Add(b);
10191 }
10192
10193 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10194 if (handlerMoveItemsAndLeaveCopy != null)
10195 {
10196 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10197 }
10198
10199 return true;
10200 }
9969 10201
9970 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10202 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9971 { 10203 {
@@ -10392,6 +10624,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10392 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10624 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10393 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10625 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10394 10626
10627 Scene scene = (Scene)m_scene;
10628 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10629 {
10630 ScenePresence p;
10631 if (scene.TryGetScenePresence(sender.AgentId, out p))
10632 {
10633 if (p.GodLevel >= 200)
10634 {
10635 groupProfileReply.GroupData.OpenEnrollment = true;
10636 groupProfileReply.GroupData.MembershipFee = 0;
10637 }
10638 }
10639 }
10640
10395 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10641 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10396 } 10642 }
10397 return true; 10643 return true;
@@ -10965,11 +11211,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10965 11211
10966 StartLure handlerStartLure = OnStartLure; 11212 StartLure handlerStartLure = OnStartLure;
10967 if (handlerStartLure != null) 11213 if (handlerStartLure != null)
10968 handlerStartLure(startLureRequest.Info.LureType, 11214 {
10969 Utils.BytesToString( 11215 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10970 startLureRequest.Info.Message), 11216 {
10971 startLureRequest.TargetData[0].TargetID, 11217 handlerStartLure(startLureRequest.Info.LureType,
10972 this); 11218 Utils.BytesToString(
11219 startLureRequest.Info.Message),
11220 startLureRequest.TargetData[i].TargetID,
11221 this);
11222 }
11223 }
10973 return true; 11224 return true;
10974 } 11225 }
10975 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11226 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11083,10 +11334,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11083 } 11334 }
11084 #endregion 11335 #endregion
11085 11336
11086 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11337 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11087 if (handlerClassifiedGodDelete != null) 11338 if (handlerClassifiedGodDelete != null)
11088 handlerClassifiedGodDelete( 11339 handlerClassifiedGodDelete(
11089 classifiedGodDelete.Data.ClassifiedID, 11340 classifiedGodDelete.Data.ClassifiedID,
11341 classifiedGodDelete.Data.QueryID,
11090 this); 11342 this);
11091 return true; 11343 return true;
11092 } 11344 }
@@ -11452,209 +11704,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11452 } 11704 }
11453 else 11705 else
11454 { 11706 {
11455// m_log.DebugFormat( 11707 ClientChangeObject updatehandler = onClientChangeObject;
11456// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
11457// i, block.Type, part.Name, part.LocalId);
11458 11708
11459// // Do this once since fetch parts creates a new array. 11709 if (updatehandler != null)
11460// SceneObjectPart[] parts = part.ParentGroup.Parts; 11710 {
11461// for (int j = 0; j < parts.Length; j++) 11711 ObjectChangeData udata = new ObjectChangeData();
11462// {
11463// part.StoreUndoState();
11464// parts[j].IgnoreUndoUpdate = true;
11465// }
11466 11712
11467 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 11713 /*ubit from ll JIRA:
11714 * 0x01 position
11715 * 0x02 rotation
11716 * 0x04 scale
11717
11718 * 0x08 LINK_SET
11719 * 0x10 UNIFORM for scale
11720 */
11468 11721
11469 switch (block.Type) 11722 // translate to internal changes
11470 { 11723 // not all cases .. just the ones older code did
11471 case 1:
11472 Vector3 pos1 = new Vector3(block.Data, 0);
11473 11724
11474 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11725 switch (block.Type)
11475 if (handlerUpdatePrimSinglePosition != null) 11726 {
11476 { 11727 case 1: //change position sp
11477 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11728 udata.position = new Vector3(block.Data, 0);
11478 handlerUpdatePrimSinglePosition(localId, pos1, this);
11479 }
11480 break;
11481 11729
11482 case 2: 11730 udata.change = ObjectChangeType.primP;
11483 Quaternion rot1 = new Quaternion(block.Data, 0, true); 11731 updatehandler(localId, udata, this);
11732 break;
11484 11733
11485 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 11734 case 2: // rotation sp
11486 if (handlerUpdatePrimSingleRotation != null) 11735 udata.rotation = new Quaternion(block.Data, 0, true);
11487 {
11488 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
11489 handlerUpdatePrimSingleRotation(localId, rot1, this);
11490 }
11491 break;
11492 11736
11493 case 3: 11737 udata.change = ObjectChangeType.primR;
11494 Vector3 rotPos = new Vector3(block.Data, 0); 11738 updatehandler(localId, udata, this);
11495 Quaternion rot2 = new Quaternion(block.Data, 12, true); 11739 break;
11496 11740
11497 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 11741 case 3: // position plus rotation
11498 if (handlerUpdatePrimSingleRotationPosition != null) 11742 udata.position = new Vector3(block.Data, 0);
11499 { 11743 udata.rotation = new Quaternion(block.Data, 12, true);
11500 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
11501 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
11502 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
11503 }
11504 break;
11505 11744
11506 case 4: 11745 udata.change = ObjectChangeType.primPR;
11507 case 20: 11746 updatehandler(localId, udata, this);
11508 Vector3 scale4 = new Vector3(block.Data, 0); 11747 break;
11509 11748
11510 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 11749 case 4: // scale sp
11511 if (handlerUpdatePrimScale != null) 11750 udata.scale = new Vector3(block.Data, 0);
11512 { 11751 udata.change = ObjectChangeType.primS;
11513 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
11514 handlerUpdatePrimScale(localId, scale4, this);
11515 }
11516 break;
11517 11752
11518 case 5: 11753 updatehandler(localId, udata, this);
11519 Vector3 scale1 = new Vector3(block.Data, 12); 11754 break;
11520 Vector3 pos11 = new Vector3(block.Data, 0);
11521 11755
11522 handlerUpdatePrimScale = OnUpdatePrimScale; 11756 case 0x14: // uniform scale sp
11523 if (handlerUpdatePrimScale != null) 11757 udata.scale = new Vector3(block.Data, 0);
11524 {
11525 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11526 handlerUpdatePrimScale(localId, scale1, this);
11527 11758
11528 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11759 udata.change = ObjectChangeType.primUS;
11529 if (handlerUpdatePrimSinglePosition != null) 11760 updatehandler(localId, udata, this);
11530 { 11761 break;
11531 handlerUpdatePrimSinglePosition(localId, pos11, this);
11532 }
11533 }
11534 break;
11535 11762
11536 case 9: 11763 case 5: // scale and position sp
11537 Vector3 pos2 = new Vector3(block.Data, 0); 11764 udata.position = new Vector3(block.Data, 0);
11765 udata.scale = new Vector3(block.Data, 12);
11538 11766
11539 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 11767 udata.change = ObjectChangeType.primPS;
11768 updatehandler(localId, udata, this);
11769 break;
11540 11770
11541 if (handlerUpdateVector != null) 11771 case 0x15: //uniform scale and position
11542 { 11772 udata.position = new Vector3(block.Data, 0);
11543 handlerUpdateVector(localId, pos2, this); 11773 udata.scale = new Vector3(block.Data, 12);
11544 }
11545 break;
11546 11774
11547 case 10: 11775 udata.change = ObjectChangeType.primPUS;
11548 Quaternion rot3 = new Quaternion(block.Data, 0, true); 11776 updatehandler(localId, udata, this);
11777 break;
11549 11778
11550 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 11779 // now group related (bit 4)
11551 if (handlerUpdatePrimRotation != null) 11780 case 9: //( 8 + 1 )group position
11552 { 11781 udata.position = new Vector3(block.Data, 0);
11553 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11554 handlerUpdatePrimRotation(localId, rot3, this);
11555 }
11556 break;
11557 11782
11558 case 11: 11783 udata.change = ObjectChangeType.groupP;
11559 Vector3 pos3 = new Vector3(block.Data, 0); 11784 updatehandler(localId, udata, this);
11560 Quaternion rot4 = new Quaternion(block.Data, 12, true); 11785 break;
11561 11786
11562 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 11787 case 0x0A: // (8 + 2) group rotation
11563 if (handlerUpdatePrimGroupRotation != null) 11788 udata.rotation = new Quaternion(block.Data, 0, true);
11564 {
11565 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11566 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11567 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
11568 }
11569 break;
11570 case 12:
11571 case 28:
11572 Vector3 scale7 = new Vector3(block.Data, 0);
11573 11789
11574 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11790 udata.change = ObjectChangeType.groupR;
11575 if (handlerUpdatePrimGroupScale != null) 11791 updatehandler(localId, udata, this);
11576 { 11792 break;
11577 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11578 handlerUpdatePrimGroupScale(localId, scale7, this);
11579 }
11580 break;
11581 11793
11582 case 13: 11794 case 0x0B: //( 8 + 2 + 1) group rotation and position
11583 Vector3 scale2 = new Vector3(block.Data, 12); 11795 udata.position = new Vector3(block.Data, 0);
11584 Vector3 pos4 = new Vector3(block.Data, 0); 11796 udata.rotation = new Quaternion(block.Data, 12, true);
11585 11797
11586 handlerUpdatePrimScale = OnUpdatePrimScale; 11798 udata.change = ObjectChangeType.groupPR;
11587 if (handlerUpdatePrimScale != null) 11799 updatehandler(localId, udata, this);
11588 { 11800 break;
11589 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11590 handlerUpdatePrimScale(localId, scale2, this);
11591 11801
11592 // Change the position based on scale (for bug number 246) 11802 case 0x0C: // (8 + 4) group scale
11593 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11803 // only afects root prim and only sent by viewer editor object tab scaling
11594 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11804 // mouse edition only allows uniform scaling
11595 if (handlerUpdatePrimSinglePosition != null) 11805 // SL MAY CHANGE THIS in viewers
11596 {
11597 handlerUpdatePrimSinglePosition(localId, pos4, this);
11598 }
11599 }
11600 break;
11601 11806
11602 case 29: 11807 udata.scale = new Vector3(block.Data, 0);
11603 Vector3 scale5 = new Vector3(block.Data, 12);
11604 Vector3 pos5 = new Vector3(block.Data, 0);
11605 11808
11606 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11809 udata.change = ObjectChangeType.groupS;
11607 if (handlerUpdatePrimGroupScale != null) 11810 updatehandler(localId, udata, this);
11608 {
11609 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11610 part.StoreUndoState(true);
11611 part.IgnoreUndoUpdate = true;
11612 handlerUpdatePrimGroupScale(localId, scale5, this);
11613 handlerUpdateVector = OnUpdatePrimGroupPosition;
11614 11811
11615 if (handlerUpdateVector != null) 11812 break;
11616 {
11617 handlerUpdateVector(localId, pos5, this);
11618 }
11619 11813
11620 part.IgnoreUndoUpdate = false; 11814 case 0x0D: //(8 + 4 + 1) group scale and position
11621 } 11815 // exception as above
11622 11816
11623 break; 11817 udata.position = new Vector3(block.Data, 0);
11818 udata.scale = new Vector3(block.Data, 12);
11624 11819
11625 case 21: 11820 udata.change = ObjectChangeType.groupPS;
11626 Vector3 scale6 = new Vector3(block.Data, 12); 11821 updatehandler(localId, udata, this);
11627 Vector3 pos6 = new Vector3(block.Data, 0); 11822 break;
11628 11823
11629 handlerUpdatePrimScale = OnUpdatePrimScale; 11824 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
11630 if (handlerUpdatePrimScale != null) 11825 udata.scale = new Vector3(block.Data, 0);
11631 {
11632 part.StoreUndoState(false);
11633 part.IgnoreUndoUpdate = true;
11634 11826
11635 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11827 udata.change = ObjectChangeType.groupUS;
11636 handlerUpdatePrimScale(localId, scale6, this); 11828 updatehandler(localId, udata, this);
11637 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11829 break;
11638 if (handlerUpdatePrimSinglePosition != null)
11639 {
11640 handlerUpdatePrimSinglePosition(localId, pos6, this);
11641 }
11642 11830
11643 part.IgnoreUndoUpdate = false; 11831 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
11644 } 11832 udata.position = new Vector3(block.Data, 0);
11645 break; 11833 udata.scale = new Vector3(block.Data, 12);
11646 11834
11647 default: 11835 udata.change = ObjectChangeType.groupPUS;
11648 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 11836 updatehandler(localId, udata, this);
11649 break; 11837 break;
11838
11839 default:
11840 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
11841 break;
11842 }
11650 } 11843 }
11651 11844
11652// for (int j = 0; j < parts.Length; j++)
11653// parts[j].IgnoreUndoUpdate = false;
11654 } 11845 }
11655 } 11846 }
11656 } 11847 }
11657
11658 return true; 11848 return true;
11659 } 11849 }
11660 11850
@@ -12102,7 +12292,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12102// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 12292// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12103// requestID, taskID, (SourceType)sourceType, Name); 12293// requestID, taskID, (SourceType)sourceType, Name);
12104 12294
12295
12296 //Note, the bool returned from the below function is useless since it is always false.
12105 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12297 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12298
12106 } 12299 }
12107 12300
12108 /// <summary> 12301 /// <summary>
@@ -12168,7 +12361,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12168 /// <returns></returns> 12361 /// <returns></returns>
12169 private static int CalculateNumPackets(byte[] data) 12362 private static int CalculateNumPackets(byte[] data)
12170 { 12363 {
12171 const uint m_maxPacketSize = 600; 12364// const uint m_maxPacketSize = 600;
12365 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12172 int numPackets = 1; 12366 int numPackets = 1;
12173 12367
12174 if (data == null) 12368 if (data == null)
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
index 8963756..c472176 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPClient.cs
@@ -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
@@ -440,6 +441,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
440 if (category >= 0 && category < m_packetOutboxes.Length) 441 if (category >= 0 && category < m_packetOutboxes.Length)
441 { 442 {
442 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category]; 443 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue = m_packetOutboxes[category];
444
445 if (m_deliverPackets == false)
446 {
447 queue.Enqueue(packet);
448 return true;
449 }
450
443 TokenBucket bucket = m_throttleCategories[category]; 451 TokenBucket bucket = m_throttleCategories[category];
444 452
445 // Don't send this packet if there is already a packet waiting in the queue 453 // Don't send this packet if there is already a packet waiting in the queue
@@ -489,7 +497,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
489 /// <returns>True if any packets were sent, otherwise false</returns> 497 /// <returns>True if any packets were sent, otherwise false</returns>
490 public bool DequeueOutgoing() 498 public bool DequeueOutgoing()
491 { 499 {
492 OutgoingPacket packet; 500 if (m_deliverPackets == false) return false;
501
502 OutgoingPacket packet = null;
493 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue; 503 OpenSim.Framework.LocklessQueue<OutgoingPacket> queue;
494 TokenBucket bucket; 504 TokenBucket bucket;
495 bool packetSent = false; 505 bool packetSent = false;
@@ -521,32 +531,49 @@ namespace OpenSim.Region.ClientStack.LindenUDP
521 // No dequeued packet waiting to be sent, try to pull one off 531 // No dequeued packet waiting to be sent, try to pull one off
522 // this queue 532 // this queue
523 queue = m_packetOutboxes[i]; 533 queue = m_packetOutboxes[i];
524 if (queue.Dequeue(out packet)) 534 if (queue != null)
525 { 535 {
526 // A packet was pulled off the queue. See if we have 536 bool success = false;
527 // enough tokens in the bucket to send it out 537 try
528 if (bucket.RemoveTokens(packet.Buffer.DataLength))
529 { 538 {
530 // Send the packet 539 success = queue.Dequeue(out packet);
531 m_udpServer.SendPacketFinal(packet);
532 packetSent = true;
533 } 540 }
534 else 541 catch
535 { 542 {
536 // Save the dequeued packet for the next iteration 543 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
537 m_nextPackets[i] = packet;
538 } 544 }
539 545 if (success)
540 // If the queue is empty after this dequeue, fire the queue 546 {
541 // empty callback now so it has a chance to fill before we 547 // A packet was pulled off the queue. See if we have
542 // get back here 548 // enough tokens in the bucket to send it out
543 if (queue.Count == 0) 549 if (bucket.RemoveTokens(packet.Buffer.DataLength))
550 {
551 // Send the packet
552 m_udpServer.SendPacketFinal(packet);
553 packetSent = true;
554 }
555 else
556 {
557 // Save the dequeued packet for the next iteration
558 m_nextPackets[i] = packet;
559 }
560
561 // If the queue is empty after this dequeue, fire the queue
562 // empty callback now so it has a chance to fill before we
563 // get back here
564 if (queue.Count == 0)
565 emptyCategories |= CategoryToFlag(i);
566 }
567 else
568 {
569 // No packets in this queue. Fire the queue empty callback
570 // if it has not been called recently
544 emptyCategories |= CategoryToFlag(i); 571 emptyCategories |= CategoryToFlag(i);
572 }
545 } 573 }
546 else 574 else
547 { 575 {
548 // No packets in this queue. Fire the queue empty callback 576 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
549 // if it has not been called recently
550 emptyCategories |= CategoryToFlag(i); 577 emptyCategories |= CategoryToFlag(i);
551 } 578 }
552 } 579 }
@@ -704,4 +731,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP
704 } 731 }
705 } 732 }
706 } 733 }
707} \ No newline at end of file 734}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
index 419de66..df4bbb3 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs
@@ -113,7 +113,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
113 /// <summary>Handlers for incoming packets</summary> 113 /// <summary>Handlers for incoming packets</summary>
114 //PacketEventDictionary packetEvents = new PacketEventDictionary(); 114 //PacketEventDictionary packetEvents = new PacketEventDictionary();
115 /// <summary>Incoming packets that are awaiting handling</summary> 115 /// <summary>Incoming packets that are awaiting handling</summary>
116 private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>(); 116 //private OpenMetaverse.BlockingQueue<IncomingPacket> packetInbox = new OpenMetaverse.BlockingQueue<IncomingPacket>();
117
118 private DoubleQueue<IncomingPacket> packetInbox = new DoubleQueue<IncomingPacket>();
117 119
118 /// <summary></summary> 120 /// <summary></summary>
119 //private UDPClientCollection m_clients = new UDPClientCollection(); 121 //private UDPClientCollection m_clients = new UDPClientCollection();
@@ -168,6 +170,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
168 /// <summary>Flag to signal when clients should send pings</summary> 170 /// <summary>Flag to signal when clients should send pings</summary>
169 protected bool m_sendPing; 171 protected bool m_sendPing;
170 172
173 private ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>> m_pendingCache = new ExpiringCache<IPEndPoint, Queue<UDPPacketBuffer>>();
171 private Pool<IncomingPacket> m_incomingPacketPool; 174 private Pool<IncomingPacket> m_incomingPacketPool;
172 175
173 private int m_defaultRTO = 0; 176 private int m_defaultRTO = 0;
@@ -891,21 +894,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP
891 894
892 #region Packet to Client Mapping 895 #region Packet to Client Mapping
893 896
894 // UseCircuitCode handling 897 // If there is already a client for this endpoint, don't process UseCircuitCode
895 if (packet.Type == PacketType.UseCircuitCode) 898 IClientAPI client = null;
899 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
896 { 900 {
897 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 901 // UseCircuitCode handling
898 // buffer. 902 if (packet.Type == PacketType.UseCircuitCode)
899 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 903 {
904 // And if there is a UseCircuitCode pending, also drop it
905 lock (m_pendingCache)
906 {
907 if (m_pendingCache.Contains(endPoint))
908 return;
900 909
901 Util.FireAndForget(HandleUseCircuitCode, array); 910 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
911 }
902 912
903 return; 913 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
914 // buffer.
915 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
916
917 Util.FireAndForget(HandleUseCircuitCode, array);
918
919 return;
920 }
921 }
922
923 // If this is a pending connection, enqueue, don't process yet
924 lock (m_pendingCache)
925 {
926 Queue<UDPPacketBuffer> queue;
927 if (m_pendingCache.TryGetValue(endPoint, out queue))
928 {
929 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
930 queue.Enqueue(buffer);
931 return;
932 }
904 } 933 }
905 934
906 // Determine which agent this packet came from 935 // Determine which agent this packet came from
907 IClientAPI client; 936 if (client == null || !(client is LLClientView))
908 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
909 { 937 {
910 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 938 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
911 return; 939 return;
@@ -914,7 +942,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
914 udpClient = ((LLClientView)client).UDPClient; 942 udpClient = ((LLClientView)client).UDPClient;
915 943
916 if (!udpClient.IsConnected) 944 if (!udpClient.IsConnected)
945 {
946// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
917 return; 947 return;
948 }
918 949
919 #endregion Packet to Client Mapping 950 #endregion Packet to Client Mapping
920 951
@@ -1044,7 +1075,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1044 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1075 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1045 } 1076 }
1046 1077
1047 packetInbox.Enqueue(incomingPacket); 1078 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1079 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1080 packetInbox.EnqueueHigh(incomingPacket);
1081 else
1082 packetInbox.EnqueueLow(incomingPacket);
1048 } 1083 }
1049 1084
1050 #region BinaryStats 1085 #region BinaryStats
@@ -1164,6 +1199,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1164 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1199 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1165 if (client != null) 1200 if (client != null)
1166 client.SceneAgent.SendInitialDataToMe(); 1201 client.SceneAgent.SendInitialDataToMe();
1202
1203 // Now we know we can handle more data
1204 Thread.Sleep(200);
1205
1206 // Obtain the queue and remove it from the cache
1207 Queue<UDPPacketBuffer> queue = null;
1208
1209 lock (m_pendingCache)
1210 {
1211 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1212 {
1213 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1214 return;
1215 }
1216 m_pendingCache.Remove(endPoint);
1217 }
1218
1219 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1220
1221 // Reinject queued packets
1222 while(queue.Count > 0)
1223 {
1224 UDPPacketBuffer buf = queue.Dequeue();
1225 PacketReceived(buf);
1226 }
1227 queue = null;
1167 } 1228 }
1168 else 1229 else
1169 { 1230 {
@@ -1171,6 +1232,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1171 m_log.WarnFormat( 1232 m_log.WarnFormat(
1172 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1233 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1173 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1234 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1235 lock (m_pendingCache)
1236 m_pendingCache.Remove(endPoint);
1174 } 1237 }
1175 1238
1176 // m_log.DebugFormat( 1239 // m_log.DebugFormat(
@@ -1289,7 +1352,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1289 if (!client.SceneAgent.IsChildAgent) 1352 if (!client.SceneAgent.IsChildAgent)
1290 client.Kick("Simulator logged you out due to connection timeout"); 1353 client.Kick("Simulator logged you out due to connection timeout");
1291 1354
1292 client.CloseWithoutChecks(); 1355 client.CloseWithoutChecks(true);
1293 } 1356 }
1294 } 1357 }
1295 1358
@@ -1301,6 +1364,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1301 1364
1302 while (IsRunningInbound) 1365 while (IsRunningInbound)
1303 { 1366 {
1367 m_scene.ThreadAlive(1);
1304 try 1368 try
1305 { 1369 {
1306 IncomingPacket incomingPacket = null; 1370 IncomingPacket incomingPacket = null;
@@ -1348,6 +1412,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1348 1412
1349 while (base.IsRunningOutbound) 1413 while (base.IsRunningOutbound)
1350 { 1414 {
1415 m_scene.ThreadAlive(2);
1351 try 1416 try
1352 { 1417 {
1353 m_packetSent = false; 1418 m_packetSent = false;
@@ -1569,8 +1634,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1569 Packet packet = incomingPacket.Packet; 1634 Packet packet = incomingPacket.Packet;
1570 LLClientView client = incomingPacket.Client; 1635 LLClientView client = incomingPacket.Client;
1571 1636
1572 if (client.IsActive) 1637// if (client.IsActive)
1573 { 1638// {
1574 m_currentIncomingClient = client; 1639 m_currentIncomingClient = client;
1575 1640
1576 try 1641 try
@@ -1597,13 +1662,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1597 { 1662 {
1598 m_currentIncomingClient = null; 1663 m_currentIncomingClient = null;
1599 } 1664 }
1600 } 1665// }
1601 else 1666// else
1602 { 1667// {
1603 m_log.DebugFormat( 1668// m_log.DebugFormat(
1604 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1669// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1605 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1670// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1606 } 1671// }
1607 } 1672 }
1608 1673
1609 protected void LogoutHandler(IClientAPI client) 1674 protected void LogoutHandler(IClientAPI client)
@@ -1613,8 +1678,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1613 if (!client.IsLoggingOut) 1678 if (!client.IsLoggingOut)
1614 { 1679 {
1615 client.IsLoggingOut = true; 1680 client.IsLoggingOut = true;
1616 client.Close(); 1681 client.Close(false, false);
1682 }
1683 }
1684 }
1685
1686 internal class DoubleQueue<T> where T:class
1687 {
1688 private Queue<T> m_lowQueue = new Queue<T>();
1689 private Queue<T> m_highQueue = new Queue<T>();
1690
1691 private object m_syncRoot = new object();
1692 private Semaphore m_s = new Semaphore(0, 1);
1693
1694 public DoubleQueue()
1695 {
1696 }
1697
1698 public virtual int Count
1699 {
1700 get { return m_highQueue.Count + m_lowQueue.Count; }
1701 }
1702
1703 public virtual void Enqueue(T data)
1704 {
1705 Enqueue(m_lowQueue, data);
1706 }
1707
1708 public virtual void EnqueueLow(T data)
1709 {
1710 Enqueue(m_lowQueue, data);
1711 }
1712
1713 public virtual void EnqueueHigh(T data)
1714 {
1715 Enqueue(m_highQueue, data);
1716 }
1717
1718 private void Enqueue(Queue<T> q, T data)
1719 {
1720 lock (m_syncRoot)
1721 {
1722 m_lowQueue.Enqueue(data);
1723 m_s.WaitOne(0);
1724 m_s.Release();
1725 }
1726 }
1727
1728 public virtual T Dequeue()
1729 {
1730 return Dequeue(Timeout.Infinite);
1731 }
1732
1733 public virtual T Dequeue(int tmo)
1734 {
1735 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1736 }
1737
1738 public virtual T Dequeue(TimeSpan wait)
1739 {
1740 T res = null;
1741
1742 if (!Dequeue(wait, ref res))
1743 return null;
1744
1745 return res;
1746 }
1747
1748 public bool Dequeue(int timeout, ref T res)
1749 {
1750 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1751 }
1752
1753 public bool Dequeue(TimeSpan wait, ref T res)
1754 {
1755 if (!m_s.WaitOne(wait))
1756 return false;
1757
1758 lock (m_syncRoot)
1759 {
1760 if (m_highQueue.Count > 0)
1761 res = m_highQueue.Dequeue();
1762 else
1763 res = m_lowQueue.Dequeue();
1764
1765 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1766 return true;
1767
1768 try
1769 {
1770 m_s.Release();
1771 }
1772 catch
1773 {
1774 }
1775
1776 return true;
1777 }
1778 }
1779
1780 public virtual void Clear()
1781 {
1782
1783 lock (m_syncRoot)
1784 {
1785 // Make sure sem count is 0
1786 m_s.WaitOne(0);
1787
1788 m_lowQueue.Clear();
1789 m_highQueue.Clear();
1617 } 1790 }
1618 } 1791 }
1619 } 1792 }
1620} \ No newline at end of file 1793}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 6e6b3ef..e7d8a30 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -118,10 +118,6 @@ namespace OpenMetaverse
118 const int SIO_UDP_CONNRESET = -1744830452; 118 const int SIO_UDP_CONNRESET = -1744830452;
119 119
120 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 120 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
121
122 m_log.DebugFormat(
123 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
124 ipep.Address, ipep.Port);
125 121
126 m_udpSocket = new Socket( 122 m_udpSocket = new Socket(
127 AddressFamily.InterNetwork, 123 AddressFamily.InterNetwork,