aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP
diff options
context:
space:
mode:
Diffstat (limited to '')
-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 7382e09..1f6af4a 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)
@@ -831,7 +860,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
831 reply.ChatData.OwnerID = ownerID; 860 reply.ChatData.OwnerID = ownerID;
832 reply.ChatData.SourceID = fromAgentID; 861 reply.ChatData.SourceID = fromAgentID;
833 862
834 OutPacket(reply, ThrottleOutPacketType.Task); 863 OutPacket(reply, ThrottleOutPacketType.Unknown);
835 } 864 }
836 865
837 /// <summary> 866 /// <summary>
@@ -1117,6 +1146,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1117 public virtual void SendLayerData(float[] map) 1146 public virtual void SendLayerData(float[] map)
1118 { 1147 {
1119 Util.FireAndForget(DoSendLayerData, map); 1148 Util.FireAndForget(DoSendLayerData, map);
1149
1150 // Send it sync, and async. It's not that much data
1151 // and it improves user experience just so much!
1152 DoSendLayerData(map);
1120 } 1153 }
1121 1154
1122 /// <summary> 1155 /// <summary>
@@ -1129,16 +1162,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1129 1162
1130 try 1163 try
1131 { 1164 {
1132 //for (int y = 0; y < 16; y++) 1165 for (int y = 0; y < 16; y++)
1133 //{ 1166 {
1134 // for (int x = 0; x < 16; x++) 1167 for (int x = 0; x < 16; x+=4)
1135 // { 1168 {
1136 // SendLayerData(x, y, map); 1169 SendLayerPacket(x, y, map);
1137 // } 1170 }
1138 //} 1171 }
1139
1140 // Send LayerData in a spiral pattern. Fun!
1141 SendLayerTopRight(map, 0, 0, 15, 15);
1142 } 1172 }
1143 catch (Exception e) 1173 catch (Exception e)
1144 { 1174 {
@@ -1146,51 +1176,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1146 } 1176 }
1147 } 1177 }
1148 1178
1149 private void SendLayerTopRight(float[] map, int x1, int y1, int x2, int y2)
1150 {
1151 // Row
1152 for (int i = x1; i <= x2; i++)
1153 SendLayerData(i, y1, map);
1154
1155 // Column
1156 for (int j = y1 + 1; j <= y2; j++)
1157 SendLayerData(x2, j, map);
1158
1159 if (x2 - x1 > 0)
1160 SendLayerBottomLeft(map, x1, y1 + 1, x2 - 1, y2);
1161 }
1162
1163 void SendLayerBottomLeft(float[] map, int x1, int y1, int x2, int y2)
1164 {
1165 // Row in reverse
1166 for (int i = x2; i >= x1; i--)
1167 SendLayerData(i, y2, map);
1168
1169 // Column in reverse
1170 for (int j = y2 - 1; j >= y1; j--)
1171 SendLayerData(x1, j, map);
1172
1173 if (x2 - x1 > 0)
1174 SendLayerTopRight(map, x1 + 1, y1, x2, y2 - 1);
1175 }
1176
1177 /// <summary> 1179 /// <summary>
1178 /// Sends a set of four patches (x, x+1, ..., x+3) to the client 1180 /// Sends a set of four patches (x, x+1, ..., x+3) to the client
1179 /// </summary> 1181 /// </summary>
1180 /// <param name="map">heightmap</param> 1182 /// <param name="map">heightmap</param>
1181 /// <param name="px">X coordinate for patches 0..12</param> 1183 /// <param name="px">X coordinate for patches 0..12</param>
1182 /// <param name="py">Y coordinate for patches 0..15</param> 1184 /// <param name="py">Y coordinate for patches 0..15</param>
1183 // private void SendLayerPacket(float[] map, int y, int x) 1185 private void SendLayerPacket(int x, int y, float[] map)
1184 // { 1186 {
1185 // int[] patches = new int[4]; 1187 int[] patches = new int[4];
1186 // patches[0] = x + 0 + y * 16; 1188 patches[0] = x + 0 + y * 16;
1187 // patches[1] = x + 1 + y * 16; 1189 patches[1] = x + 1 + y * 16;
1188 // patches[2] = x + 2 + y * 16; 1190 patches[2] = x + 2 + y * 16;
1189 // patches[3] = x + 3 + y * 16; 1191 patches[3] = x + 3 + y * 16;
1190 1192
1191 // Packet layerpack = LLClientView.TerrainManager.CreateLandPacket(map, patches); 1193 float[] heightmap = (map.Length == 65536) ?
1192 // OutPacket(layerpack, ThrottleOutPacketType.Land); 1194 map :
1193 // } 1195 LLHeightFieldMoronize(map);
1196
1197 try
1198 {
1199 Packet layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1200 OutPacket(layerpack, ThrottleOutPacketType.Land);
1201 }
1202 catch
1203 {
1204 for (int px = x ; px < x + 4 ; px++)
1205 SendLayerData(px, y, map);
1206 }
1207 }
1194 1208
1195 /// <summary> 1209 /// <summary>
1196 /// Sends a specified patch to a client 1210 /// Sends a specified patch to a client
@@ -1210,7 +1224,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1210 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1224 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1211 layerpack.Header.Reliable = true; 1225 layerpack.Header.Reliable = true;
1212 1226
1213 OutPacket(layerpack, ThrottleOutPacketType.Land); 1227 OutPacket(layerpack, ThrottleOutPacketType.Task);
1214 } 1228 }
1215 catch (Exception e) 1229 catch (Exception e)
1216 { 1230 {
@@ -1573,7 +1587,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1573 1587
1574 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1588 public void SendKillObject(ulong regionHandle, List<uint> localIDs)
1575 { 1589 {
1576// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, localID, regionHandle); 1590// foreach (uint id in localIDs)
1591// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1577 1592
1578 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1593 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1579 // TODO: don't create new blocks if recycling an old packet 1594 // TODO: don't create new blocks if recycling an old packet
@@ -1595,17 +1610,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1595 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race 1610 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1596 // condition where a kill can be processed before an out-of-date update for the same object. 1611 // condition where a kill can be processed before an out-of-date update for the same object.
1597 // ProcessEntityUpdates() also takes the m_killRecord lock. 1612 // ProcessEntityUpdates() also takes the m_killRecord lock.
1598 lock (m_killRecord) 1613// lock (m_killRecord)
1599 { 1614// {
1600 foreach (uint localID in localIDs) 1615// foreach (uint localID in localIDs)
1601 m_killRecord.Add(localID); 1616// m_killRecord.Add(localID);
1602 1617
1603 // The throttle queue used here must match that being used for updates. Otherwise, there is a 1618 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1604 // chance that a kill packet put on a separate queue will be sent to the client before an existing 1619 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1605 // update packet on another queue. Receiving updates after kills results in unowned and undeletable 1620 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1606 // scene objects in a viewer until that viewer is relogged in. 1621 // scene objects in a viewer until that viewer is relogged in.
1607 OutPacket(kill, ThrottleOutPacketType.Task); 1622 OutPacket(kill, ThrottleOutPacketType.Task);
1608 } 1623// }
1609 } 1624 }
1610 } 1625 }
1611 1626
@@ -2063,9 +2078,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2063 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset); 2078 OutPacket(bulkUpdate, ThrottleOutPacketType.Asset);
2064 } 2079 }
2065 2080
2066 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2067 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId) 2081 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, uint callbackId)
2068 { 2082 {
2083 SendInventoryItemCreateUpdate(Item, UUID.Zero, callbackId);
2084 }
2085
2086 /// <see>IClientAPI.SendInventoryItemCreateUpdate(InventoryItemBase)</see>
2087 public void SendInventoryItemCreateUpdate(InventoryItemBase Item, UUID transactionID, uint callbackId)
2088 {
2069 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All; 2089 const uint FULL_MASK_PERMISSIONS = (uint)PermissionMask.All;
2070 2090
2071 UpdateCreateInventoryItemPacket InventoryReply 2091 UpdateCreateInventoryItemPacket InventoryReply
@@ -2075,6 +2095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2075 // TODO: don't create new blocks if recycling an old packet 2095 // TODO: don't create new blocks if recycling an old packet
2076 InventoryReply.AgentData.AgentID = AgentId; 2096 InventoryReply.AgentData.AgentID = AgentId;
2077 InventoryReply.AgentData.SimApproved = true; 2097 InventoryReply.AgentData.SimApproved = true;
2098 InventoryReply.AgentData.TransactionID = transactionID;
2078 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1]; 2099 InventoryReply.InventoryData = new UpdateCreateInventoryItemPacket.InventoryDataBlock[1];
2079 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock(); 2100 InventoryReply.InventoryData[0] = new UpdateCreateInventoryItemPacket.InventoryDataBlock();
2080 InventoryReply.InventoryData[0].ItemID = Item.ID; 2101 InventoryReply.InventoryData[0].ItemID = Item.ID;
@@ -2144,16 +2165,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2144 replytask.InventoryData.TaskID = taskID; 2165 replytask.InventoryData.TaskID = taskID;
2145 replytask.InventoryData.Serial = serial; 2166 replytask.InventoryData.Serial = serial;
2146 replytask.InventoryData.Filename = fileName; 2167 replytask.InventoryData.Filename = fileName;
2147 OutPacket(replytask, ThrottleOutPacketType.Asset); 2168 OutPacket(replytask, ThrottleOutPacketType.Task);
2148 } 2169 }
2149 2170
2150 public void SendXferPacket(ulong xferID, uint packet, byte[] data) 2171 public void SendXferPacket(ulong xferID, uint packet, byte[] data, bool isTaskInventory)
2151 { 2172 {
2173 ThrottleOutPacketType type = ThrottleOutPacketType.Asset;
2174 if (isTaskInventory)
2175 type = ThrottleOutPacketType.Task;
2176
2152 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket); 2177 SendXferPacketPacket sendXfer = (SendXferPacketPacket)PacketPool.Instance.GetPacket(PacketType.SendXferPacket);
2153 sendXfer.XferID.ID = xferID; 2178 sendXfer.XferID.ID = xferID;
2154 sendXfer.XferID.Packet = packet; 2179 sendXfer.XferID.Packet = packet;
2155 sendXfer.DataPacket.Data = data; 2180 sendXfer.DataPacket.Data = data;
2156 OutPacket(sendXfer, ThrottleOutPacketType.Asset); 2181 OutPacket(sendXfer, type);
2157 } 2182 }
2158 2183
2159 public void SendAbortXferPacket(ulong xferID) 2184 public void SendAbortXferPacket(ulong xferID)
@@ -2335,6 +2360,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2335 OutPacket(sound, ThrottleOutPacketType.Task); 2360 OutPacket(sound, ThrottleOutPacketType.Task);
2336 } 2361 }
2337 2362
2363 public void SendTransferAbort(TransferRequestPacket transferRequest)
2364 {
2365 TransferAbortPacket abort = (TransferAbortPacket)PacketPool.Instance.GetPacket(PacketType.TransferAbort);
2366 abort.TransferInfo.TransferID = transferRequest.TransferInfo.TransferID;
2367 abort.TransferInfo.ChannelType = transferRequest.TransferInfo.ChannelType;
2368 m_log.Debug("[Assets] Aborting transfer; asset request failed");
2369 OutPacket(abort, ThrottleOutPacketType.Task);
2370 }
2371
2338 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain) 2372 public void SendTriggeredSound(UUID soundID, UUID ownerID, UUID objectID, UUID parentID, ulong handle, Vector3 position, float gain)
2339 { 2373 {
2340 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger); 2374 SoundTriggerPacket sound = (SoundTriggerPacket)PacketPool.Instance.GetPacket(PacketType.SoundTrigger);
@@ -2627,6 +2661,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2627 } 2661 }
2628 } 2662 }
2629 2663
2664 public void SendPartPhysicsProprieties(ISceneEntity entity)
2665 {
2666 SceneObjectPart part = (SceneObjectPart)entity;
2667 if (part != null && AgentId != UUID.Zero)
2668 {
2669 try
2670 {
2671 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
2672 if (eq != null)
2673 {
2674 uint localid = part.LocalId;
2675 byte physshapetype = part.PhysicsShapeType;
2676 float density = part.Density;
2677 float friction = part.Friction;
2678 float bounce = part.Bounciness;
2679 float gravmod = part.GravityModifier;
2680
2681 eq.partPhysicsProperties(localid, physshapetype, density, friction, bounce, gravmod,AgentId);
2682 }
2683 }
2684 catch (Exception ex)
2685 {
2686 m_log.Error("Unable to send part Physics Proprieties - exception: " + ex.ToString());
2687 }
2688 part.UpdatePhysRequired = false;
2689 }
2690 }
2691
2692
2630 2693
2631 public void SendGroupNameReply(UUID groupLLUID, string GroupName) 2694 public void SendGroupNameReply(UUID groupLLUID, string GroupName)
2632 { 2695 {
@@ -2724,7 +2787,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2724 else 2787 else
2725 { 2788 {
2726 int processedLength = 0; 2789 int processedLength = 0;
2727 int maxChunkSize = Settings.MAX_PACKET_SIZE - 100; 2790// int maxChunkSize = Settings.MAX_PACKET_SIZE - 100;
2791
2792 int maxChunkSize = (int) MaxTransferBytesPerPacket;
2728 int packetNumber = 0; 2793 int packetNumber = 0;
2729 2794
2730 while (processedLength < req.AssetInf.Data.Length) 2795 while (processedLength < req.AssetInf.Data.Length)
@@ -2795,7 +2860,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2795 reply.Data.ParcelID = parcelID; 2860 reply.Data.ParcelID = parcelID;
2796 reply.Data.OwnerID = land.OwnerID; 2861 reply.Data.OwnerID = land.OwnerID;
2797 reply.Data.Name = Utils.StringToBytes(land.Name); 2862 reply.Data.Name = Utils.StringToBytes(land.Name);
2798 reply.Data.Desc = Utils.StringToBytes(land.Description); 2863 if (land != null && land.Description != null && land.Description != String.Empty)
2864 reply.Data.Desc = Utils.StringToBytes(land.Description.Substring(0, land.Description.Length > 254 ? 254: land.Description.Length));
2865 else
2866 reply.Data.Desc = new Byte[0];
2799 reply.Data.ActualArea = land.Area; 2867 reply.Data.ActualArea = land.Area;
2800 reply.Data.BillableArea = land.Area; // TODO: what is this? 2868 reply.Data.BillableArea = land.Area; // TODO: what is this?
2801 2869
@@ -3530,7 +3598,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3530 3598
3531 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); 3599 AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance);
3532 // TODO: don't create new blocks if recycling an old packet 3600 // TODO: don't create new blocks if recycling an old packet
3533 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; 3601 avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[visualParams.Length];
3534 avp.ObjectData.TextureEntry = textureEntry; 3602 avp.ObjectData.TextureEntry = textureEntry;
3535 3603
3536 AvatarAppearancePacket.VisualParamBlock avblock = null; 3604 AvatarAppearancePacket.VisualParamBlock avblock = null;
@@ -3660,7 +3728,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3660 /// </summary> 3728 /// </summary>
3661 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) 3729 public void SendEntityUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
3662 { 3730 {
3663 //double priority = m_prioritizer.GetUpdatePriority(this, entity); 3731 if (entity is SceneObjectPart)
3732 {
3733 SceneObjectPart e = (SceneObjectPart)entity;
3734 SceneObjectGroup g = e.ParentGroup;
3735 if (g.RootPart.Shape.State > 30) // HUD
3736 if (g.OwnerID != AgentId)
3737 return; // Don't send updates for other people's HUDs
3738 }
3739
3664 uint priority = m_prioritizer.GetUpdatePriority(this, entity); 3740 uint priority = m_prioritizer.GetUpdatePriority(this, entity);
3665 3741
3666 lock (m_entityUpdates.SyncRoot) 3742 lock (m_entityUpdates.SyncRoot)
@@ -3727,27 +3803,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3727 3803
3728 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race 3804 // We must lock for both manipulating the kill record and sending the packet, in order to avoid a race
3729 // condition where a kill can be processed before an out-of-date update for the same object. 3805 // condition where a kill can be processed before an out-of-date update for the same object.
3730 lock (m_killRecord) 3806 float avgTimeDilation = 1.0f;
3807 IEntityUpdate iupdate;
3808 Int32 timeinqueue; // this is just debugging code & can be dropped later
3809
3810 while (updatesThisCall < maxUpdates)
3731 { 3811 {
3732 float avgTimeDilation = 1.0f; 3812 lock (m_entityUpdates.SyncRoot)
3733 IEntityUpdate iupdate; 3813 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3734 Int32 timeinqueue; // this is just debugging code & can be dropped later 3814 break;
3815
3816 EntityUpdate update = (EntityUpdate)iupdate;
3817
3818 avgTimeDilation += update.TimeDilation;
3819 avgTimeDilation *= 0.5f;
3735 3820
3736 while (updatesThisCall < maxUpdates) 3821 if (update.Entity is SceneObjectPart)
3737 { 3822 {
3738 lock (m_entityUpdates.SyncRoot) 3823 SceneObjectPart part = (SceneObjectPart)update.Entity;
3739 if (!m_entityUpdates.TryDequeue(out iupdate, out timeinqueue))
3740 break;
3741 3824
3742 EntityUpdate update = (EntityUpdate)iupdate; 3825 if (part.ParentGroup.IsDeleted)
3743 3826 continue;
3744 avgTimeDilation += update.TimeDilation;
3745 avgTimeDilation *= 0.5f;
3746 3827
3747 if (update.Entity is SceneObjectPart) 3828 if (part.ParentGroup.IsAttachment)
3829 { // Someone else's HUD, why are we getting these?
3830 if (part.ParentGroup.OwnerID != AgentId &&
3831 part.ParentGroup.RootPart.Shape.State > 30)
3832 continue;
3833 ScenePresence sp;
3834 // Owner is not in the sim, don't update it to
3835 // anyone
3836 if (!m_scene.TryGetScenePresence(part.OwnerID, out sp))
3837 continue;
3838
3839 List<SceneObjectGroup> atts = sp.GetAttachments();
3840 bool found = false;
3841 foreach (SceneObjectGroup att in atts)
3842 {
3843 if (att == part.ParentGroup)
3844 {
3845 found = true;
3846 break;
3847 }
3848 }
3849
3850 // It's an attachment of a valid avatar, but
3851 // doesn't seem to be attached, skip
3852 if (!found)
3853 continue;
3854
3855 // On vehicle crossing, the attachments are received
3856 // while the avatar is still a child. Don't send
3857 // updates here because the LocalId has not yet
3858 // been updated and the viewer will derender the
3859 // attachments until the avatar becomes root.
3860 if (sp.IsChildAgent)
3861 continue;
3862
3863 // If the object is an attachment we don't want it to be in the kill
3864 // record. Else attaching from inworld and subsequently dropping
3865 // it will no longer work.
3866// lock (m_killRecord)
3867// {
3868// m_killRecord.Remove(part.LocalId);
3869// m_killRecord.Remove(part.ParentGroup.RootPart.LocalId);
3870// }
3871 }
3872 else
3748 { 3873 {
3749 SceneObjectPart part = (SceneObjectPart)update.Entity;
3750
3751 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client 3874 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3752 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good 3875 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3753 // safety measure. 3876 // safety measure.
@@ -3758,241 +3881,177 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3758 // 3881 //
3759 // This doesn't appear to apply to child prims - a client will happily ignore these updates 3882 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3760 // after the root prim has been deleted. 3883 // after the root prim has been deleted.
3761 if (m_killRecord.Contains(part.LocalId)) 3884 //
3762 { 3885 // We ignore this for attachments because attaching something from inworld breaks unless we do.
3763 // m_log.WarnFormat( 3886// lock (m_killRecord)
3764 // "[CLIENT]: Preventing update for prim with local id {0} after client for user {1} told it was deleted", 3887// {
3765 // part.LocalId, Name); 3888// if (m_killRecord.Contains(part.LocalId))
3766 continue; 3889// continue;
3767 } 3890// if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3768 3891// continue;
3769 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3892// }
3893 }
3894
3895 if (part.ParentGroup.IsAttachment && m_disableFacelights)
3896 {
3897 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand &&
3898 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3770 { 3899 {
3771 if (part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.LeftHand && 3900 part.Shape.LightEntry = false;
3772 part.ParentGroup.RootPart.Shape.State != (byte)AttachmentPoint.RightHand)
3773 {
3774 part.Shape.LightEntry = false;
3775 }
3776 } 3901 }
3777 } 3902 }
3778 3903 }
3779 #region UpdateFlags to packet type conversion 3904
3780 3905 ++updatesThisCall;
3781 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; 3906
3782 3907 #region UpdateFlags to packet type conversion
3783 bool canUseCompressed = true; 3908
3784 bool canUseImproved = true; 3909 PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags;
3785 3910
3786 // Compressed object updates only make sense for LL primitives 3911 bool canUseCompressed = true;
3787 if (!(update.Entity is SceneObjectPart)) 3912 bool canUseImproved = true;
3913
3914 // Compressed object updates only make sense for LL primitives
3915 if (!(update.Entity is SceneObjectPart))
3916 {
3917 canUseCompressed = false;
3918 }
3919
3920 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate))
3921 {
3922 canUseCompressed = false;
3923 canUseImproved = false;
3924 }
3925 else
3926 {
3927 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3928 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3929 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3930 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3788 { 3931 {
3789 canUseCompressed = false; 3932 canUseCompressed = false;
3790 } 3933 }
3791 3934
3792 if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) 3935 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3936 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3937 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3938 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3939 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3940 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3941 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3942 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3943 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3944 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3945 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3946 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3947 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3948 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3793 { 3949 {
3794 canUseCompressed = false;
3795 canUseImproved = false; 3950 canUseImproved = false;
3796 } 3951 }
3797 else 3952 }
3798 {
3799 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3800 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3801 updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) ||
3802 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3803 {
3804 canUseCompressed = false;
3805 }
3806
3807 if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) ||
3808 updateFlags.HasFlag(PrimUpdateFlags.ParentID) ||
3809 updateFlags.HasFlag(PrimUpdateFlags.Scale) ||
3810 updateFlags.HasFlag(PrimUpdateFlags.PrimData) ||
3811 updateFlags.HasFlag(PrimUpdateFlags.Text) ||
3812 updateFlags.HasFlag(PrimUpdateFlags.NameValue) ||
3813 updateFlags.HasFlag(PrimUpdateFlags.ExtraData) ||
3814 updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) ||
3815 updateFlags.HasFlag(PrimUpdateFlags.Sound) ||
3816 updateFlags.HasFlag(PrimUpdateFlags.Particles) ||
3817 updateFlags.HasFlag(PrimUpdateFlags.Material) ||
3818 updateFlags.HasFlag(PrimUpdateFlags.ClickAction) ||
3819 updateFlags.HasFlag(PrimUpdateFlags.MediaURL) ||
3820 updateFlags.HasFlag(PrimUpdateFlags.Joint))
3821 {
3822 canUseImproved = false;
3823 }
3824 }
3825
3826 #endregion UpdateFlags to packet type conversion
3827
3828 #region Block Construction
3829
3830 // TODO: Remove this once we can build compressed updates
3831 canUseCompressed = false;
3832 3953
3833 if (!canUseImproved && !canUseCompressed) 3954 #endregion UpdateFlags to packet type conversion
3834 {
3835 ObjectUpdatePacket.ObjectDataBlock updateBlock;
3836 3955
3837 if (update.Entity is ScenePresence) 3956 #region Block Construction
3838 {
3839 updateBlock = CreateAvatarUpdateBlock((ScenePresence)update.Entity);
3840 }
3841 else
3842 {
3843 SceneObjectPart part = (SceneObjectPart)update.Entity;
3844 updateBlock = CreatePrimUpdateBlock(part, AgentId);
3845
3846 // If the part has become a private hud since the update was scheduled then we do not
3847 // want to send it to other avatars.
3848 if (part.ParentGroup.IsAttachment
3849 && part.ParentGroup.HasPrivateAttachmentPoint
3850 && part.ParentGroup.AttachedAvatar != AgentId)
3851 continue;
3852
3853 // If the part has since been deleted, then drop the update. In the case of attachments,
3854 // this is to avoid spurious updates to other viewers since post-processing of attachments
3855 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3856 // of the test above).
3857 //
3858 // Actual deletions (kills) happen in another method.
3859 if (part.ParentGroup.IsDeleted)
3860 continue;
3861 }
3862 3957
3863 objectUpdateBlocks.Value.Add(updateBlock); 3958 // TODO: Remove this once we can build compressed updates
3864 objectUpdates.Value.Add(update); 3959 canUseCompressed = false;
3865 }
3866 else if (!canUseImproved)
3867 {
3868 SceneObjectPart part = (SceneObjectPart)update.Entity;
3869 ObjectUpdateCompressedPacket.ObjectDataBlock compressedBlock
3870 = CreateCompressedUpdateBlock(part, updateFlags);
3871
3872 // If the part has since been deleted, then drop the update. In the case of attachments,
3873 // this is to avoid spurious updates to other viewers since post-processing of attachments
3874 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3875 // of the test above).
3876 //
3877 // Actual deletions (kills) happen in another method.
3878 if (part.ParentGroup.IsDeleted)
3879 continue;
3880 3960
3881 compressedUpdateBlocks.Value.Add(compressedBlock); 3961 if (!canUseImproved && !canUseCompressed)
3882 compressedUpdates.Value.Add(update); 3962 {
3963 if (update.Entity is ScenePresence)
3964 {
3965 objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity));
3883 } 3966 }
3884 else 3967 else
3885 { 3968 {
3886 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 3969 objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId));
3887 {
3888 // Self updates go into a special list
3889 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3890 terseAgentUpdates.Value.Add(update);
3891 }
3892 else
3893 {
3894 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseUpdateBlock
3895 = CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures));
3896
3897 // Everything else goes here
3898 if (update.Entity is SceneObjectPart)
3899 {
3900 SceneObjectPart part = (SceneObjectPart)update.Entity;
3901
3902 // If the part has become a private hud since the update was scheduled then we do not
3903 // want to send it to other avatars.
3904 if (part.ParentGroup.IsAttachment
3905 && part.ParentGroup.HasPrivateAttachmentPoint
3906 && part.ParentGroup.AttachedAvatar != AgentId)
3907 continue;
3908
3909 // If the part has since been deleted, then drop the update. In the case of attachments,
3910 // this is to avoid spurious updates to other viewers since post-processing of attachments
3911 // has to change the IsAttachment flag for various reasons (which will end up in a pass
3912 // of the test above).
3913 //
3914 // Actual deletions (kills) happen in another method.
3915 if (part.ParentGroup.IsDeleted)
3916 continue;
3917 }
3918
3919 terseUpdateBlocks.Value.Add(terseUpdateBlock);
3920 terseUpdates.Value.Add(update);
3921 }
3922 } 3970 }
3923
3924 ++updatesThisCall;
3925
3926 #endregion Block Construction
3927 } 3971 }
3928 3972 else if (!canUseImproved)
3929 #region Packet Sending 3973 {
3930 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 3974 compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags));
3931 3975 }
3932 if (terseAgentUpdateBlocks.IsValueCreated) 3976 else
3933 { 3977 {
3934 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value; 3978 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId)
3979 // Self updates go into a special list
3980 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3981 else
3982 // Everything else goes here
3983 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3984 }
3935 3985
3936 ImprovedTerseObjectUpdatePacket packet 3986 #endregion Block Construction
3937 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3987 }
3938 3988
3939 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 3989 #region Packet Sending
3940 packet.RegionData.TimeDilation = timeDilation; 3990
3941 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 3991 const float TIME_DILATION = 1.0f;
3992 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
3993
3994 if (terseAgentUpdateBlocks.IsValueCreated)
3995 {
3996 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseAgentUpdateBlocks.Value;
3942 3997
3943 for (int i = 0; i < blocks.Count; i++) 3998 ImprovedTerseObjectUpdatePacket packet
3944 packet.ObjectData[i] = blocks[i]; 3999 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3945 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4000 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3946 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseAgentUpdates.Value, oPacket); }); 4001 packet.RegionData.TimeDilation = timeDilation;
3947 } 4002 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3948 4003
3949 if (objectUpdateBlocks.IsValueCreated) 4004 for (int i = 0; i < blocks.Count; i++)
3950 { 4005 packet.ObjectData[i] = blocks[i];
3951 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3952
3953 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3954 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3955 packet.RegionData.TimeDilation = timeDilation;
3956 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3957
3958 for (int i = 0; i < blocks.Count; i++)
3959 packet.ObjectData[i] = blocks[i];
3960 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3961 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(objectUpdates.Value, oPacket); });
3962 }
3963
3964 if (compressedUpdateBlocks.IsValueCreated)
3965 {
3966 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3967
3968 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3969 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3970 packet.RegionData.TimeDilation = timeDilation;
3971 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3972
3973 for (int i = 0; i < blocks.Count; i++)
3974 packet.ObjectData[i] = blocks[i];
3975 // If any of the packets created from this call go unacknowledged, all of the updates will be resent
3976 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(compressedUpdates.Value, oPacket); });
3977 }
3978 4006
3979 if (terseUpdateBlocks.IsValueCreated) 4007 OutPacket(packet, ThrottleOutPacketType.Unknown, true);
3980 { 4008 }
3981 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
3982
3983 ImprovedTerseObjectUpdatePacket packet
3984 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
3985 PacketType.ImprovedTerseObjectUpdate);
3986 4009
3987 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; 4010 if (objectUpdateBlocks.IsValueCreated)
3988 packet.RegionData.TimeDilation = timeDilation; 4011 {
3989 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; 4012 List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value;
3990 4013
3991 for (int i = 0; i < blocks.Count; i++) 4014 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3992 packet.ObjectData[i] = blocks[i]; 4015 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3993 // If any of the packets created from this call go unacknowledged, all of the updates will be resent 4016 packet.RegionData.TimeDilation = timeDilation;
3994 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4017 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3995 } 4018
4019 for (int i = 0; i < blocks.Count; i++)
4020 packet.ObjectData[i] = blocks[i];
4021
4022 OutPacket(packet, ThrottleOutPacketType.Task, true);
4023 }
4024
4025 if (compressedUpdateBlocks.IsValueCreated)
4026 {
4027 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
4028
4029 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
4030 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4031 packet.RegionData.TimeDilation = timeDilation;
4032 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
4033
4034 for (int i = 0; i < blocks.Count; i++)
4035 packet.ObjectData[i] = blocks[i];
4036
4037 OutPacket(packet, ThrottleOutPacketType.Task, true);
4038 }
4039
4040 if (terseUpdateBlocks.IsValueCreated)
4041 {
4042 List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value;
4043
4044 ImprovedTerseObjectUpdatePacket packet
4045 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
4046 PacketType.ImprovedTerseObjectUpdate);
4047 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4048 packet.RegionData.TimeDilation = timeDilation;
4049 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
4050
4051 for (int i = 0; i < blocks.Count; i++)
4052 packet.ObjectData[i] = blocks[i];
4053
4054 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
3996 } 4055 }
3997 4056
3998 #endregion Packet Sending 4057 #endregion Packet Sending
@@ -4285,11 +4344,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4285 4344
4286 // Pass in the delegate so that if this packet needs to be resent, we send the current properties 4345 // Pass in the delegate so that if this packet needs to be resent, we send the current properties
4287 // of the object rather than the properties when the packet was created 4346 // of the object rather than the properties when the packet was created
4288 OutPacket(packet, ThrottleOutPacketType.Task, true, 4347 // HACK : Remove intelligent resending until it's fixed in core
4289 delegate(OutgoingPacket oPacket) 4348 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4290 { 4349 // delegate(OutgoingPacket oPacket)
4291 ResendPropertyUpdates(updates, oPacket); 4350 // {
4292 }); 4351 // ResendPropertyUpdates(updates, oPacket);
4352 // });
4353 OutPacket(packet, ThrottleOutPacketType.Task, true);
4293 4354
4294 // pbcnt += blocks.Count; 4355 // pbcnt += blocks.Count;
4295 // ppcnt++; 4356 // ppcnt++;
@@ -4315,11 +4376,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4315 // of the object rather than the properties when the packet was created 4376 // of the object rather than the properties when the packet was created
4316 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>(); 4377 List<ObjectPropertyUpdate> updates = new List<ObjectPropertyUpdate>();
4317 updates.Add(familyUpdates.Value[i]); 4378 updates.Add(familyUpdates.Value[i]);
4318 OutPacket(packet, ThrottleOutPacketType.Task, true, 4379 // HACK : Remove intelligent resending until it's fixed in core
4319 delegate(OutgoingPacket oPacket) 4380 //OutPacket(packet, ThrottleOutPacketType.Task, true,
4320 { 4381 // delegate(OutgoingPacket oPacket)
4321 ResendPropertyUpdates(updates, oPacket); 4382 // {
4322 }); 4383 // ResendPropertyUpdates(updates, oPacket);
4384 // });
4385 OutPacket(packet, ThrottleOutPacketType.Task, true);
4323 4386
4324 // fpcnt++; 4387 // fpcnt++;
4325 // fbcnt++; 4388 // fbcnt++;
@@ -4691,7 +4754,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4691 4754
4692 if (landData.SimwideArea > 0) 4755 if (landData.SimwideArea > 0)
4693 { 4756 {
4694 int simulatorCapacity = (int)(((float)landData.SimwideArea / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); 4757 int simulatorCapacity = (int)((long)landData.SimwideArea * (long)m_scene.RegionInfo.ObjectCapacity * (long)m_scene.RegionInfo.RegionSettings.ObjectBonus / 65536L);
4758 // Never report more than sim total capacity
4759 if (simulatorCapacity > m_scene.RegionInfo.ObjectCapacity)
4760 simulatorCapacity = m_scene.RegionInfo.ObjectCapacity;
4695 updateMessage.SimWideMaxPrims = simulatorCapacity; 4761 updateMessage.SimWideMaxPrims = simulatorCapacity;
4696 } 4762 }
4697 else 4763 else
@@ -4820,14 +4886,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4820 4886
4821 if (notifyCount > 0) 4887 if (notifyCount > 0)
4822 { 4888 {
4823 if (notifyCount > 32) 4889// if (notifyCount > 32)
4824 { 4890// {
4825 m_log.InfoFormat( 4891// m_log.InfoFormat(
4826 "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}" 4892// "[LAND]: More than {0} avatars own prims on this parcel. Only sending back details of first {0}"
4827 + " - a developer might want to investigate whether this is a hard limit", 32); 4893// + " - a developer might want to investigate whether this is a hard limit", 32);
4828 4894//
4829 notifyCount = 32; 4895// notifyCount = 32;
4830 } 4896// }
4831 4897
4832 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock 4898 ParcelObjectOwnersReplyPacket.DataBlock[] dataBlock
4833 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount]; 4899 = new ParcelObjectOwnersReplyPacket.DataBlock[notifyCount];
@@ -4882,9 +4948,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4882 { 4948 {
4883 ScenePresence presence = (ScenePresence)entity; 4949 ScenePresence presence = (ScenePresence)entity;
4884 4950
4951 position = presence.OffsetPosition;
4952 rotation = presence.Rotation;
4953
4954 if (presence.ParentID != 0)
4955 {
4956 SceneObjectPart part = m_scene.GetSceneObjectPart(presence.ParentID);
4957 if (part != null && part != part.ParentGroup.RootPart)
4958 {
4959 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
4960 rotation = part.RotationOffset * presence.Rotation;
4961 }
4962 }
4963
4885 attachPoint = 0; 4964 attachPoint = 0;
4886 collisionPlane = presence.CollisionPlane; 4965 collisionPlane = presence.CollisionPlane;
4887 position = presence.OffsetPosition;
4888 velocity = presence.Velocity; 4966 velocity = presence.Velocity;
4889 acceleration = Vector3.Zero; 4967 acceleration = Vector3.Zero;
4890 4968
@@ -4894,7 +4972,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4894// acceleration = new Vector3(1, 0, 0); 4972// acceleration = new Vector3(1, 0, 0);
4895 4973
4896 angularVelocity = Vector3.Zero; 4974 angularVelocity = Vector3.Zero;
4897 rotation = presence.Rotation;
4898 4975
4899 if (sendTexture) 4976 if (sendTexture)
4900 textureEntry = presence.Appearance.Texture.GetBytes(); 4977 textureEntry = presence.Appearance.Texture.GetBytes();
@@ -5001,13 +5078,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5001 5078
5002 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) 5079 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
5003 { 5080 {
5081 Vector3 offsetPosition = data.OffsetPosition;
5082 Quaternion rotation = data.Rotation;
5083 uint parentID = data.ParentID;
5084
5085 if (parentID != 0)
5086 {
5087 SceneObjectPart part = m_scene.GetSceneObjectPart(parentID);
5088 if (part != null && part != part.ParentGroup.RootPart)
5089 {
5090 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
5091 rotation = part.RotationOffset * data.Rotation;
5092 parentID = part.ParentGroup.RootPart.LocalId;
5093 }
5094 }
5095
5004 byte[] objectData = new byte[76]; 5096 byte[] objectData = new byte[76];
5005 5097
5006 data.CollisionPlane.ToBytes(objectData, 0); 5098 data.CollisionPlane.ToBytes(objectData, 0);
5007 data.OffsetPosition.ToBytes(objectData, 16); 5099 offsetPosition.ToBytes(objectData, 16);
5008// data.Velocity.ToBytes(objectData, 28); 5100// data.Velocity.ToBytes(objectData, 28);
5009// data.Acceleration.ToBytes(objectData, 40); 5101// data.Acceleration.ToBytes(objectData, 40);
5010 data.Rotation.ToBytes(objectData, 52); 5102 rotation.ToBytes(objectData, 52);
5011 //data.AngularVelocity.ToBytes(objectData, 64); 5103 //data.AngularVelocity.ToBytes(objectData, 64);
5012 5104
5013 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5105 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5021,7 +5113,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5021 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5113 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5022 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5114 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5023 update.ObjectData = objectData; 5115 update.ObjectData = objectData;
5024 update.ParentID = data.ParentID; 5116 update.ParentID = parentID;
5025 update.PathCurve = 16; 5117 update.PathCurve = 16;
5026 update.PathScaleX = 100; 5118 update.PathScaleX = 100;
5027 update.PathScaleY = 100; 5119 update.PathScaleY = 100;
@@ -5039,10 +5131,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5039 update.TextureEntry = Utils.EmptyBytes; 5131 update.TextureEntry = Utils.EmptyBytes;
5040// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; 5132// update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes;
5041 5133
5134/* all this flags seem related to prims and not avatars. This allow for wrong viewer side move of a avatar in prim edition mode (anv mantis 854)
5042 update.UpdateFlags = (uint)( 5135 update.UpdateFlags = (uint)(
5043 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | 5136 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
5044 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | 5137 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
5045 PrimFlags.ObjectOwnerModify); 5138 PrimFlags.ObjectOwnerModify);
5139*/
5140 update.UpdateFlags = 0;
5046 5141
5047 return update; 5142 return update;
5048 } 5143 }
@@ -5366,6 +5461,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5366 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false); 5461 AddLocalPacketHandler(PacketType.TransferAbort, HandleTransferAbort, false);
5367 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false); 5462 AddLocalPacketHandler(PacketType.MuteListRequest, HandleMuteListRequest, false);
5368 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode); 5463 AddLocalPacketHandler(PacketType.UseCircuitCode, HandleUseCircuitCode);
5464 AddLocalPacketHandler(PacketType.CreateNewOutfitAttachments, HandleCreateNewOutfitAttachments);
5369 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false); 5465 AddLocalPacketHandler(PacketType.AgentHeightWidth, HandleAgentHeightWidth, false);
5370 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents); 5466 AddLocalPacketHandler(PacketType.InventoryDescendents, HandleInventoryDescendents);
5371 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery); 5467 AddLocalPacketHandler(PacketType.DirPlacesQuery, HandleDirPlacesQuery);
@@ -5432,6 +5528,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5432 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest); 5528 AddLocalPacketHandler(PacketType.GroupVoteHistoryRequest, HandleGroupVoteHistoryRequest);
5433 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes); 5529 AddLocalPacketHandler(PacketType.SimWideDeletes, HandleSimWideDeletes);
5434 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard); 5530 AddLocalPacketHandler(PacketType.SendPostcard, HandleSendPostcard);
5531 AddLocalPacketHandler(PacketType.ChangeInventoryItemFlags, HandleChangeInventoryItemFlags);
5435 5532
5436 AddGenericPacketHandler("autopilot", HandleAutopilot); 5533 AddGenericPacketHandler("autopilot", HandleAutopilot);
5437 } 5534 }
@@ -5470,6 +5567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5470 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || 5567 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5471 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || 5568 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5472 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || 5569 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5570 (x.ControlFlags != 0) ||
5473 (x.Far != m_lastAgentUpdateArgs.Far) || 5571 (x.Far != m_lastAgentUpdateArgs.Far) ||
5474 (x.Flags != m_lastAgentUpdateArgs.Flags) || 5572 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5475 (x.State != m_lastAgentUpdateArgs.State) || 5573 (x.State != m_lastAgentUpdateArgs.State) ||
@@ -6368,6 +6466,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6368 { 6466 {
6369 handlerCompleteMovementToRegion(sender, true); 6467 handlerCompleteMovementToRegion(sender, true);
6370 } 6468 }
6469 else
6470 m_log.Debug("HandleCompleteAgentMovement NULL handler");
6471
6371 handlerCompleteMovementToRegion = null; 6472 handlerCompleteMovementToRegion = null;
6372 6473
6373 return true; 6474 return true;
@@ -6385,7 +6486,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6385 return true; 6486 return true;
6386 } 6487 }
6387 #endregion 6488 #endregion
6388 6489/*
6389 StartAnim handlerStartAnim = null; 6490 StartAnim handlerStartAnim = null;
6390 StopAnim handlerStopAnim = null; 6491 StopAnim handlerStopAnim = null;
6391 6492
@@ -6409,6 +6510,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6409 } 6510 }
6410 } 6511 }
6411 return true; 6512 return true;
6513*/
6514 ChangeAnim handlerChangeAnim = null;
6515
6516 for (int i = 0; i < AgentAni.AnimationList.Length; i++)
6517 {
6518 handlerChangeAnim = OnChangeAnim;
6519 if (handlerChangeAnim != null)
6520 {
6521 handlerChangeAnim(AgentAni.AnimationList[i].AnimID, AgentAni.AnimationList[i].StartAnim, false);
6522 }
6523 }
6524
6525 handlerChangeAnim = OnChangeAnim;
6526 if (handlerChangeAnim != null)
6527 {
6528 handlerChangeAnim(UUID.Zero, false, true);
6529 }
6530
6531 return true;
6412 } 6532 }
6413 6533
6414 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack) 6534 private bool HandleAgentRequestSit(IClientAPI sender, Packet Pack)
@@ -7034,10 +7154,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7034 // 46,47,48 are special positions within the packet 7154 // 46,47,48 are special positions within the packet
7035 // This may change so perhaps we need a better way 7155 // This may change so perhaps we need a better way
7036 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?) 7156 // of storing this (OMV.FlagUpdatePacket.UsePhysics,etc?)
7037 bool UsePhysics = (data[46] != 0) ? true : false; 7157 /*
7038 bool IsTemporary = (data[47] != 0) ? true : false; 7158 bool UsePhysics = (data[46] != 0) ? true : false;
7039 bool IsPhantom = (data[48] != 0) ? true : false; 7159 bool IsTemporary = (data[47] != 0) ? true : false;
7040 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this); 7160 bool IsPhantom = (data[48] != 0) ? true : false;
7161 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, this);
7162 */
7163 bool UsePhysics = flags.AgentData.UsePhysics;
7164 bool IsPhantom = flags.AgentData.IsPhantom;
7165 bool IsTemporary = flags.AgentData.IsTemporary;
7166 ObjectFlagUpdatePacket.ExtraPhysicsBlock[] blocks = flags.ExtraPhysics;
7167 ExtraPhysicsData physdata = new ExtraPhysicsData();
7168
7169 if (blocks == null || blocks.Length == 0)
7170 {
7171 physdata.PhysShapeType = PhysShapeType.invalid;
7172 }
7173 else
7174 {
7175 ObjectFlagUpdatePacket.ExtraPhysicsBlock phsblock = blocks[0];
7176 physdata.PhysShapeType = (PhysShapeType)phsblock.PhysicsShapeType;
7177 physdata.Bounce = phsblock.Restitution;
7178 physdata.Density = phsblock.Density;
7179 physdata.Friction = phsblock.Friction;
7180 physdata.GravitationModifier = phsblock.GravityMultiplier;
7181 }
7182
7183 handlerUpdatePrimFlags(flags.AgentData.ObjectLocalID, UsePhysics, IsTemporary, IsPhantom, physdata, this);
7041 } 7184 }
7042 return true; 7185 return true;
7043 } 7186 }
@@ -8638,16 +8781,61 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8638 8781
8639 #region Parcel related packets 8782 #region Parcel related packets
8640 8783
8784 // acumulate several HandleRegionHandleRequest consecutive overlaping requests
8785 // to be done with minimal resources as possible
8786 // variables temporary here while in test
8787
8788 Queue<UUID> RegionHandleRequests = new Queue<UUID>();
8789 bool RegionHandleRequestsInService = false;
8790
8641 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack) 8791 private bool HandleRegionHandleRequest(IClientAPI sender, Packet Pack)
8642 { 8792 {
8643 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack; 8793 UUID currentUUID;
8644 8794
8645 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest; 8795 RegionHandleRequest handlerRegionHandleRequest = OnRegionHandleRequest;
8646 if (handlerRegionHandleRequest != null) 8796
8797 if (handlerRegionHandleRequest == null)
8798 return true;
8799
8800 RegionHandleRequestPacket rhrPack = (RegionHandleRequestPacket)Pack;
8801
8802 lock (RegionHandleRequests)
8647 { 8803 {
8648 handlerRegionHandleRequest(this, rhrPack.RequestBlock.RegionID); 8804 if (RegionHandleRequestsInService)
8805 {
8806 // we are already busy doing a previus request
8807 // so enqueue it
8808 RegionHandleRequests.Enqueue(rhrPack.RequestBlock.RegionID);
8809 return true;
8810 }
8811
8812 // else do it
8813 currentUUID = rhrPack.RequestBlock.RegionID;
8814 RegionHandleRequestsInService = true;
8649 } 8815 }
8650 return true; 8816
8817 while (true)
8818 {
8819 handlerRegionHandleRequest(this, currentUUID);
8820
8821 lock (RegionHandleRequests)
8822 {
8823 // exit condition, nothing to do or closed
8824 // current code seems to assume we may loose the handler at anytime,
8825 // so keep checking it
8826 handlerRegionHandleRequest = OnRegionHandleRequest;
8827
8828 if (RegionHandleRequests.Count == 0 || !IsActive || handlerRegionHandleRequest == null)
8829 {
8830 RegionHandleRequests.Clear();
8831 RegionHandleRequestsInService = false;
8832 return true;
8833 }
8834 currentUUID = RegionHandleRequests.Dequeue();
8835 }
8836 }
8837
8838 return true; // actually unreached
8651 } 8839 }
8652 8840
8653 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack) 8841 private bool HandleParcelInfoRequest(IClientAPI sender, Packet Pack)
@@ -9903,7 +10091,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9903 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID, 10091 handlerUpdateMuteListEntry(this, UpdateMuteListEntry.MuteData.MuteID,
9904 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName), 10092 Utils.BytesToString(UpdateMuteListEntry.MuteData.MuteName),
9905 UpdateMuteListEntry.MuteData.MuteType, 10093 UpdateMuteListEntry.MuteData.MuteType,
9906 UpdateMuteListEntry.AgentData.AgentID); 10094 UpdateMuteListEntry.MuteData.MuteFlags);
9907 return true; 10095 return true;
9908 } 10096 }
9909 return false; 10097 return false;
@@ -9918,8 +10106,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9918 { 10106 {
9919 handlerRemoveMuteListEntry(this, 10107 handlerRemoveMuteListEntry(this,
9920 RemoveMuteListEntry.MuteData.MuteID, 10108 RemoveMuteListEntry.MuteData.MuteID,
9921 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName), 10109 Utils.BytesToString(RemoveMuteListEntry.MuteData.MuteName));
9922 RemoveMuteListEntry.AgentData.AgentID);
9923 return true; 10110 return true;
9924 } 10111 }
9925 return false; 10112 return false;
@@ -9963,10 +10150,55 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9963 return false; 10150 return false;
9964 } 10151 }
9965 10152
10153 private bool HandleChangeInventoryItemFlags(IClientAPI client, Packet packet)
10154 {
10155 ChangeInventoryItemFlagsPacket ChangeInventoryItemFlags =
10156 (ChangeInventoryItemFlagsPacket)packet;
10157 ChangeInventoryItemFlags handlerChangeInventoryItemFlags = OnChangeInventoryItemFlags;
10158 if (handlerChangeInventoryItemFlags != null)
10159 {
10160 foreach(ChangeInventoryItemFlagsPacket.InventoryDataBlock b in ChangeInventoryItemFlags.InventoryData)
10161 handlerChangeInventoryItemFlags(this, b.ItemID, b.Flags);
10162 return true;
10163 }
10164 return false;
10165 }
10166
9966 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack) 10167 private bool HandleUseCircuitCode(IClientAPI sender, Packet Pack)
9967 { 10168 {
9968 return true; 10169 return true;
9969 } 10170 }
10171
10172 private bool HandleCreateNewOutfitAttachments(IClientAPI sender, Packet Pack)
10173 {
10174 CreateNewOutfitAttachmentsPacket packet = (CreateNewOutfitAttachmentsPacket)Pack;
10175
10176 #region Packet Session and User Check
10177 if (m_checkPackets)
10178 {
10179 if (packet.AgentData.SessionID != SessionId ||
10180 packet.AgentData.AgentID != AgentId)
10181 return true;
10182 }
10183 #endregion
10184 MoveItemsAndLeaveCopy handlerMoveItemsAndLeaveCopy = null;
10185 List<InventoryItemBase> items = new List<InventoryItemBase>();
10186 foreach (CreateNewOutfitAttachmentsPacket.ObjectDataBlock n in packet.ObjectData)
10187 {
10188 InventoryItemBase b = new InventoryItemBase();
10189 b.ID = n.OldItemID;
10190 b.Folder = n.OldFolderID;
10191 items.Add(b);
10192 }
10193
10194 handlerMoveItemsAndLeaveCopy = OnMoveItemsAndLeaveCopy;
10195 if (handlerMoveItemsAndLeaveCopy != null)
10196 {
10197 handlerMoveItemsAndLeaveCopy(this, items, packet.HeaderData.NewFolderID);
10198 }
10199
10200 return true;
10201 }
9970 10202
9971 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack) 10203 private bool HandleAgentHeightWidth(IClientAPI sender, Packet Pack)
9972 { 10204 {
@@ -10393,6 +10625,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10393 groupProfileReply.GroupData.MaturePublish = d.MaturePublish; 10625 groupProfileReply.GroupData.MaturePublish = d.MaturePublish;
10394 groupProfileReply.GroupData.OwnerRole = d.OwnerRole; 10626 groupProfileReply.GroupData.OwnerRole = d.OwnerRole;
10395 10627
10628 Scene scene = (Scene)m_scene;
10629 if (scene.Permissions.IsGod(sender.AgentId) && (!sender.IsGroupMember(groupProfileRequest.GroupData.GroupID)))
10630 {
10631 ScenePresence p;
10632 if (scene.TryGetScenePresence(sender.AgentId, out p))
10633 {
10634 if (p.GodLevel >= 200)
10635 {
10636 groupProfileReply.GroupData.OpenEnrollment = true;
10637 groupProfileReply.GroupData.MembershipFee = 0;
10638 }
10639 }
10640 }
10641
10396 OutPacket(groupProfileReply, ThrottleOutPacketType.Task); 10642 OutPacket(groupProfileReply, ThrottleOutPacketType.Task);
10397 } 10643 }
10398 return true; 10644 return true;
@@ -10966,11 +11212,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10966 11212
10967 StartLure handlerStartLure = OnStartLure; 11213 StartLure handlerStartLure = OnStartLure;
10968 if (handlerStartLure != null) 11214 if (handlerStartLure != null)
10969 handlerStartLure(startLureRequest.Info.LureType, 11215 {
10970 Utils.BytesToString( 11216 for (int i = 0 ; i < startLureRequest.TargetData.Length ; i++)
10971 startLureRequest.Info.Message), 11217 {
10972 startLureRequest.TargetData[0].TargetID, 11218 handlerStartLure(startLureRequest.Info.LureType,
10973 this); 11219 Utils.BytesToString(
11220 startLureRequest.Info.Message),
11221 startLureRequest.TargetData[i].TargetID,
11222 this);
11223 }
11224 }
10974 return true; 11225 return true;
10975 } 11226 }
10976 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack) 11227 private bool HandleTeleportLureRequest(IClientAPI sender, Packet Pack)
@@ -11084,10 +11335,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11084 } 11335 }
11085 #endregion 11336 #endregion
11086 11337
11087 ClassifiedDelete handlerClassifiedGodDelete = OnClassifiedGodDelete; 11338 ClassifiedGodDelete handlerClassifiedGodDelete = OnClassifiedGodDelete;
11088 if (handlerClassifiedGodDelete != null) 11339 if (handlerClassifiedGodDelete != null)
11089 handlerClassifiedGodDelete( 11340 handlerClassifiedGodDelete(
11090 classifiedGodDelete.Data.ClassifiedID, 11341 classifiedGodDelete.Data.ClassifiedID,
11342 classifiedGodDelete.Data.QueryID,
11091 this); 11343 this);
11092 return true; 11344 return true;
11093 } 11345 }
@@ -11453,209 +11705,147 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11453 } 11705 }
11454 else 11706 else
11455 { 11707 {
11456// m_log.DebugFormat( 11708 ClientChangeObject updatehandler = onClientChangeObject;
11457// "[CLIENT]: Processing block {0} type {1} for {2} {3}",
11458// i, block.Type, part.Name, part.LocalId);
11459 11709
11460// // Do this once since fetch parts creates a new array. 11710 if (updatehandler != null)
11461// SceneObjectPart[] parts = part.ParentGroup.Parts; 11711 {
11462// for (int j = 0; j < parts.Length; j++) 11712 ObjectChangeData udata = new ObjectChangeData();
11463// {
11464// part.StoreUndoState();
11465// parts[j].IgnoreUndoUpdate = true;
11466// }
11467 11713
11468 UpdatePrimGroupRotation handlerUpdatePrimGroupRotation; 11714 /*ubit from ll JIRA:
11715 * 0x01 position
11716 * 0x02 rotation
11717 * 0x04 scale
11718
11719 * 0x08 LINK_SET
11720 * 0x10 UNIFORM for scale
11721 */
11469 11722
11470 switch (block.Type) 11723 // translate to internal changes
11471 { 11724 // not all cases .. just the ones older code did
11472 case 1:
11473 Vector3 pos1 = new Vector3(block.Data, 0);
11474 11725
11475 UpdateVector handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11726 switch (block.Type)
11476 if (handlerUpdatePrimSinglePosition != null) 11727 {
11477 { 11728 case 1: //change position sp
11478 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11729 udata.position = new Vector3(block.Data, 0);
11479 handlerUpdatePrimSinglePosition(localId, pos1, this);
11480 }
11481 break;
11482 11730
11483 case 2: 11731 udata.change = ObjectChangeType.primP;
11484 Quaternion rot1 = new Quaternion(block.Data, 0, true); 11732 updatehandler(localId, udata, this);
11733 break;
11485 11734
11486 UpdatePrimSingleRotation handlerUpdatePrimSingleRotation = OnUpdatePrimSingleRotation; 11735 case 2: // rotation sp
11487 if (handlerUpdatePrimSingleRotation != null) 11736 udata.rotation = new Quaternion(block.Data, 0, true);
11488 {
11489 // m_log.Info("new tab rotation is " + rot1.X + " , " + rot1.Y + " , " + rot1.Z + " , " + rot1.W);
11490 handlerUpdatePrimSingleRotation(localId, rot1, this);
11491 }
11492 break;
11493 11737
11494 case 3: 11738 udata.change = ObjectChangeType.primR;
11495 Vector3 rotPos = new Vector3(block.Data, 0); 11739 updatehandler(localId, udata, this);
11496 Quaternion rot2 = new Quaternion(block.Data, 12, true); 11740 break;
11497 11741
11498 UpdatePrimSingleRotationPosition handlerUpdatePrimSingleRotationPosition = OnUpdatePrimSingleRotationPosition; 11742 case 3: // position plus rotation
11499 if (handlerUpdatePrimSingleRotationPosition != null) 11743 udata.position = new Vector3(block.Data, 0);
11500 { 11744 udata.rotation = new Quaternion(block.Data, 12, true);
11501 // m_log.Debug("new mouse rotation position is " + rotPos.X + " , " + rotPos.Y + " , " + rotPos.Z);
11502 // m_log.Info("new mouse rotation is " + rot2.X + " , " + rot2.Y + " , " + rot2.Z + " , " + rot2.W);
11503 handlerUpdatePrimSingleRotationPosition(localId, rot2, rotPos, this);
11504 }
11505 break;
11506 11745
11507 case 4: 11746 udata.change = ObjectChangeType.primPR;
11508 case 20: 11747 updatehandler(localId, udata, this);
11509 Vector3 scale4 = new Vector3(block.Data, 0); 11748 break;
11510 11749
11511 UpdateVector handlerUpdatePrimScale = OnUpdatePrimScale; 11750 case 4: // scale sp
11512 if (handlerUpdatePrimScale != null) 11751 udata.scale = new Vector3(block.Data, 0);
11513 { 11752 udata.change = ObjectChangeType.primS;
11514 // m_log.Debug("new scale is " + scale4.X + " , " + scale4.Y + " , " + scale4.Z);
11515 handlerUpdatePrimScale(localId, scale4, this);
11516 }
11517 break;
11518 11753
11519 case 5: 11754 updatehandler(localId, udata, this);
11520 Vector3 scale1 = new Vector3(block.Data, 12); 11755 break;
11521 Vector3 pos11 = new Vector3(block.Data, 0);
11522 11756
11523 handlerUpdatePrimScale = OnUpdatePrimScale; 11757 case 0x14: // uniform scale sp
11524 if (handlerUpdatePrimScale != null) 11758 udata.scale = new Vector3(block.Data, 0);
11525 {
11526 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11527 handlerUpdatePrimScale(localId, scale1, this);
11528 11759
11529 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11760 udata.change = ObjectChangeType.primUS;
11530 if (handlerUpdatePrimSinglePosition != null) 11761 updatehandler(localId, udata, this);
11531 { 11762 break;
11532 handlerUpdatePrimSinglePosition(localId, pos11, this);
11533 }
11534 }
11535 break;
11536 11763
11537 case 9: 11764 case 5: // scale and position sp
11538 Vector3 pos2 = new Vector3(block.Data, 0); 11765 udata.position = new Vector3(block.Data, 0);
11766 udata.scale = new Vector3(block.Data, 12);
11539 11767
11540 UpdateVector handlerUpdateVector = OnUpdatePrimGroupPosition; 11768 udata.change = ObjectChangeType.primPS;
11769 updatehandler(localId, udata, this);
11770 break;
11541 11771
11542 if (handlerUpdateVector != null) 11772 case 0x15: //uniform scale and position
11543 { 11773 udata.position = new Vector3(block.Data, 0);
11544 handlerUpdateVector(localId, pos2, this); 11774 udata.scale = new Vector3(block.Data, 12);
11545 }
11546 break;
11547 11775
11548 case 10: 11776 udata.change = ObjectChangeType.primPUS;
11549 Quaternion rot3 = new Quaternion(block.Data, 0, true); 11777 updatehandler(localId, udata, this);
11778 break;
11550 11779
11551 UpdatePrimRotation handlerUpdatePrimRotation = OnUpdatePrimGroupRotation; 11780 // now group related (bit 4)
11552 if (handlerUpdatePrimRotation != null) 11781 case 9: //( 8 + 1 )group position
11553 { 11782 udata.position = new Vector3(block.Data, 0);
11554 // Console.WriteLine("new rotation is " + rot3.X + " , " + rot3.Y + " , " + rot3.Z + " , " + rot3.W);
11555 handlerUpdatePrimRotation(localId, rot3, this);
11556 }
11557 break;
11558 11783
11559 case 11: 11784 udata.change = ObjectChangeType.groupP;
11560 Vector3 pos3 = new Vector3(block.Data, 0); 11785 updatehandler(localId, udata, this);
11561 Quaternion rot4 = new Quaternion(block.Data, 12, true); 11786 break;
11562 11787
11563 handlerUpdatePrimGroupRotation = OnUpdatePrimGroupMouseRotation; 11788 case 0x0A: // (8 + 2) group rotation
11564 if (handlerUpdatePrimGroupRotation != null) 11789 udata.rotation = new Quaternion(block.Data, 0, true);
11565 {
11566 // m_log.Debug("new rotation position is " + pos.X + " , " + pos.Y + " , " + pos.Z);
11567 // m_log.Debug("new group mouse rotation is " + rot4.X + " , " + rot4.Y + " , " + rot4.Z + " , " + rot4.W);
11568 handlerUpdatePrimGroupRotation(localId, pos3, rot4, this);
11569 }
11570 break;
11571 case 12:
11572 case 28:
11573 Vector3 scale7 = new Vector3(block.Data, 0);
11574 11790
11575 UpdateVector handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11791 udata.change = ObjectChangeType.groupR;
11576 if (handlerUpdatePrimGroupScale != null) 11792 updatehandler(localId, udata, this);
11577 { 11793 break;
11578 // m_log.Debug("new scale is " + scale7.X + " , " + scale7.Y + " , " + scale7.Z);
11579 handlerUpdatePrimGroupScale(localId, scale7, this);
11580 }
11581 break;
11582 11794
11583 case 13: 11795 case 0x0B: //( 8 + 2 + 1) group rotation and position
11584 Vector3 scale2 = new Vector3(block.Data, 12); 11796 udata.position = new Vector3(block.Data, 0);
11585 Vector3 pos4 = new Vector3(block.Data, 0); 11797 udata.rotation = new Quaternion(block.Data, 12, true);
11586 11798
11587 handlerUpdatePrimScale = OnUpdatePrimScale; 11799 udata.change = ObjectChangeType.groupPR;
11588 if (handlerUpdatePrimScale != null) 11800 updatehandler(localId, udata, this);
11589 { 11801 break;
11590 //m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11591 handlerUpdatePrimScale(localId, scale2, this);
11592 11802
11593 // Change the position based on scale (for bug number 246) 11803 case 0x0C: // (8 + 4) group scale
11594 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11804 // only afects root prim and only sent by viewer editor object tab scaling
11595 // m_log.Debug("new movement position is " + pos.X + " , " + pos.Y + " , " + pos.Z); 11805 // mouse edition only allows uniform scaling
11596 if (handlerUpdatePrimSinglePosition != null) 11806 // SL MAY CHANGE THIS in viewers
11597 {
11598 handlerUpdatePrimSinglePosition(localId, pos4, this);
11599 }
11600 }
11601 break;
11602 11807
11603 case 29: 11808 udata.scale = new Vector3(block.Data, 0);
11604 Vector3 scale5 = new Vector3(block.Data, 12);
11605 Vector3 pos5 = new Vector3(block.Data, 0);
11606 11809
11607 handlerUpdatePrimGroupScale = OnUpdatePrimGroupScale; 11810 udata.change = ObjectChangeType.groupS;
11608 if (handlerUpdatePrimGroupScale != null) 11811 updatehandler(localId, udata, this);
11609 {
11610 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z);
11611 part.StoreUndoState(true);
11612 part.IgnoreUndoUpdate = true;
11613 handlerUpdatePrimGroupScale(localId, scale5, this);
11614 handlerUpdateVector = OnUpdatePrimGroupPosition;
11615 11812
11616 if (handlerUpdateVector != null) 11813 break;
11617 {
11618 handlerUpdateVector(localId, pos5, this);
11619 }
11620 11814
11621 part.IgnoreUndoUpdate = false; 11815 case 0x0D: //(8 + 4 + 1) group scale and position
11622 } 11816 // exception as above
11623 11817
11624 break; 11818 udata.position = new Vector3(block.Data, 0);
11819 udata.scale = new Vector3(block.Data, 12);
11625 11820
11626 case 21: 11821 udata.change = ObjectChangeType.groupPS;
11627 Vector3 scale6 = new Vector3(block.Data, 12); 11822 updatehandler(localId, udata, this);
11628 Vector3 pos6 = new Vector3(block.Data, 0); 11823 break;
11629 11824
11630 handlerUpdatePrimScale = OnUpdatePrimScale; 11825 case 0x1C: // (0x10 + 8 + 4 ) group scale UNIFORM
11631 if (handlerUpdatePrimScale != null) 11826 udata.scale = new Vector3(block.Data, 0);
11632 {
11633 part.StoreUndoState(false);
11634 part.IgnoreUndoUpdate = true;
11635 11827
11636 // m_log.Debug("new scale is " + scale.X + " , " + scale.Y + " , " + scale.Z); 11828 udata.change = ObjectChangeType.groupUS;
11637 handlerUpdatePrimScale(localId, scale6, this); 11829 updatehandler(localId, udata, this);
11638 handlerUpdatePrimSinglePosition = OnUpdatePrimSinglePosition; 11830 break;
11639 if (handlerUpdatePrimSinglePosition != null)
11640 {
11641 handlerUpdatePrimSinglePosition(localId, pos6, this);
11642 }
11643 11831
11644 part.IgnoreUndoUpdate = false; 11832 case 0x1D: // (UNIFORM + GROUP + SCALE + POS)
11645 } 11833 udata.position = new Vector3(block.Data, 0);
11646 break; 11834 udata.scale = new Vector3(block.Data, 12);
11647 11835
11648 default: 11836 udata.change = ObjectChangeType.groupPUS;
11649 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type)); 11837 updatehandler(localId, udata, this);
11650 break; 11838 break;
11839
11840 default:
11841 m_log.Debug("[CLIENT]: MultipleObjUpdate recieved an unknown packet type: " + (block.Type));
11842 break;
11843 }
11651 } 11844 }
11652 11845
11653// for (int j = 0; j < parts.Length; j++)
11654// parts[j].IgnoreUndoUpdate = false;
11655 } 11846 }
11656 } 11847 }
11657 } 11848 }
11658
11659 return true; 11849 return true;
11660 } 11850 }
11661 11851
@@ -12103,7 +12293,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12103// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}", 12293// "[LLCLIENTVIEW]: Received transfer request for {0} in {1} type {2} by {3}",
12104// requestID, taskID, (SourceType)sourceType, Name); 12294// requestID, taskID, (SourceType)sourceType, Name);
12105 12295
12296
12297 //Note, the bool returned from the below function is useless since it is always false.
12106 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived); 12298 m_assetService.Get(requestID.ToString(), transferRequest, AssetReceived);
12299
12107 } 12300 }
12108 12301
12109 /// <summary> 12302 /// <summary>
@@ -12169,7 +12362,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12169 /// <returns></returns> 12362 /// <returns></returns>
12170 private static int CalculateNumPackets(byte[] data) 12363 private static int CalculateNumPackets(byte[] data)
12171 { 12364 {
12172 const uint m_maxPacketSize = 600; 12365// const uint m_maxPacketSize = 600;
12366 uint m_maxPacketSize = MaxTransferBytesPerPacket;
12173 int numPackets = 1; 12367 int numPackets = 1;
12174 12368
12175 if (data == null) 12369 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 14cc863..b8951d9 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 Stat m_incomingPacketPoolStat; 176 private Stat m_incomingPacketPoolStat;
@@ -974,21 +977,46 @@ namespace OpenSim.Region.ClientStack.LindenUDP
974 977
975 #region Packet to Client Mapping 978 #region Packet to Client Mapping
976 979
977 // UseCircuitCode handling 980 // If there is already a client for this endpoint, don't process UseCircuitCode
978 if (packet.Type == PacketType.UseCircuitCode) 981 IClientAPI client = null;
982 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
979 { 983 {
980 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the 984 // UseCircuitCode handling
981 // buffer. 985 if (packet.Type == PacketType.UseCircuitCode)
982 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; 986 {
987 // And if there is a UseCircuitCode pending, also drop it
988 lock (m_pendingCache)
989 {
990 if (m_pendingCache.Contains(endPoint))
991 return;
983 992
984 Util.FireAndForget(HandleUseCircuitCode, array); 993 m_pendingCache.AddOrUpdate(endPoint, new Queue<UDPPacketBuffer>(), 60);
994 }
985 995
986 return; 996 // We need to copy the endpoint so that it doesn't get changed when another thread reuses the
997 // buffer.
998 object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet };
999
1000 Util.FireAndForget(HandleUseCircuitCode, array);
1001
1002 return;
1003 }
1004 }
1005
1006 // If this is a pending connection, enqueue, don't process yet
1007 lock (m_pendingCache)
1008 {
1009 Queue<UDPPacketBuffer> queue;
1010 if (m_pendingCache.TryGetValue(endPoint, out queue))
1011 {
1012 //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type);
1013 queue.Enqueue(buffer);
1014 return;
1015 }
987 } 1016 }
988 1017
989 // Determine which agent this packet came from 1018 // Determine which agent this packet came from
990 IClientAPI client; 1019 if (client == null || !(client is LLClientView))
991 if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView))
992 { 1020 {
993 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName); 1021 //m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + " in " + m_scene.RegionInfo.RegionName);
994 return; 1022 return;
@@ -997,7 +1025,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
997 udpClient = ((LLClientView)client).UDPClient; 1025 udpClient = ((LLClientView)client).UDPClient;
998 1026
999 if (!udpClient.IsConnected) 1027 if (!udpClient.IsConnected)
1028 {
1029// m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet for a unConnected client in " + m_scene.RegionInfo.RegionName);
1000 return; 1030 return;
1031 }
1001 1032
1002 #endregion Packet to Client Mapping 1033 #endregion Packet to Client Mapping
1003 1034
@@ -1127,7 +1158,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1127 incomingPacket = new IncomingPacket((LLClientView)client, packet); 1158 incomingPacket = new IncomingPacket((LLClientView)client, packet);
1128 } 1159 }
1129 1160
1130 packetInbox.Enqueue(incomingPacket); 1161 if (incomingPacket.Packet.Type == PacketType.AgentUpdate ||
1162 incomingPacket.Packet.Type == PacketType.ChatFromViewer)
1163 packetInbox.EnqueueHigh(incomingPacket);
1164 else
1165 packetInbox.EnqueueLow(incomingPacket);
1131 } 1166 }
1132 1167
1133 #region BinaryStats 1168 #region BinaryStats
@@ -1247,6 +1282,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1247 // We only want to send initial data to new clients, not ones which are being converted from child to root. 1282 // We only want to send initial data to new clients, not ones which are being converted from child to root.
1248 if (client != null) 1283 if (client != null)
1249 client.SceneAgent.SendInitialDataToMe(); 1284 client.SceneAgent.SendInitialDataToMe();
1285
1286 // Now we know we can handle more data
1287 Thread.Sleep(200);
1288
1289 // Obtain the queue and remove it from the cache
1290 Queue<UDPPacketBuffer> queue = null;
1291
1292 lock (m_pendingCache)
1293 {
1294 if (!m_pendingCache.TryGetValue(endPoint, out queue))
1295 {
1296 m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present");
1297 return;
1298 }
1299 m_pendingCache.Remove(endPoint);
1300 }
1301
1302 m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count);
1303
1304 // Reinject queued packets
1305 while(queue.Count > 0)
1306 {
1307 UDPPacketBuffer buf = queue.Dequeue();
1308 PacketReceived(buf);
1309 }
1310 queue = null;
1250 } 1311 }
1251 else 1312 else
1252 { 1313 {
@@ -1254,6 +1315,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1254 m_log.WarnFormat( 1315 m_log.WarnFormat(
1255 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", 1316 "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}",
1256 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); 1317 uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint);
1318 lock (m_pendingCache)
1319 m_pendingCache.Remove(endPoint);
1257 } 1320 }
1258 1321
1259 // m_log.DebugFormat( 1322 // m_log.DebugFormat(
@@ -1372,7 +1435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1372 if (!client.SceneAgent.IsChildAgent) 1435 if (!client.SceneAgent.IsChildAgent)
1373 client.Kick("Simulator logged you out due to connection timeout"); 1436 client.Kick("Simulator logged you out due to connection timeout");
1374 1437
1375 client.CloseWithoutChecks(); 1438 client.CloseWithoutChecks(true);
1376 } 1439 }
1377 } 1440 }
1378 1441
@@ -1384,6 +1447,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1384 1447
1385 while (IsRunningInbound) 1448 while (IsRunningInbound)
1386 { 1449 {
1450 m_scene.ThreadAlive(1);
1387 try 1451 try
1388 { 1452 {
1389 IncomingPacket incomingPacket = null; 1453 IncomingPacket incomingPacket = null;
@@ -1431,6 +1495,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1431 1495
1432 while (base.IsRunningOutbound) 1496 while (base.IsRunningOutbound)
1433 { 1497 {
1498 m_scene.ThreadAlive(2);
1434 try 1499 try
1435 { 1500 {
1436 m_packetSent = false; 1501 m_packetSent = false;
@@ -1652,8 +1717,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1652 Packet packet = incomingPacket.Packet; 1717 Packet packet = incomingPacket.Packet;
1653 LLClientView client = incomingPacket.Client; 1718 LLClientView client = incomingPacket.Client;
1654 1719
1655 if (client.IsActive) 1720// if (client.IsActive)
1656 { 1721// {
1657 m_currentIncomingClient = client; 1722 m_currentIncomingClient = client;
1658 1723
1659 try 1724 try
@@ -1680,13 +1745,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1680 { 1745 {
1681 m_currentIncomingClient = null; 1746 m_currentIncomingClient = null;
1682 } 1747 }
1683 } 1748// }
1684 else 1749// else
1685 { 1750// {
1686 m_log.DebugFormat( 1751// m_log.DebugFormat(
1687 "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}", 1752// "[LLUDPSERVER]: Dropped incoming {0} for dead client {1} in {2}",
1688 packet.Type, client.Name, m_scene.RegionInfo.RegionName); 1753// packet.Type, client.Name, m_scene.RegionInfo.RegionName);
1689 } 1754// }
1690 } 1755 }
1691 1756
1692 protected void LogoutHandler(IClientAPI client) 1757 protected void LogoutHandler(IClientAPI client)
@@ -1696,8 +1761,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1696 if (!client.IsLoggingOut) 1761 if (!client.IsLoggingOut)
1697 { 1762 {
1698 client.IsLoggingOut = true; 1763 client.IsLoggingOut = true;
1699 client.Close(); 1764 client.Close(false, false);
1765 }
1766 }
1767 }
1768
1769 internal class DoubleQueue<T> where T:class
1770 {
1771 private Queue<T> m_lowQueue = new Queue<T>();
1772 private Queue<T> m_highQueue = new Queue<T>();
1773
1774 private object m_syncRoot = new object();
1775 private Semaphore m_s = new Semaphore(0, 1);
1776
1777 public DoubleQueue()
1778 {
1779 }
1780
1781 public virtual int Count
1782 {
1783 get { return m_highQueue.Count + m_lowQueue.Count; }
1784 }
1785
1786 public virtual void Enqueue(T data)
1787 {
1788 Enqueue(m_lowQueue, data);
1789 }
1790
1791 public virtual void EnqueueLow(T data)
1792 {
1793 Enqueue(m_lowQueue, data);
1794 }
1795
1796 public virtual void EnqueueHigh(T data)
1797 {
1798 Enqueue(m_highQueue, data);
1799 }
1800
1801 private void Enqueue(Queue<T> q, T data)
1802 {
1803 lock (m_syncRoot)
1804 {
1805 m_lowQueue.Enqueue(data);
1806 m_s.WaitOne(0);
1807 m_s.Release();
1808 }
1809 }
1810
1811 public virtual T Dequeue()
1812 {
1813 return Dequeue(Timeout.Infinite);
1814 }
1815
1816 public virtual T Dequeue(int tmo)
1817 {
1818 return Dequeue(TimeSpan.FromMilliseconds(tmo));
1819 }
1820
1821 public virtual T Dequeue(TimeSpan wait)
1822 {
1823 T res = null;
1824
1825 if (!Dequeue(wait, ref res))
1826 return null;
1827
1828 return res;
1829 }
1830
1831 public bool Dequeue(int timeout, ref T res)
1832 {
1833 return Dequeue(TimeSpan.FromMilliseconds(timeout), ref res);
1834 }
1835
1836 public bool Dequeue(TimeSpan wait, ref T res)
1837 {
1838 if (!m_s.WaitOne(wait))
1839 return false;
1840
1841 lock (m_syncRoot)
1842 {
1843 if (m_highQueue.Count > 0)
1844 res = m_highQueue.Dequeue();
1845 else
1846 res = m_lowQueue.Dequeue();
1847
1848 if (m_highQueue.Count == 0 && m_lowQueue.Count == 0)
1849 return true;
1850
1851 try
1852 {
1853 m_s.Release();
1854 }
1855 catch
1856 {
1857 }
1858
1859 return true;
1860 }
1861 }
1862
1863 public virtual void Clear()
1864 {
1865
1866 lock (m_syncRoot)
1867 {
1868 // Make sure sem count is 0
1869 m_s.WaitOne(0);
1870
1871 m_lowQueue.Clear();
1872 m_highQueue.Clear();
1700 } 1873 }
1701 } 1874 }
1702 } 1875 }
1703} \ No newline at end of file 1876}
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
index 85cbb06..8bd3461 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs
@@ -116,10 +116,6 @@ namespace OpenMetaverse
116 const int SIO_UDP_CONNRESET = -1744830452; 116 const int SIO_UDP_CONNRESET = -1744830452;
117 117
118 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort); 118 IPEndPoint ipep = new IPEndPoint(m_localBindAddress, m_udpPort);
119
120 m_log.DebugFormat(
121 "[UDPBASE]: Binding UDP listener using internal IP address config {0}:{1}",
122 ipep.Address, ipep.Port);
123 119
124 m_udpSocket = new Socket( 120 m_udpSocket = new Socket(
125 AddressFamily.InterNetwork, 121 AddressFamily.InterNetwork,