aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs719
1 files changed, 499 insertions, 220 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 7c62f90..f599342 100644
--- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
@@ -84,6 +84,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
84 public event ModifyTerrain OnModifyTerrain; 84 public event ModifyTerrain OnModifyTerrain;
85 public event Action<IClientAPI> OnRegionHandShakeReply; 85 public event Action<IClientAPI> OnRegionHandShakeReply;
86 public event GenericCall1 OnRequestWearables; 86 public event GenericCall1 OnRequestWearables;
87 public event CachedTextureRequest OnCachedTextureRequest;
87 public event SetAppearance OnSetAppearance; 88 public event SetAppearance OnSetAppearance;
88 public event AvatarNowWearing OnAvatarNowWearing; 89 public event AvatarNowWearing OnAvatarNowWearing;
89 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; 90 public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv;
@@ -95,6 +96,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
95 public event Action<IClientAPI, bool> OnCompleteMovementToRegion; 96 public event Action<IClientAPI, bool> OnCompleteMovementToRegion;
96 public event UpdateAgent OnPreAgentUpdate; 97 public event UpdateAgent OnPreAgentUpdate;
97 public event UpdateAgent OnAgentUpdate; 98 public event UpdateAgent OnAgentUpdate;
99 public event UpdateAgent OnAgentCameraUpdate;
98 public event AgentRequestSit OnAgentRequestSit; 100 public event AgentRequestSit OnAgentRequestSit;
99 public event AgentSit OnAgentSit; 101 public event AgentSit OnAgentSit;
100 public event AvatarPickerRequest OnAvatarPickerRequest; 102 public event AvatarPickerRequest OnAvatarPickerRequest;
@@ -335,6 +337,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
335 private bool m_VelocityInterpolate = false; 337 private bool m_VelocityInterpolate = false;
336 private const uint MaxTransferBytesPerPacket = 600; 338 private const uint MaxTransferBytesPerPacket = 600;
337 339
340 private volatile bool m_justEditedTerrain = false;
338 341
339 /// <value> 342 /// <value>
340 /// List used in construction of data blocks for an object update packet. This is to stop us having to 343 /// List used in construction of data blocks for an object update packet. This is to stop us having to
@@ -367,7 +370,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
367 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods 370 /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods
368 /// cannot retain a reference to it outside of that method. 371 /// cannot retain a reference to it outside of that method.
369 /// </remarks> 372 /// </remarks>
370 private AgentUpdateArgs m_lastAgentUpdateArgs; 373 private AgentUpdateArgs m_thisAgentUpdateArgs = new AgentUpdateArgs();
371 374
372 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>(); 375 protected Dictionary<PacketType, PacketProcessor> m_packetHandlers = new Dictionary<PacketType, PacketProcessor>();
373 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 376 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
@@ -504,6 +507,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 m_udpServer = udpServer; 507 m_udpServer = udpServer;
505 m_udpClient = udpClient; 508 m_udpClient = udpClient;
506 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 509 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
510 m_udpClient.HasUpdates += HandleHasUpdates;
507 m_udpClient.OnPacketStats += PopulateStats; 511 m_udpClient.OnPacketStats += PopulateStats;
508 512
509 m_prioritizer = new Prioritizer(m_scene); 513 m_prioritizer = new Prioritizer(m_scene);
@@ -533,7 +537,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
533 // We still perform a force close inside the sync lock since this is intended to attempt close where 537 // We still perform a force close inside the sync lock since this is intended to attempt close where
534 // there is some unidentified connection problem, not where we have issues due to deadlock 538 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force) 539 if (!IsActive && !force)
540 {
541 m_log.DebugFormat(
542 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set",
543 Name, m_scene.Name);
544
536 return; 545 return;
546 }
537 547
538 IsActive = false; 548 IsActive = false;
539 CloseWithoutChecks(sendStop); 549 CloseWithoutChecks(sendStop);
@@ -709,12 +719,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
709 //there is a local handler for this packet type 719 //there is a local handler for this packet type
710 if (pprocessor.Async) 720 if (pprocessor.Async)
711 { 721 {
722 ClientInfo cinfo = UDPClient.GetClientInfo();
723 if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString()))
724 cinfo.AsyncRequests[packet.Type.ToString()] = 0;
725 cinfo.AsyncRequests[packet.Type.ToString()]++;
726
712 object obj = new AsyncPacketProcess(this, pprocessor.method, packet); 727 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
713 Util.FireAndForget(ProcessSpecificPacketAsync, obj); 728 Util.FireAndForget(ProcessSpecificPacketAsync, obj);
714 result = true; 729 result = true;
715 } 730 }
716 else 731 else
717 { 732 {
733 ClientInfo cinfo = UDPClient.GetClientInfo();
734 if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString()))
735 cinfo.SyncRequests[packet.Type.ToString()] = 0;
736 cinfo.SyncRequests[packet.Type.ToString()]++;
737
718 result = pprocessor.method(this, packet); 738 result = pprocessor.method(this, packet);
719 } 739 }
720 } 740 }
@@ -729,6 +749,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
729 } 749 }
730 if (found) 750 if (found)
731 { 751 {
752 ClientInfo cinfo = UDPClient.GetClientInfo();
753 if (!cinfo.GenericRequests.ContainsKey(packet.Type.ToString()))
754 cinfo.GenericRequests[packet.Type.ToString()] = 0;
755 cinfo.GenericRequests[packet.Type.ToString()]++;
756
732 result = method(this, packet); 757 result = method(this, packet);
733 } 758 }
734 } 759 }
@@ -758,7 +783,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
758 783
759 public virtual void Start() 784 public virtual void Start()
760 { 785 {
761 m_scene.AddNewClient(this, PresenceType.User); 786 m_scene.AddNewAgent(this, PresenceType.User);
762 787
763 RefreshGroupMembership(); 788 RefreshGroupMembership();
764 } 789 }
@@ -820,12 +845,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
820 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 845 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
821 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 846 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
822 847
823 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[0]; 848 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[1];
824// OutPacket(handshake, ThrottleOutPacketType.Task); 849 handshake.RegionInfo4[0] = new RegionHandshakePacket.RegionInfo4Block();
825 // use same as MoveAgentIntoRegion (both should be task ) 850 handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags;
851 handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported
852
826 OutPacket(handshake, ThrottleOutPacketType.Unknown); 853 OutPacket(handshake, ThrottleOutPacketType.Unknown);
827 } 854 }
828 855
856
829 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 857 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
830 { 858 {
831 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); 859 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
@@ -1210,9 +1238,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1210 LLHeightFieldMoronize(map); 1238 LLHeightFieldMoronize(map);
1211 1239
1212 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1240 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1213 layerpack.Header.Reliable = true; 1241
1242 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1243 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
1244 // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
1245 // invalidating previous packets for that area.
1246
1247 // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
1248 // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
1249
1250 // One last note on this topic, by the time users are going to be editing the terrain, it's extremely likely that the sim will
1251 // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
1252 // patches.
1214 1253
1215 OutPacket(layerpack, ThrottleOutPacketType.Task); 1254 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
1255 if (m_justEditedTerrain)
1256 {
1257 layerpack.Header.Reliable = false;
1258 OutPacket(layerpack,
1259 ThrottleOutPacketType.Unknown );
1260 }
1261 else
1262 {
1263 layerpack.Header.Reliable = true;
1264 OutPacket(layerpack,
1265 ThrottleOutPacketType.Task);
1266 }
1216 } 1267 }
1217 catch (Exception e) 1268 catch (Exception e)
1218 { 1269 {
@@ -1405,6 +1456,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1405 1456
1406 mapReply.AgentData.AgentID = AgentId; 1457 mapReply.AgentData.AgentID = AgentId;
1407 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; 1458 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length];
1459 mapReply.Size = new MapBlockReplyPacket.SizeBlock[mapBlocks2.Length];
1408 mapReply.AgentData.Flags = flag; 1460 mapReply.AgentData.Flags = flag;
1409 1461
1410 for (int i = 0; i < mapBlocks2.Length; i++) 1462 for (int i = 0; i < mapBlocks2.Length; i++)
@@ -1419,6 +1471,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1419 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; 1471 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags;
1420 mapReply.Data[i].Access = mapBlocks2[i].Access; 1472 mapReply.Data[i].Access = mapBlocks2[i].Access;
1421 mapReply.Data[i].Agents = mapBlocks2[i].Agents; 1473 mapReply.Data[i].Agents = mapBlocks2[i].Agents;
1474
1475 // TODO: hookup varregion sim size here
1476 mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock();
1477 mapReply.Size[i].SizeX = 256;
1478 mapReply.Size[i].SizeY = 256;
1422 } 1479 }
1423 OutPacket(mapReply, ThrottleOutPacketType.Land); 1480 OutPacket(mapReply, ThrottleOutPacketType.Land);
1424 } 1481 }
@@ -1580,7 +1637,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1580 OutPacket(pc, ThrottleOutPacketType.Unknown); 1637 OutPacket(pc, ThrottleOutPacketType.Unknown);
1581 } 1638 }
1582 1639
1583 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1640 public void SendKillObject(List<uint> localIDs)
1584 { 1641 {
1585// foreach (uint id in localIDs) 1642// foreach (uint id in localIDs)
1586// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); 1643// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
@@ -2594,11 +2651,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2594 { 2651 {
2595 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); 2652 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2596 avatarSitResponse.SitObject.ID = TargetID; 2653 avatarSitResponse.SitObject.ID = TargetID;
2597 if (CameraAtOffset != Vector3.Zero) 2654 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2598 { 2655 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2599 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2600 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2601 }
2602 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; 2656 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
2603 avatarSitResponse.SitTransform.AutoPilot = autopilot; 2657 avatarSitResponse.SitTransform.AutoPilot = autopilot;
2604 avatarSitResponse.SitTransform.SitPosition = OffsetPos; 2658 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
@@ -3794,12 +3848,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3794 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber); 3848 m_udpClient.NeedAcks.Remove(oPacket.SequenceNumber);
3795 3849
3796 // Count this as a resent packet since we are going to requeue all of the updates contained in it 3850 // Count this as a resent packet since we are going to requeue all of the updates contained in it
3797 Interlocked.Increment(ref m_udpClient.PacketsResent); 3851 Interlocked.Increment(ref m_udpClient.PacketsResent);
3852
3853 // We're not going to worry about interlock yet since its not currently critical that this total count
3854 // is 100% correct
3855 m_udpServer.PacketsResentCount++;
3798 3856
3799 foreach (EntityUpdate update in updates) 3857 foreach (EntityUpdate update in updates)
3800 ResendPrimUpdate(update); 3858 ResendPrimUpdate(update);
3801 } 3859 }
3802 3860
3861// OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
3862// OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>();
3863// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3864// OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseAgentUpdateBlocks = new OpenSim.Framework.Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>();
3865//
3866// OpenSim.Framework.Lazy<List<EntityUpdate>> objectUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3867// OpenSim.Framework.Lazy<List<EntityUpdate>> compressedUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3868// OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3869// OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3870
3871
3803 private void ProcessEntityUpdates(int maxUpdates) 3872 private void ProcessEntityUpdates(int maxUpdates)
3804 { 3873 {
3805 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3874 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3812,6 +3881,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3812 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3881 OpenSim.Framework.Lazy<List<EntityUpdate>> terseUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3813 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>(); 3882 OpenSim.Framework.Lazy<List<EntityUpdate>> terseAgentUpdates = new OpenSim.Framework.Lazy<List<EntityUpdate>>();
3814 3883
3884// objectUpdateBlocks.Value.Clear();
3885// compressedUpdateBlocks.Value.Clear();
3886// terseUpdateBlocks.Value.Clear();
3887// terseAgentUpdateBlocks.Value.Clear();
3888// objectUpdates.Value.Clear();
3889// compressedUpdates.Value.Clear();
3890// terseUpdates.Value.Clear();
3891// terseAgentUpdates.Value.Clear();
3892
3815 // Check to see if this is a flush 3893 // Check to see if this is a flush
3816 if (maxUpdates <= 0) 3894 if (maxUpdates <= 0)
3817 { 3895 {
@@ -4140,8 +4218,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4140 4218
4141 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 4219 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
4142 { 4220 {
4221// if (!m_udpServer.IsRunningOutbound)
4222// return;
4223
4143 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 4224 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4144 { 4225 {
4226// if (!m_udpServer.IsRunningOutbound)
4227// return;
4228
4145 if (m_maxUpdates == 0 || m_LastQueueFill == 0) 4229 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
4146 { 4230 {
4147 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; 4231 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
@@ -4167,6 +4251,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4167 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); 4251 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
4168 } 4252 }
4169 4253
4254 internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories)
4255 {
4256 bool hasUpdates = false;
4257
4258 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4259 {
4260 if (m_entityUpdates.Count > 0)
4261 hasUpdates = true;
4262 else if (m_entityProps.Count > 0)
4263 hasUpdates = true;
4264 }
4265
4266 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
4267 {
4268 if (ImageManager.HasUpdates())
4269 hasUpdates = true;
4270 }
4271
4272 return hasUpdates;
4273 }
4274
4170 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 4275 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
4171 { 4276 {
4172 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); 4277 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
@@ -4312,6 +4417,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4312 // Count this as a resent packet since we are going to requeue all of the updates contained in it 4417 // Count this as a resent packet since we are going to requeue all of the updates contained in it
4313 Interlocked.Increment(ref m_udpClient.PacketsResent); 4418 Interlocked.Increment(ref m_udpClient.PacketsResent);
4314 4419
4420 // We're not going to worry about interlock yet since its not currently critical that this total count
4421 // is 100% correct
4422 m_udpServer.PacketsResentCount++;
4423
4315 foreach (ObjectPropertyUpdate update in updates) 4424 foreach (ObjectPropertyUpdate update in updates)
4316 ResendPropertyUpdate(update); 4425 ResendPropertyUpdate(update);
4317 } 4426 }
@@ -4499,6 +4608,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4499 SceneObjectPart root = sop.ParentGroup.RootPart; 4608 SceneObjectPart root = sop.ParentGroup.RootPart;
4500 4609
4501 block.TouchName = Util.StringToBytes256(root.TouchName); 4610 block.TouchName = Util.StringToBytes256(root.TouchName);
4611
4612 // SL 3.3.4, at least, appears to read this information as a concatenated byte[] stream of UUIDs but
4613 // it's not yet clear whether this is actually used. If this is done in the future then a pre-cached
4614 // copy is really needed since it's less efficient to be constantly recreating this byte array.
4615// using (MemoryStream memStream = new MemoryStream())
4616// {
4617// using (BinaryWriter binWriter = new BinaryWriter(memStream))
4618// {
4619// for (int i = 0; i < sop.GetNumberOfSides(); i++)
4620// {
4621// Primitive.TextureEntryFace teFace = sop.Shape.Textures.FaceTextures[i];
4622//
4623// UUID textureID;
4624//
4625// if (teFace != null)
4626// textureID = teFace.TextureID;
4627// else
4628// textureID = sop.Shape.Textures.DefaultTexture.TextureID;
4629//
4630// binWriter.Write(textureID.GetBytes());
4631// }
4632//
4633// block.TextureID = memStream.ToArray();
4634// }
4635// }
4636
4502 block.TextureID = new byte[0]; // TextureID ??? 4637 block.TextureID = new byte[0]; // TextureID ???
4503 block.SitName = Util.StringToBytes256(root.SitName); 4638 block.SitName = Util.StringToBytes256(root.SitName);
4504 block.OwnerMask = root.OwnerMask; 4639 block.OwnerMask = root.OwnerMask;
@@ -4877,7 +5012,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4877 5012
4878 public void SendForceClientSelectObjects(List<uint> ObjectIDs) 5013 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4879 { 5014 {
4880 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); 5015// m_log.DebugFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4881 5016
4882 bool firstCall = true; 5017 bool firstCall = true;
4883 const int MAX_OBJECTS_PER_PACKET = 251; 5018 const int MAX_OBJECTS_PER_PACKET = 251;
@@ -5015,15 +5150,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5015 } 5150 }
5016 5151
5017 attachPoint = 0; 5152 attachPoint = 0;
5153// m_log.DebugFormat(
5154// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5155
5156 // attachPoint = presence.State; // Core: commented
5018 collisionPlane = presence.CollisionPlane; 5157 collisionPlane = presence.CollisionPlane;
5019 velocity = presence.Velocity; 5158 velocity = presence.Velocity;
5020 acceleration = Vector3.Zero; 5159 acceleration = Vector3.Zero;
5021 5160
5022 // Interestingly, sending this to non-zero will cause the client's avatar to start moving & accelerating
5023 // in that direction, even though we don't model this on the server. Implementing this in the future
5024 // may improve movement smoothness.
5025// acceleration = new Vector3(1, 0, 0);
5026
5027 if (sendTexture) 5161 if (sendTexture)
5028 textureEntry = presence.Appearance.Texture.GetBytes(); 5162 textureEntry = presence.Appearance.Texture.GetBytes();
5029 else 5163 else
@@ -5034,7 +5168,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5034 SceneObjectPart part = (SceneObjectPart)entity; 5168 SceneObjectPart part = (SceneObjectPart)entity;
5035 5169
5036 attachPoint = part.ParentGroup.AttachmentPoint; 5170 attachPoint = part.ParentGroup.AttachmentPoint;
5037 5171 attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
5038// m_log.DebugFormat( 5172// m_log.DebugFormat(
5039// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", 5173// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
5040// attachPoint, part.Name, part.LocalId, Name); 5174// attachPoint, part.Name, part.LocalId, Name);
@@ -5062,7 +5196,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5062 pos += 4; 5196 pos += 4;
5063 5197
5064 // Avatar/CollisionPlane 5198 // Avatar/CollisionPlane
5065 data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; 5199 data[pos++] = (byte) attachPoint;
5066 if (avatar) 5200 if (avatar)
5067 { 5201 {
5068 data[pos++] = 1; 5202 data[pos++] = 1;
@@ -5143,6 +5277,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5143 parentID = part.ParentGroup.RootPart.LocalId; 5277 parentID = part.ParentGroup.RootPart.LocalId;
5144 } 5278 }
5145 } 5279 }
5280// m_log.DebugFormat(
5281// "[LLCLIENTVIEW]: Sending full update to {0} with position {1} in {2}", Name, data.OffsetPosition, m_scene.Name);
5146 5282
5147 byte[] objectData = new byte[76]; 5283 byte[] objectData = new byte[76];
5148 5284
@@ -5168,7 +5304,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5168 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5304 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5169 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5305 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5170 update.ObjectData = objectData; 5306 update.ObjectData = objectData;
5171 update.ParentID = parentID; 5307
5308 SceneObjectPart parentPart = data.ParentPart;
5309 if (parentPart != null)
5310 update.ParentID = parentPart.ParentGroup.LocalId;
5311 else
5312 update.ParentID = 0;
5313
5172 update.PathCurve = 16; 5314 update.PathCurve = 16;
5173 update.PathScaleX = 100; 5315 update.PathScaleX = 100;
5174 update.PathScaleY = 100; 5316 update.PathScaleY = 100;
@@ -5387,7 +5529,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5387 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject); 5529 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject);
5388 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); 5530 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject);
5389 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); 5531 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand);
5390 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply); 5532 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, false);
5391 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest); 5533 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest);
5392 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance); 5534 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance);
5393 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing); 5535 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing);
@@ -5448,8 +5590,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5448 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false); 5590 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false);
5449 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false); 5591 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false);
5450 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false); 5592 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false);
5451 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage); 5593 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage, false);
5452 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest); 5594 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest, false);
5453 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); 5595 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest);
5454 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); 5596 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer);
5455 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); 5597 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket);
@@ -5481,7 +5623,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5481 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); 5623 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel);
5482 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5624 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
5483 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); 5625 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
5484 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); 5626 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest, false);
5485 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest); 5627 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
5486 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); 5628 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
5487 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); 5629 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
@@ -5594,83 +5736,137 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5594 5736
5595 #region Packet Handlers 5737 #region Packet Handlers
5596 5738
5739 public int TotalAgentUpdates { get; set; }
5740
5597 #region Scene/Avatar 5741 #region Scene/Avatar
5598 5742
5599 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5743 // Threshold for body rotation to be a significant agent update
5744 private const float QDELTA = 0.000001f;
5745 // Threshold for camera rotation to be a significant agent update
5746 private const float VDELTA = 0.01f;
5747
5748 /// <summary>
5749 /// This checks the update significance against the last update made.
5750 /// </summary>
5751 /// <remarks>Can only be called by one thread at a time</remarks>
5752 /// <returns></returns>
5753 /// <param name='x'></param>
5754 public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5600 { 5755 {
5601 if (OnAgentUpdate != null) 5756 return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x);
5602 { 5757 }
5603 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5604 5758
5605 #region Packet Session and User Check 5759 /// <summary>
5606 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) 5760 /// This checks the movement/state update significance against the last update made.
5607 { 5761 /// </summary>
5608 PacketPool.Instance.ReturnPacket(packet); 5762 /// <remarks>Can only be called by one thread at a time</remarks>
5609 return false; 5763 /// <returns></returns>
5610 } 5764 /// <param name='x'></param>
5611 #endregion 5765 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5766 {
5767 float qdelta1 = 1 - (float)Math.Pow(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation), 2);
5768 //qdelta2 = 1 - (float)Math.Pow(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation), 2);
5769
5770 bool movementSignificant =
5771 (qdelta1 > QDELTA) // significant if body rotation above threshold
5772 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5773 // || (qdelta2 > QDELTA * 10) // significant if head rotation above threshold
5774 || (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5775 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands
5776 || (x.Far != m_thisAgentUpdateArgs.Far) // significant if far distance changed
5777 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
5778 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
5779 ;
5780 //if (movementSignificant)
5781 //{
5782 //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}",
5783 // qdelta1, qdelta2);
5784 //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}",
5785 // x.ControlFlags, x.Flags, x.Far, x.State);
5786 //}
5787 return movementSignificant;
5788 }
5612 5789
5613 bool update = false; 5790 /// <summary>
5614 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5791 /// This checks the camera update significance against the last update made.
5615 5792 /// </summary>
5616 if (m_lastAgentUpdateArgs != null) 5793 /// <remarks>Can only be called by one thread at a time</remarks>
5617 { 5794 /// <returns></returns>
5618 // These should be ordered from most-likely to 5795 /// <param name='x'></param>
5619 // least likely to change. I've made an initial 5796 private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5620 // guess at that. 5797 {
5621 update = 5798 float vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis);
5622 ( 5799 float vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter);
5623 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || 5800 float vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis);
5624 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || 5801 float vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis);
5625 (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) ||
5626 (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) ||
5627 (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) ||
5628 (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) ||
5629 (x.ControlFlags != 0) ||
5630 (x.Far != m_lastAgentUpdateArgs.Far) ||
5631 (x.Flags != m_lastAgentUpdateArgs.Flags) ||
5632 (x.State != m_lastAgentUpdateArgs.State) ||
5633 (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) ||
5634 (x.SessionID != m_lastAgentUpdateArgs.SessionID) ||
5635 (x.AgentID != m_lastAgentUpdateArgs.AgentID)
5636 );
5637 }
5638 else
5639 {
5640 m_lastAgentUpdateArgs = new AgentUpdateArgs();
5641 update = true;
5642 }
5643 5802
5644 if (update) 5803 bool cameraSignificant =
5645 { 5804 (vdelta1 > VDELTA) ||
5646// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5805 (vdelta2 > VDELTA) ||
5806 (vdelta3 > VDELTA) ||
5807 (vdelta4 > VDELTA)
5808 ;
5647 5809
5648 m_lastAgentUpdateArgs.AgentID = x.AgentID; 5810 //if (cameraSignificant)
5649 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; 5811 //{
5650 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; 5812 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}",
5651 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; 5813 // x.CameraAtAxis, x.CameraCenter);
5652 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; 5814 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}",
5653 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; 5815 // x.CameraLeftAxis, x.CameraUpAxis);
5654 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; 5816 //}
5655 m_lastAgentUpdateArgs.Far = x.Far;
5656 m_lastAgentUpdateArgs.Flags = x.Flags;
5657 m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation;
5658 m_lastAgentUpdateArgs.SessionID = x.SessionID;
5659 m_lastAgentUpdateArgs.State = x.State;
5660 5817
5661 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5818 return cameraSignificant;
5662 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5819 }
5663 5820
5664 if (handlerPreAgentUpdate != null) 5821 private bool HandleAgentUpdate(IClientAPI sener, Packet packet)
5665 OnPreAgentUpdate(this, m_lastAgentUpdateArgs); 5822 {
5823 // We got here, which means that something in agent update was significant
5666 5824
5667 if (handlerAgentUpdate != null) 5825 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5668 OnAgentUpdate(this, m_lastAgentUpdateArgs); 5826 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5669 5827
5670 handlerAgentUpdate = null; 5828 if (x.AgentID != AgentId || x.SessionID != SessionId)
5671 handlerPreAgentUpdate = null; 5829 return false;
5672 } 5830
5673 } 5831 // Before we update the current m_thisAgentUpdateArgs, let's check this again
5832 // to see what exactly changed
5833 bool movement = CheckAgentMovementUpdateSignificance(x);
5834 bool camera = CheckAgentCameraUpdateSignificance(x);
5835
5836 m_thisAgentUpdateArgs.AgentID = x.AgentID;
5837 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5838 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5839 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
5840 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5841 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5842 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5843 m_thisAgentUpdateArgs.Far = x.Far;
5844 m_thisAgentUpdateArgs.Flags = x.Flags;
5845 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5846 m_thisAgentUpdateArgs.SessionID = x.SessionID;
5847 m_thisAgentUpdateArgs.State = x.State;
5848
5849 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5850 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5851 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
5852
5853 // Was there a significant movement/state change?
5854 if (movement)
5855 {
5856 if (handlerPreAgentUpdate != null)
5857 OnPreAgentUpdate(this, m_thisAgentUpdateArgs);
5858
5859 if (handlerAgentUpdate != null)
5860 OnAgentUpdate(this, m_thisAgentUpdateArgs);
5861 }
5862 // Was there a significant camera(s) change?
5863 if (camera)
5864 if (handlerAgentCameraUpdate != null)
5865 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs);
5866
5867 handlerAgentUpdate = null;
5868 handlerPreAgentUpdate = null;
5869 handlerAgentCameraUpdate = null;
5674 5870
5675 PacketPool.Instance.ReturnPacket(packet); 5871 PacketPool.Instance.ReturnPacket(packet);
5676 5872
@@ -6260,6 +6456,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6260 //m_log.Info("[LAND]: LAND:" + modify.ToString()); 6456 //m_log.Info("[LAND]: LAND:" + modify.ToString());
6261 if (modify.ParcelData.Length > 0) 6457 if (modify.ParcelData.Length > 0)
6262 { 6458 {
6459 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6460 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6461 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6263 if (OnModifyTerrain != null) 6462 if (OnModifyTerrain != null)
6264 { 6463 {
6265 for (int i = 0; i < modify.ParcelData.Length; i++) 6464 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6275,6 +6474,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6275 } 6474 }
6276 } 6475 }
6277 } 6476 }
6477 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6278 } 6478 }
6279 6479
6280 return true; 6480 return true;
@@ -6636,6 +6836,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6636 } 6836 }
6637 #endregion 6837 #endregion
6638 6838
6839 if (SceneAgent.IsChildAgent)
6840 {
6841 SendCantSitBecauseChildAgentResponse();
6842 return true;
6843 }
6844
6639 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; 6845 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6640 6846
6641 if (handlerAgentRequestSit != null) 6847 if (handlerAgentRequestSit != null)
@@ -6660,6 +6866,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6660 } 6866 }
6661 #endregion 6867 #endregion
6662 6868
6869 if (SceneAgent.IsChildAgent)
6870 {
6871 SendCantSitBecauseChildAgentResponse();
6872 return true;
6873 }
6874
6663 AgentSit handlerAgentSit = OnAgentSit; 6875 AgentSit handlerAgentSit = OnAgentSit;
6664 if (handlerAgentSit != null) 6876 if (handlerAgentSit != null)
6665 { 6877 {
@@ -6669,6 +6881,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6669 return true; 6881 return true;
6670 } 6882 }
6671 6883
6884 /// <summary>
6885 /// Used when a child agent gets a sit response which should not be fulfilled.
6886 /// </summary>
6887 private void SendCantSitBecauseChildAgentResponse()
6888 {
6889 SendAlertMessage("Try moving closer. Can't sit on object because it is not in the same region as you.");
6890 }
6891
6672 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) 6892 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
6673 { 6893 {
6674 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; 6894 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
@@ -7879,129 +8099,145 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7879 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); 8099 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
7880 8100
7881 TransferRequestPacket transfer = (TransferRequestPacket)Pack; 8101 TransferRequestPacket transfer = (TransferRequestPacket)Pack;
7882 //m_log.Debug("Transfer Request: " + transfer.ToString());
7883 // Validate inventory transfers
7884 // Has to be done here, because AssetCache can't do it
7885 //
7886 UUID taskID = UUID.Zero; 8102 UUID taskID = UUID.Zero;
7887 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) 8103 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
7888 { 8104 {
7889 taskID = new UUID(transfer.TransferInfo.Params, 48);
7890 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7891 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7892
7893// m_log.DebugFormat(
7894// "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7895// requestID, itemID, taskID, Name);
7896
7897 if (!(((Scene)m_scene).Permissions.BypassPermissions())) 8105 if (!(((Scene)m_scene).Permissions.BypassPermissions()))
7898 { 8106 {
7899 if (taskID != UUID.Zero) // Prim 8107 // We're spawning a thread because the permissions check can block this thread
8108 Util.FireAndForget(delegate
7900 { 8109 {
7901 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); 8110 // This requests the asset if needed
8111 HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer);
8112 });
8113 return true;
8114 }
8115 }
8116 else if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate)
8117 {
8118 //TransferRequestPacket does not include covenant uuid?
8119 //get scene covenant uuid
8120 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
8121 }
7902 8122
7903 if (part == null) 8123 // This is non-blocking
7904 { 8124 MakeAssetRequest(transfer, taskID);
7905 m_log.WarnFormat(
7906 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7907 Name, requestID, itemID, taskID);
7908 return true;
7909 }
7910 8125
7911 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); 8126 return true;
7912 if (tii == null) 8127 }
7913 {
7914 m_log.WarnFormat(
7915 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7916 Name, requestID, itemID, taskID);
7917 return true;
7918 }
7919 8128
7920 if (tii.Type == (int)AssetType.LSLText) 8129 private void HandleSimInventoryTransferRequestWithPermsCheck(IClientAPI sender, TransferRequestPacket transfer)
7921 { 8130 {
7922 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) 8131 UUID taskID = new UUID(transfer.TransferInfo.Params, 48);
7923 return true; 8132 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7924 } 8133 UUID requestID = new UUID(transfer.TransferInfo.Params, 80);
7925 else if (tii.Type == (int)AssetType.Notecard)
7926 {
7927 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
7928 return true;
7929 }
7930 else
7931 {
7932 // TODO: Change this code to allow items other than notecards and scripts to be successfully
7933 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
7934 if (part.OwnerID != AgentId)
7935 {
7936 m_log.WarnFormat(
7937 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
7938 Name, requestID, itemID, taskID, part.OwnerID);
7939 return true;
7940 }
7941 8134
7942 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) 8135 //m_log.DebugFormat(
7943 { 8136 // "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7944 m_log.WarnFormat( 8137 // requestID, itemID, taskID, Name);
7945 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7946 Name, requestID, itemID, taskID);
7947 return true;
7948 }
7949 8138
7950 if (tii.OwnerID != AgentId) 8139 //m_log.Debug("Transfer Request: " + transfer.ToString());
7951 { 8140 // Validate inventory transfers
7952 m_log.WarnFormat( 8141 // Has to be done here, because AssetCache can't do it
7953 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}", 8142 //
7954 Name, requestID, itemID, taskID, tii.OwnerID); 8143 if (taskID != UUID.Zero) // Prim
7955 return true; 8144 {
7956 } 8145 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
7957 8146
7958 if (( 8147 if (part == null)
7959 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8148 {
7960 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8149 m_log.WarnFormat(
7961 { 8150 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7962 m_log.WarnFormat( 8151 Name, requestID, itemID, taskID);
7963 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", 8152 return;
7964 Name, requestID, itemID, taskID); 8153 }
7965 return true;
7966 }
7967 8154
7968 if (tii.AssetID != requestID) 8155 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
7969 { 8156 if (tii == null)
7970 m_log.WarnFormat( 8157 {
7971 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", 8158 m_log.WarnFormat(
7972 Name, requestID, itemID, taskID, tii.AssetID); 8159 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7973 return true; 8160 Name, requestID, itemID, taskID);
7974 } 8161 return;
7975 } 8162 }
8163
8164 if (tii.Type == (int)AssetType.LSLText)
8165 {
8166 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId))
8167 return;
8168 }
8169 else if (tii.Type == (int)AssetType.Notecard)
8170 {
8171 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
8172 return;
8173 }
8174 else
8175 {
8176 // TODO: Change this code to allow items other than notecards and scripts to be successfully
8177 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
8178 if (part.OwnerID != AgentId)
8179 {
8180 m_log.WarnFormat(
8181 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
8182 Name, requestID, itemID, taskID, part.OwnerID);
8183 return;
7976 } 8184 }
7977 else // Agent 8185
8186 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
7978 { 8187 {
7979 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 8188 m_log.WarnFormat(
7980 if (invAccess != null) 8189 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7981 { 8190 Name, requestID, itemID, taskID);
7982 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) 8191 return;
7983 return false; 8192 }
7984 } 8193
7985 else 8194 if (tii.OwnerID != AgentId)
7986 { 8195 {
7987 return false; 8196 m_log.WarnFormat(
7988 } 8197 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
8198 Name, requestID, itemID, taskID, tii.OwnerID);
8199 return;
8200 }
8201
8202 if ((
8203 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8204 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8205 {
8206 m_log.WarnFormat(
8207 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
8208 Name, requestID, itemID, taskID);
8209 return;
8210 }
8211
8212 if (tii.AssetID != requestID)
8213 {
8214 m_log.WarnFormat(
8215 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
8216 Name, requestID, itemID, taskID, tii.AssetID);
8217 return;
7989 } 8218 }
7990 } 8219 }
7991 } 8220 }
7992 else 8221 else // Agent
7993 if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate) 8222 {
8223 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
8224 if (invAccess != null)
7994 { 8225 {
7995 //TransferRequestPacket does not include covenant uuid? 8226 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID))
7996 //get scene covenant uuid 8227 return;
7997 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
7998 } 8228 }
8229 else
8230 {
8231 return;
8232 }
8233 }
7999 8234
8235 // Permissions out of the way, let's request the asset
8000 MakeAssetRequest(transfer, taskID); 8236 MakeAssetRequest(transfer, taskID);
8001 8237
8002 return true;
8003 } 8238 }
8004 8239
8240
8005 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack) 8241 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack)
8006 { 8242 {
8007 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; 8243 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
@@ -11732,8 +11968,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11732 } 11968 }
11733 11969
11734 /// <summary> 11970 /// <summary>
11735 /// Send a response back to a client when it asks the asset server (via the region server) if it has
11736 /// its appearance texture cached.
11737 /// </summary> 11971 /// </summary>
11738 /// <remarks> 11972 /// <remarks>
11739 /// At the moment, we always reply that there is no cached texture. 11973 /// At the moment, we always reply that there is no cached texture.
@@ -11741,6 +11975,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11741 /// <param name="simclient"></param> 11975 /// <param name="simclient"></param>
11742 /// <param name="packet"></param> 11976 /// <param name="packet"></param>
11743 /// <returns></returns> 11977 /// <returns></returns>
11978 // TODO: Convert old handler to use new method
11979 /*protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11980 {
11981 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11982
11983 if (cachedtex.AgentData.SessionID != SessionId)
11984 return false;
11985
11986
11987 List<CachedTextureRequestArg> requestArgs = new List<CachedTextureRequestArg>();
11988
11989 for (int i = 0; i < cachedtex.WearableData.Length; i++)
11990 {
11991 CachedTextureRequestArg arg = new CachedTextureRequestArg();
11992 arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex;
11993 arg.WearableHashID = cachedtex.WearableData[i].ID;
11994
11995 requestArgs.Add(arg);
11996 }
11997
11998 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
11999 if (handlerCachedTextureRequest != null)
12000 {
12001 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
12002 }
12003
12004 return true;
12005 }*/
12006
11744 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 12007 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11745 { 12008 {
11746 //m_log.Debug("texture cached: " + packet.ToString()); 12009 //m_log.Debug("texture cached: " + packet.ToString());
@@ -11899,6 +12162,40 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11899 return true; 12162 return true;
11900 } 12163 }
11901 12164
12165 /// <summary>
12166 /// Send a response back to a client when it asks the asset server (via the region server) if it has
12167 /// its appearance texture cached.
12168 /// </summary>
12169 /// <param name="avatar"></param>
12170 /// <param name="serial"></param>
12171 /// <param name="cachedTextures"></param>
12172 /// <returns></returns>
12173 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
12174 {
12175 ScenePresence presence = avatar as ScenePresence;
12176 if (presence == null)
12177 return;
12178
12179 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
12180
12181 // TODO: don't create new blocks if recycling an old packet
12182 cachedresp.AgentData.AgentID = m_agentId;
12183 cachedresp.AgentData.SessionID = m_sessionId;
12184 cachedresp.AgentData.SerialNum = serial;
12185 cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedTextures.Count];
12186
12187 for (int i = 0; i < cachedTextures.Count; i++)
12188 {
12189 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
12190 cachedresp.WearableData[i].TextureIndex = (byte)cachedTextures[i].BakedTextureIndex;
12191 cachedresp.WearableData[i].TextureID = cachedTextures[i].BakedTextureID;
12192 cachedresp.WearableData[i].HostName = new byte[0];
12193 }
12194
12195 cachedresp.Header.Zerocoded = true;
12196 OutPacket(cachedresp, ThrottleOutPacketType.Task);
12197 }
12198
11902 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) 12199 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet)
11903 { 12200 {
11904 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; 12201 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
@@ -11924,8 +12221,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11924 if (part == null) 12221 if (part == null)
11925 { 12222 {
11926 // It's a ghost! tell the client to delete it from view. 12223 // It's a ghost! tell the client to delete it from view.
11927 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 12224 simClient.SendKillObject(new List<uint> { localId });
11928 new List<uint> { localId });
11929 } 12225 }
11930 else 12226 else
11931 { 12227 {
@@ -12299,6 +12595,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12299 12595
12300 shape.PCode = addPacket.ObjectData.PCode; 12596 shape.PCode = addPacket.ObjectData.PCode;
12301 shape.State = addPacket.ObjectData.State; 12597 shape.State = addPacket.ObjectData.State;
12598 shape.LastAttachPoint = addPacket.ObjectData.State;
12302 shape.PathBegin = addPacket.ObjectData.PathBegin; 12599 shape.PathBegin = addPacket.ObjectData.PathBegin;
12303 shape.PathEnd = addPacket.ObjectData.PathEnd; 12600 shape.PathEnd = addPacket.ObjectData.PathEnd;
12304 shape.PathScaleX = addPacket.ObjectData.PathScaleX; 12601 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
@@ -12329,7 +12626,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12329 ClientInfo info = m_udpClient.GetClientInfo(); 12626 ClientInfo info = m_udpClient.GetClientInfo();
12330 12627
12331 info.proxyEP = null; 12628 info.proxyEP = null;
12332 info.agentcircuit = RequestClientInfo(); 12629 if (info.agentcircuit == null)
12630 info.agentcircuit = RequestClientInfo();
12333 12631
12334 return info; 12632 return info;
12335 } 12633 }
@@ -12712,11 +13010,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12712 OutPacket(dialog, ThrottleOutPacketType.Task); 13010 OutPacket(dialog, ThrottleOutPacketType.Task);
12713 } 13011 }
12714 13012
12715 public void StopFlying(ISceneEntity p) 13013 public void SendAgentTerseUpdate(ISceneEntity p)
12716 { 13014 {
12717 if (p is ScenePresence) 13015 if (p is ScenePresence)
12718 { 13016 {
12719 ScenePresence presence = p as ScenePresence; 13017// m_log.DebugFormat(
13018// "[LLCLIENTVIEW]: Immediately sending terse agent update for {0} to {1} in {2}",
13019// p.Name, Name, Scene.Name);
13020
12720 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities 13021 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities
12721 // There's no explicit message to send the client to tell it to stop flying.. it relies on the 13022 // There's no explicit message to send the client to tell it to stop flying.. it relies on the
12722 // velocity, collision plane and avatar height 13023 // velocity, collision plane and avatar height
@@ -12724,34 +13025,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12724 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air 13025 // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air
12725 // when the avatar stands up 13026 // when the avatar stands up
12726 13027
12727 Vector3 pos = presence.AbsolutePosition;
12728
12729 if (presence.Appearance.AvatarHeight != 127.0f)
12730 pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f));
12731 else
12732 pos += new Vector3(0f, 0f, (1.56f/6f));
12733
12734 presence.AbsolutePosition = pos;
12735
12736 // attach a suitable collision plane regardless of the actual situation to force the LLClient to land.
12737 // Collision plane below the avatar's position a 6th of the avatar's height is suitable.
12738 // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a
12739 // certain amount.. because the LLClient wouldn't land in that situation anyway.
12740
12741 // why are we still testing for this really old height value default???
12742 if (presence.Appearance.AvatarHeight != 127.0f)
12743 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f);
12744 else
12745 presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f));
12746
12747
12748 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = 13028 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12749 CreateImprovedTerseBlock(p, false); 13029 CreateImprovedTerseBlock(p, false);
12750 13030
12751 const float TIME_DILATION = 1.0f; 13031 const float TIME_DILATION = 1.0f;
12752 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 13032 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12753 13033
12754
12755 ImprovedTerseObjectUpdatePacket packet 13034 ImprovedTerseObjectUpdatePacket packet
12756 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 13035 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12757 PacketType.ImprovedTerseObjectUpdate); 13036 PacketType.ImprovedTerseObjectUpdate);