diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs | 719 |
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); |