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.cs1113
1 files changed, 660 insertions, 453 deletions
diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs
index 5ee1596..849fec3 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
@@ -355,7 +358,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
355// protected HashSet<uint> m_attachmentsSent; 358// protected HashSet<uint> m_attachmentsSent;
356 359
357 private bool m_deliverPackets = true; 360 private bool m_deliverPackets = true;
358 private int m_animationSequenceNumber = 1; 361
359 private bool m_SendLogoutPacketWhenClosing = true; 362 private bool m_SendLogoutPacketWhenClosing = true;
360 363
361 /// <summary> 364 /// <summary>
@@ -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
@@ -416,6 +419,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
416 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } 419 public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } }
417 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); } 420 public bool IsGroupMember(UUID groupID) { return m_groupPowers.ContainsKey(groupID); }
418 421
422 public int PingTimeMS
423 {
424 get
425 {
426 if (UDPClient != null)
427 return UDPClient.PingTimeMS;
428 return 0;
429 }
430 }
431
419 /// <summary> 432 /// <summary>
420 /// Entity update queues 433 /// Entity update queues
421 /// </summary> 434 /// </summary>
@@ -437,7 +450,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
437 public string Name { get { return FirstName + " " + LastName; } } 450 public string Name { get { return FirstName + " " + LastName; } }
438 451
439 public uint CircuitCode { get { return m_circuitCode; } } 452 public uint CircuitCode { get { return m_circuitCode; } }
440 public int NextAnimationSequenceNumber { get { return m_animationSequenceNumber++; } } 453 public int NextAnimationSequenceNumber
454 {
455 get { return m_udpServer.NextAnimationSequenceNumber; }
456 }
441 457
442 /// <summary> 458 /// <summary>
443 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to 459 /// As well as it's function in IClientAPI, in LLClientView we are locking on this property in order to
@@ -458,6 +474,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
458 set { m_disableFacelights = value; } 474 set { m_disableFacelights = value; }
459 } 475 }
460 476
477
461 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } } 478 public bool SendLogoutPacketWhenClosing { set { m_SendLogoutPacketWhenClosing = value; } }
462 479
463 480
@@ -504,6 +521,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
504 m_udpServer = udpServer; 521 m_udpServer = udpServer;
505 m_udpClient = udpClient; 522 m_udpClient = udpClient;
506 m_udpClient.OnQueueEmpty += HandleQueueEmpty; 523 m_udpClient.OnQueueEmpty += HandleQueueEmpty;
524 m_udpClient.HasUpdates += HandleHasUpdates;
507 m_udpClient.OnPacketStats += PopulateStats; 525 m_udpClient.OnPacketStats += PopulateStats;
508 526
509 m_prioritizer = new Prioritizer(m_scene); 527 m_prioritizer = new Prioritizer(m_scene);
@@ -533,7 +551,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 551 // 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 552 // there is some unidentified connection problem, not where we have issues due to deadlock
535 if (!IsActive && !force) 553 if (!IsActive && !force)
554 {
555 m_log.DebugFormat(
556 "[CLIENT]: Not attempting to close inactive client {0} in {1} since force flag is not set",
557 Name, m_scene.Name);
558
536 return; 559 return;
560 }
537 561
538 IsActive = false; 562 IsActive = false;
539 CloseWithoutChecks(sendStop); 563 CloseWithoutChecks(sendStop);
@@ -583,7 +607,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
583 607
584 // Disable UDP handling for this client 608 // Disable UDP handling for this client
585 m_udpClient.Shutdown(); 609 m_udpClient.Shutdown();
586 610
587 611
588 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false)); 612 //m_log.InfoFormat("[CLIENTVIEW] Memory pre GC {0}", System.GC.GetTotalMemory(false));
589 //GC.Collect(); 613 //GC.Collect();
@@ -709,12 +733,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
709 //there is a local handler for this packet type 733 //there is a local handler for this packet type
710 if (pprocessor.Async) 734 if (pprocessor.Async)
711 { 735 {
736 ClientInfo cinfo = UDPClient.GetClientInfo();
737 if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString()))
738 cinfo.AsyncRequests[packet.Type.ToString()] = 0;
739 cinfo.AsyncRequests[packet.Type.ToString()]++;
740
712 object obj = new AsyncPacketProcess(this, pprocessor.method, packet); 741 object obj = new AsyncPacketProcess(this, pprocessor.method, packet);
713 Util.FireAndForget(ProcessSpecificPacketAsync, obj); 742 Util.FireAndForget(ProcessSpecificPacketAsync, obj);
714 result = true; 743 result = true;
715 } 744 }
716 else 745 else
717 { 746 {
747 ClientInfo cinfo = UDPClient.GetClientInfo();
748 if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString()))
749 cinfo.SyncRequests[packet.Type.ToString()] = 0;
750 cinfo.SyncRequests[packet.Type.ToString()]++;
751
718 result = pprocessor.method(this, packet); 752 result = pprocessor.method(this, packet);
719 } 753 }
720 } 754 }
@@ -729,6 +763,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
729 } 763 }
730 if (found) 764 if (found)
731 { 765 {
766 ClientInfo cinfo = UDPClient.GetClientInfo();
767 if (!cinfo.GenericRequests.ContainsKey(packet.Type.ToString()))
768 cinfo.GenericRequests[packet.Type.ToString()] = 0;
769 cinfo.GenericRequests[packet.Type.ToString()]++;
770
732 result = method(this, packet); 771 result = method(this, packet);
733 } 772 }
734 } 773 }
@@ -758,7 +797,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
758 797
759 public virtual void Start() 798 public virtual void Start()
760 { 799 {
761 m_scene.AddNewClient(this, PresenceType.User); 800 m_scene.AddNewAgent(this, PresenceType.User);
762 801
763 RefreshGroupMembership(); 802 RefreshGroupMembership();
764 } 803 }
@@ -820,14 +859,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
820 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType); 859 handshake.RegionInfo3.ProductName = Util.StringToBytes256(regionInfo.RegionType);
821 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes; 860 handshake.RegionInfo3.ProductSKU = Utils.EmptyBytes;
822 861
823 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[0]; 862 handshake.RegionInfo4 = new RegionHandshakePacket.RegionInfo4Block[1];
824// OutPacket(handshake, ThrottleOutPacketType.Task); 863 handshake.RegionInfo4[0] = new RegionHandshakePacket.RegionInfo4Block();
825 // use same as MoveAgentIntoRegion (both should be task ) 864 handshake.RegionInfo4[0].RegionFlagsExtended = args.regionFlags;
865 handshake.RegionInfo4[0].RegionProtocols = 0; // 1 here would indicate that SSB is supported
866
826 OutPacket(handshake, ThrottleOutPacketType.Unknown); 867 OutPacket(handshake, ThrottleOutPacketType.Unknown);
827 } 868 }
828 869
870
829 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) 871 public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look)
830 { 872 {
873 m_thisAgentUpdateArgs.CameraAtAxis.X = float.MinValue;
874 m_thisAgentUpdateArgs.ControlFlags = uint.MaxValue;
875
831 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); 876 AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete);
832 mov.SimData.ChannelVersion = m_channelVersion; 877 mov.SimData.ChannelVersion = m_channelVersion;
833 mov.AgentData.SessionID = m_sessionId; 878 mov.AgentData.SessionID = m_sessionId;
@@ -1210,9 +1255,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1210 LLHeightFieldMoronize(map); 1255 LLHeightFieldMoronize(map);
1211 1256
1212 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches); 1257 LayerDataPacket layerpack = TerrainCompressor.CreateLandPacket(heightmap, patches);
1213 layerpack.Header.Reliable = true; 1258
1259 // When a user edits the terrain, so much data is sent, the data queues up fast and presents a sub optimal editing experience.
1260 // To alleviate this issue, when the user edits the terrain, we start skipping the queues until they're done editing the terrain.
1261 // We also make them unreliable because it's extremely likely that multiple packets will be sent for a terrain patch area
1262 // invalidating previous packets for that area.
1263
1264 // It's possible for an editing user to flood themselves with edited packets but the majority of use cases are such that only a
1265 // tiny percentage of users will be editing the terrain. Other, non-editing users will see the edits much slower.
1266
1267 // 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
1268 // have rezzed already and therefore this is not likely going to cause any additional issues with lost packets, objects or terrain
1269 // patches.
1214 1270
1215 OutPacket(layerpack, ThrottleOutPacketType.Task); 1271 // m_justEditedTerrain is volatile, so test once and duplicate two affected statements so we only have one cache miss.
1272 if (m_justEditedTerrain)
1273 {
1274 layerpack.Header.Reliable = false;
1275 OutPacket(layerpack,
1276 ThrottleOutPacketType.Unknown );
1277 }
1278 else
1279 {
1280 layerpack.Header.Reliable = true;
1281 OutPacket(layerpack,
1282 ThrottleOutPacketType.Task);
1283 }
1216 } 1284 }
1217 catch (Exception e) 1285 catch (Exception e)
1218 { 1286 {
@@ -1405,6 +1473,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1405 1473
1406 mapReply.AgentData.AgentID = AgentId; 1474 mapReply.AgentData.AgentID = AgentId;
1407 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length]; 1475 mapReply.Data = new MapBlockReplyPacket.DataBlock[mapBlocks2.Length];
1476 mapReply.Size = new MapBlockReplyPacket.SizeBlock[mapBlocks2.Length];
1408 mapReply.AgentData.Flags = flag; 1477 mapReply.AgentData.Flags = flag;
1409 1478
1410 for (int i = 0; i < mapBlocks2.Length; i++) 1479 for (int i = 0; i < mapBlocks2.Length; i++)
@@ -1419,6 +1488,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1419 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags; 1488 mapReply.Data[i].RegionFlags = mapBlocks2[i].RegionFlags;
1420 mapReply.Data[i].Access = mapBlocks2[i].Access; 1489 mapReply.Data[i].Access = mapBlocks2[i].Access;
1421 mapReply.Data[i].Agents = mapBlocks2[i].Agents; 1490 mapReply.Data[i].Agents = mapBlocks2[i].Agents;
1491
1492 // TODO: hookup varregion sim size here
1493 mapReply.Size[i] = new MapBlockReplyPacket.SizeBlock();
1494 mapReply.Size[i].SizeX = 256;
1495 mapReply.Size[i].SizeY = 256;
1422 } 1496 }
1423 OutPacket(mapReply, ThrottleOutPacketType.Land); 1497 OutPacket(mapReply, ThrottleOutPacketType.Land);
1424 } 1498 }
@@ -1578,13 +1652,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1578 pc.PingID.OldestUnacked = 0; 1652 pc.PingID.OldestUnacked = 0;
1579 1653
1580 OutPacket(pc, ThrottleOutPacketType.Unknown); 1654 OutPacket(pc, ThrottleOutPacketType.Unknown);
1655 UDPClient.m_lastStartpingTimeMS = Util.EnvironmentTickCount();
1581 } 1656 }
1582 1657
1583 public void SendKillObject(ulong regionHandle, List<uint> localIDs) 1658 public void SendKillObject(List<uint> localIDs)
1584 { 1659 {
1585// foreach (uint id in localIDs) 1660// foreach (uint id in localIDs)
1586// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle); 1661// m_log.DebugFormat("[CLIENT]: Sending KillObjectPacket to {0} for {1} in {2}", Name, id, regionHandle);
1587 1662
1663 // remove pending entities
1664 lock (m_entityProps.SyncRoot)
1665 m_entityProps.Remove(localIDs);
1666 lock (m_entityUpdates.SyncRoot)
1667 m_entityUpdates.Remove(localIDs);
1668
1588 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject); 1669 KillObjectPacket kill = (KillObjectPacket)PacketPool.Instance.GetPacket(PacketType.KillObject);
1589 // TODO: don't create new blocks if recycling an old packet 1670 // TODO: don't create new blocks if recycling an old packet
1590 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count]; 1671 kill.ObjectData = new KillObjectPacket.ObjectDataBlock[localIDs.Count];
@@ -1596,28 +1677,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1596 kill.Header.Reliable = true; 1677 kill.Header.Reliable = true;
1597 kill.Header.Zerocoded = true; 1678 kill.Header.Zerocoded = true;
1598 1679
1599 if (localIDs.Count == 1 && m_scene.GetScenePresence(localIDs[0]) != null) 1680 OutPacket(kill, ThrottleOutPacketType.Task);
1600 { 1681 }
1601 OutPacket(kill, ThrottleOutPacketType.Task);
1602 }
1603 else
1604 {
1605 // We MUST lock for both manipulating the kill record and sending the packet, in order to avoid a race
1606 // condition where a kill can be processed before an out-of-date update for the same object.
1607 // ProcessEntityUpdates() also takes the m_killRecord lock.
1608// lock (m_killRecord)
1609// {
1610// foreach (uint localID in localIDs)
1611// m_killRecord.Add(localID);
1612
1613 // The throttle queue used here must match that being used for updates. Otherwise, there is a
1614 // chance that a kill packet put on a separate queue will be sent to the client before an existing
1615 // update packet on another queue. Receiving updates after kills results in unowned and undeletable
1616 // scene objects in a viewer until that viewer is relogged in.
1617 OutPacket(kill, ThrottleOutPacketType.Task);
1618// }
1619 }
1620 }
1621 1682
1622 /// <summary> 1683 /// <summary>
1623 /// Send information about the items contained in a folder to the client. 1684 /// Send information about the items contained in a folder to the client.
@@ -2594,11 +2655,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2594 { 2655 {
2595 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket(); 2656 AvatarSitResponsePacket avatarSitResponse = new AvatarSitResponsePacket();
2596 avatarSitResponse.SitObject.ID = TargetID; 2657 avatarSitResponse.SitObject.ID = TargetID;
2597 if (CameraAtOffset != Vector3.Zero) 2658 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2598 { 2659 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2599 avatarSitResponse.SitTransform.CameraAtOffset = CameraAtOffset;
2600 avatarSitResponse.SitTransform.CameraEyeOffset = CameraEyeOffset;
2601 }
2602 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook; 2660 avatarSitResponse.SitTransform.ForceMouselook = ForceMouseLook;
2603 avatarSitResponse.SitTransform.AutoPilot = autopilot; 2661 avatarSitResponse.SitTransform.AutoPilot = autopilot;
2604 avatarSitResponse.SitTransform.SitPosition = OffsetPos; 2662 avatarSitResponse.SitTransform.SitPosition = OffsetPos;
@@ -3630,8 +3688,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3630 avp.Sender.IsTrial = false; 3688 avp.Sender.IsTrial = false;
3631 avp.Sender.ID = agentID; 3689 avp.Sender.ID = agentID;
3632 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0]; 3690 avp.AppearanceData = new AvatarAppearancePacket.AppearanceDataBlock[0];
3691
3692 // this need be use in future
3693 // avp.AppearanceData[0].AppearanceVersion = 0;
3694 // avp.AppearanceData[0].CofVersion = 0;
3695
3633 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString()); 3696 //m_log.DebugFormat("[CLIENT]: Sending appearance for {0} to {1}", agentID.ToString(), AgentId.ToString());
3634 OutPacket(avp, ThrottleOutPacketType.Task); 3697 OutPacket(avp, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3635 } 3698 }
3636 3699
3637 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3700 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3659,7 +3722,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3659 ani.AnimationSourceList[i].ObjectID = objectIDs[i]; 3722 ani.AnimationSourceList[i].ObjectID = objectIDs[i];
3660 } 3723 }
3661 ani.Header.Reliable = false; 3724 ani.Header.Reliable = false;
3662 OutPacket(ani, ThrottleOutPacketType.Task); 3725 OutPacket(ani, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3663 } 3726 }
3664 3727
3665 #endregion 3728 #endregion
@@ -3688,7 +3751,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3688 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3751 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3689 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); 3752 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence);
3690 3753
3691 OutPacket(objupdate, ThrottleOutPacketType.Task); 3754 OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority);
3692 3755
3693 // We need to record the avatar local id since the root prim of an attachment points to this. 3756 // We need to record the avatar local id since the root prim of an attachment points to this.
3694// m_attachmentsSent.Add(avatar.LocalId); 3757// m_attachmentsSent.Add(avatar.LocalId);
@@ -3751,8 +3814,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3751 { 3814 {
3752 SceneObjectPart e = (SceneObjectPart)entity; 3815 SceneObjectPart e = (SceneObjectPart)entity;
3753 SceneObjectGroup g = e.ParentGroup; 3816 SceneObjectGroup g = e.ParentGroup;
3754 if (g.RootPart.Shape.State > 30) // HUD 3817 if (g.HasPrivateAttachmentPoint && g.OwnerID != AgentId)
3755 if (g.OwnerID != AgentId)
3756 return; // Don't send updates for other people's HUDs 3818 return; // Don't send updates for other people's HUDs
3757 } 3819 }
3758 3820
@@ -3762,6 +3824,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3762 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation)); 3824 m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags, m_scene.TimeDilation));
3763 } 3825 }
3764 3826
3827
3765 /// <summary> 3828 /// <summary>
3766 /// Requeue an EntityUpdate when it was not acknowledged by the client. 3829 /// Requeue an EntityUpdate when it was not acknowledged by the client.
3767 /// We will update the priority and put it in the correct queue, merging update flags 3830 /// We will update the priority and put it in the correct queue, merging update flags
@@ -3769,8 +3832,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3769 /// The original update time is used for the merged update. 3832 /// The original update time is used for the merged update.
3770 /// </summary> 3833 /// </summary>
3771 private void ResendPrimUpdate(EntityUpdate update) 3834 private void ResendPrimUpdate(EntityUpdate update)
3772 { 3835 {
3773 // If the update exists in priority queue, it will be updated. 3836 // If the update exists in priority queue, it will be updated.
3774 // If it does not exist then it will be added with the current (rather than its original) priority 3837 // If it does not exist then it will be added with the current (rather than its original) priority
3775 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity); 3838 uint priority = m_prioritizer.GetUpdatePriority(this, update.Entity);
3776 3839
@@ -3796,10 +3859,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3796 // Count this as a resent packet since we are going to requeue all of the updates contained in it 3859 // 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); 3860 Interlocked.Increment(ref m_udpClient.PacketsResent);
3798 3861
3862 // We're not going to worry about interlock yet since its not currently critical that this total count
3863 // is 100% correct
3864 m_udpServer.PacketsResentCount++;
3865
3799 foreach (EntityUpdate update in updates) 3866 foreach (EntityUpdate update in updates)
3800 ResendPrimUpdate(update); 3867 ResendPrimUpdate(update);
3801 } 3868 }
3802 3869
3803 private void ProcessEntityUpdates(int maxUpdates) 3870 private void ProcessEntityUpdates(int maxUpdates)
3804 { 3871 {
3805 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); 3872 OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new OpenSim.Framework.Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>();
@@ -3841,13 +3908,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3841 { 3908 {
3842 SceneObjectPart part = (SceneObjectPart)update.Entity; 3909 SceneObjectPart part = (SceneObjectPart)update.Entity;
3843 3910
3844 if (part.ParentGroup.IsDeleted) 3911 if (part.ParentGroup.IsDeleted || part.ParentGroup.inTransit)
3845 continue; 3912 continue;
3846 3913
3847 if (part.ParentGroup.IsAttachment) 3914 if (part.ParentGroup.IsAttachment)
3848 { // Someone else's HUD, why are we getting these? 3915 { // Someone else's HUD, why are we getting these?
3849 if (part.ParentGroup.OwnerID != AgentId && 3916 if (part.ParentGroup.OwnerID != AgentId && part.ParentGroup.HasPrivateAttachmentPoint)
3850 part.ParentGroup.RootPart.Shape.State > 30)
3851 continue; 3917 continue;
3852 ScenePresence sp; 3918 ScenePresence sp;
3853 // Owner is not in the sim, don't update it to 3919 // Owner is not in the sim, don't update it to
@@ -3879,36 +3945,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3879 if (sp.IsChildAgent) 3945 if (sp.IsChildAgent)
3880 continue; 3946 continue;
3881 3947
3882 // If the object is an attachment we don't want it to be in the kill
3883 // record. Else attaching from inworld and subsequently dropping
3884 // it will no longer work.
3885// lock (m_killRecord)
3886// {
3887// m_killRecord.Remove(part.LocalId);
3888// m_killRecord.Remove(part.ParentGroup.RootPart.LocalId);
3889// }
3890 }
3891 else
3892 {
3893 // Please do not remove this unless you can demonstrate on the OpenSim mailing list that a client
3894 // will never receive an update after a prim kill. Even then, keeping the kill record may be a good
3895 // safety measure.
3896 //
3897 // If a Linden Lab 1.23.5 client (and possibly later and earlier) receives an object update
3898 // after a kill, it will keep displaying the deleted object until relog. OpenSim currently performs
3899 // updates and kills on different threads with different scheduling strategies, hence this protection.
3900 //
3901 // This doesn't appear to apply to child prims - a client will happily ignore these updates
3902 // after the root prim has been deleted.
3903 //
3904 // We ignore this for attachments because attaching something from inworld breaks unless we do.
3905// lock (m_killRecord)
3906// {
3907// if (m_killRecord.Contains(part.LocalId))
3908// continue;
3909// if (m_killRecord.Contains(part.ParentGroup.RootPart.LocalId))
3910// continue;
3911// }
3912 } 3948 }
3913 3949
3914 if (part.ParentGroup.IsAttachment && m_disableFacelights) 3950 if (part.ParentGroup.IsAttachment && m_disableFacelights)
@@ -3939,7 +3975,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3939 else if (update.Entity is ScenePresence) 3975 else if (update.Entity is ScenePresence)
3940 { 3976 {
3941 ScenePresence presence = (ScenePresence)update.Entity; 3977 ScenePresence presence = (ScenePresence)update.Entity;
3942 3978 if (presence.IsDeleted)
3979 continue;
3943 // If ParentUUID is not UUID.Zero and ParentID is 0, this 3980 // If ParentUUID is not UUID.Zero and ParentID is 0, this
3944 // avatar is in the process of crossing regions while 3981 // avatar is in the process of crossing regions while
3945 // sat on an object. In this state, we don't want any 3982 // sat on an object. In this state, we don't want any
@@ -4022,8 +4059,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4022 } 4059 }
4023 else 4060 else
4024 { 4061 {
4025 if (update.Entity is ScenePresence && ((ScenePresence)update.Entity).UUID == AgentId) 4062 if (update.Entity is ScenePresence)
4026 // Self updates go into a special list 4063 // ALL presence updates go into a special list
4027 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); 4064 terseAgentUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
4028 else 4065 else
4029 // Everything else goes here 4066 // Everything else goes here
@@ -4035,7 +4072,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4035 4072
4036 #region Packet Sending 4073 #region Packet Sending
4037 4074
4038 const float TIME_DILATION = 1.0f; 4075// const float TIME_DILATION = 1.0f;
4039 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f); 4076 ushort timeDilation = Utils.FloatToUInt16(avgTimeDilation, 0.0f, 1.0f);
4040 4077
4041 if (terseAgentUpdateBlocks.IsValueCreated) 4078 if (terseAgentUpdateBlocks.IsValueCreated)
@@ -4051,7 +4088,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4051 for (int i = 0; i < blocks.Count; i++) 4088 for (int i = 0; i < blocks.Count; i++)
4052 packet.ObjectData[i] = blocks[i]; 4089 packet.ObjectData[i] = blocks[i];
4053 4090
4054 OutPacket(packet, ThrottleOutPacketType.Unknown, true); 4091 OutPacket(packet, ThrottleOutPacketType.Unknown, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4055 } 4092 }
4056 4093
4057 if (objectUpdateBlocks.IsValueCreated) 4094 if (objectUpdateBlocks.IsValueCreated)
@@ -4097,13 +4134,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4097 4134
4098 for (int i = 0; i < blocks.Count; i++) 4135 for (int i = 0; i < blocks.Count; i++)
4099 packet.ObjectData[i] = blocks[i]; 4136 packet.ObjectData[i] = blocks[i];
4100 4137
4101 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); 4138 OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); });
4102 } 4139 }
4103 4140
4104 #endregion Packet Sending 4141 #endregion Packet Sending
4105 } 4142 }
4106 4143
4144 // hack.. dont use
4145 public void SendPartFullUpdate(ISceneEntity ent, uint? parentID)
4146 {
4147 if (ent is SceneObjectPart)
4148 {
4149 SceneObjectPart part = (SceneObjectPart)ent;
4150 ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
4151 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
4152 packet.RegionData.TimeDilation = 1;
4153 packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
4154
4155 ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, this.m_agentId);
4156 if (parentID.HasValue)
4157 {
4158 blk.ParentID = parentID.Value;
4159 }
4160
4161 packet.ObjectData[0] = blk;
4162
4163 OutPacket(packet, ThrottleOutPacketType.Task, true);
4164 }
4165 }
4166
4107 public void ReprioritizeUpdates() 4167 public void ReprioritizeUpdates()
4108 { 4168 {
4109 lock (m_entityUpdates.SyncRoot) 4169 lock (m_entityUpdates.SyncRoot)
@@ -4140,8 +4200,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4140 4200
4141 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) 4201 void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories)
4142 { 4202 {
4203// if (!m_udpServer.IsRunningOutbound)
4204// return;
4205
4143 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) 4206 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4144 { 4207 {
4208// if (!m_udpServer.IsRunningOutbound)
4209// return;
4210
4145 if (m_maxUpdates == 0 || m_LastQueueFill == 0) 4211 if (m_maxUpdates == 0 || m_LastQueueFill == 0)
4146 { 4212 {
4147 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback; 4213 m_maxUpdates = m_udpServer.PrimUpdatesPerCallback;
@@ -4167,6 +4233,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4167 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); 4233 ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit);
4168 } 4234 }
4169 4235
4236 internal bool HandleHasUpdates(ThrottleOutPacketTypeFlags categories)
4237 {
4238 bool hasUpdates = false;
4239
4240 if ((categories & ThrottleOutPacketTypeFlags.Task) != 0)
4241 {
4242 if (m_entityUpdates.Count > 0)
4243 hasUpdates = true;
4244 else if (m_entityProps.Count > 0)
4245 hasUpdates = true;
4246 }
4247
4248 if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0)
4249 {
4250 if (ImageManager.HasUpdates())
4251 hasUpdates = true;
4252 }
4253
4254 return hasUpdates;
4255 }
4256
4170 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 4257 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
4171 { 4258 {
4172 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket(); 4259 AssetUploadCompletePacket newPack = new AssetUploadCompletePacket();
@@ -4312,6 +4399,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 4399 // 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); 4400 Interlocked.Increment(ref m_udpClient.PacketsResent);
4314 4401
4402 // We're not going to worry about interlock yet since its not currently critical that this total count
4403 // is 100% correct
4404 m_udpServer.PacketsResentCount++;
4405
4315 foreach (ObjectPropertyUpdate update in updates) 4406 foreach (ObjectPropertyUpdate update in updates)
4316 ResendPropertyUpdate(update); 4407 ResendPropertyUpdate(update);
4317 } 4408 }
@@ -4499,6 +4590,32 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4499 SceneObjectPart root = sop.ParentGroup.RootPart; 4590 SceneObjectPart root = sop.ParentGroup.RootPart;
4500 4591
4501 block.TouchName = Util.StringToBytes256(root.TouchName); 4592 block.TouchName = Util.StringToBytes256(root.TouchName);
4593
4594 // SL 3.3.4, at least, appears to read this information as a concatenated byte[] stream of UUIDs but
4595 // it's not yet clear whether this is actually used. If this is done in the future then a pre-cached
4596 // copy is really needed since it's less efficient to be constantly recreating this byte array.
4597// using (MemoryStream memStream = new MemoryStream())
4598// {
4599// using (BinaryWriter binWriter = new BinaryWriter(memStream))
4600// {
4601// for (int i = 0; i < sop.GetNumberOfSides(); i++)
4602// {
4603// Primitive.TextureEntryFace teFace = sop.Shape.Textures.FaceTextures[i];
4604//
4605// UUID textureID;
4606//
4607// if (teFace != null)
4608// textureID = teFace.TextureID;
4609// else
4610// textureID = sop.Shape.Textures.DefaultTexture.TextureID;
4611//
4612// binWriter.Write(textureID.GetBytes());
4613// }
4614//
4615// block.TextureID = memStream.ToArray();
4616// }
4617// }
4618
4502 block.TextureID = new byte[0]; // TextureID ??? 4619 block.TextureID = new byte[0]; // TextureID ???
4503 block.SitName = Util.StringToBytes256(root.SitName); 4620 block.SitName = Util.StringToBytes256(root.SitName);
4504 block.OwnerMask = root.OwnerMask; 4621 block.OwnerMask = root.OwnerMask;
@@ -4839,7 +4956,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4839 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>(); 4956 IEventQueue eq = Scene.RequestModuleInterface<IEventQueue>();
4840 if (eq != null) 4957 if (eq != null)
4841 { 4958 {
4842 eq.ParcelProperties(updateMessage, this.AgentId); 4959
4960 OSD message_body = updateMessage.Serialize();
4961 // Add new fields here until OMV has them
4962 OSDMap bodyMap = (OSDMap)message_body;
4963 OSDArray parcelDataArray = (OSDArray)bodyMap["ParcelData"];
4964 OSDMap parcelData = (OSDMap)parcelDataArray[0];
4965 parcelData["SeeAVs"] = OSD.FromBoolean(landData.SeeAVs);
4966 parcelData["AnyAVSounds"] = OSD.FromBoolean(landData.AnyAVSounds);
4967 parcelData["GroupAVSounds"] = OSD.FromBoolean(landData.GroupAVSounds);
4968 OSDMap message = new OSDMap();
4969 message.Add("message", OSD.FromString("ParcelProperties"));
4970 message.Add("body", message_body);
4971
4972 eq.Enqueue (message, this.AgentId);
4973
4974// eq.ParcelProperties(updateMessage, this.AgentId);
4843 } 4975 }
4844 else 4976 else
4845 { 4977 {
@@ -4877,7 +5009,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4877 5009
4878 public void SendForceClientSelectObjects(List<uint> ObjectIDs) 5010 public void SendForceClientSelectObjects(List<uint> ObjectIDs)
4879 { 5011 {
4880 m_log.WarnFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count); 5012// m_log.DebugFormat("[LLCLIENTVIEW] sending select with {0} objects", ObjectIDs.Count);
4881 5013
4882 bool firstCall = true; 5014 bool firstCall = true;
4883 const int MAX_OBJECTS_PER_PACKET = 251; 5015 const int MAX_OBJECTS_PER_PACKET = 251;
@@ -4997,35 +5129,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4997 5129
4998 position = presence.OffsetPosition; 5130 position = presence.OffsetPosition;
4999 rotation = presence.Rotation; 5131 rotation = presence.Rotation;
5000 5132 angularVelocity = presence.AngularVelocity;
5001 if (presence.ParentID != 0) 5133 rotation = presence.Rotation;
5002 {
5003 SceneObjectPart part = m_scene.GetSceneObjectPart(presence.ParentID);
5004 if (part != null && part != part.ParentGroup.RootPart)
5005 {
5006 position = part.OffsetPosition + presence.OffsetPosition * part.RotationOffset;
5007 rotation = part.RotationOffset * presence.Rotation;
5008 }
5009 angularVelocity = Vector3.Zero;
5010 }
5011 else
5012 {
5013 angularVelocity = presence.AngularVelocity;
5014 rotation = presence.Rotation;
5015 }
5016 5134
5017 attachPoint = 0; 5135 attachPoint = 0;
5136// m_log.DebugFormat(
5137// "[LLCLIENTVIEW]: Sending terse update to {0} with position {1} in {2}", Name, presence.OffsetPosition, m_scene.Name);
5138
5139 // attachPoint = presence.State; // Core: commented
5018 collisionPlane = presence.CollisionPlane; 5140 collisionPlane = presence.CollisionPlane;
5019 velocity = presence.Velocity; 5141 velocity = presence.Velocity;
5020 acceleration = Vector3.Zero; 5142 acceleration = Vector3.Zero;
5021 5143
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) 5144 if (sendTexture)
5145 {
5028 textureEntry = presence.Appearance.Texture.GetBytes(); 5146 textureEntry = presence.Appearance.Texture.GetBytes();
5147 }
5029 else 5148 else
5030 textureEntry = null; 5149 textureEntry = null;
5031 } 5150 }
@@ -5034,7 +5153,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5034 SceneObjectPart part = (SceneObjectPart)entity; 5153 SceneObjectPart part = (SceneObjectPart)entity;
5035 5154
5036 attachPoint = part.ParentGroup.AttachmentPoint; 5155 attachPoint = part.ParentGroup.AttachmentPoint;
5037 5156 attachPoint = ((attachPoint % 16) * 16 + (attachPoint / 16));
5038// m_log.DebugFormat( 5157// m_log.DebugFormat(
5039// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}", 5158// "[LLCLIENTVIEW]: Sending attachPoint {0} for {1} {2} to {3}",
5040// attachPoint, part.Name, part.LocalId, Name); 5159// attachPoint, part.Name, part.LocalId, Name);
@@ -5062,7 +5181,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5062 pos += 4; 5181 pos += 4;
5063 5182
5064 // Avatar/CollisionPlane 5183 // Avatar/CollisionPlane
5065 data[pos++] = (byte)((attachPoint % 16) * 16 + (attachPoint / 16)); ; 5184 data[pos++] = (byte) attachPoint;
5066 if (avatar) 5185 if (avatar)
5067 { 5186 {
5068 data[pos++] = 1; 5187 data[pos++] = 1;
@@ -5132,30 +5251,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5132 Vector3 offsetPosition = data.OffsetPosition; 5251 Vector3 offsetPosition = data.OffsetPosition;
5133 Quaternion rotation = data.Rotation; 5252 Quaternion rotation = data.Rotation;
5134 uint parentID = data.ParentID; 5253 uint parentID = data.ParentID;
5135 5254
5136 if (parentID != 0) 5255// m_log.DebugFormat(
5137 { 5256// "[LLCLIENTVIEW]: Sending full update to {0} with position {1} in {2}", Name, data.OffsetPosition, m_scene.Name);
5138 SceneObjectPart part = m_scene.GetSceneObjectPart(parentID);
5139 if (part != null && part != part.ParentGroup.RootPart)
5140 {
5141 offsetPosition = part.OffsetPosition + data.OffsetPosition * part.RotationOffset;
5142 rotation = part.RotationOffset * data.Rotation;
5143 parentID = part.ParentGroup.RootPart.LocalId;
5144 }
5145 }
5146 5257
5147 byte[] objectData = new byte[76]; 5258 byte[] objectData = new byte[76];
5148 5259
5149 data.CollisionPlane.ToBytes(objectData, 0);
5150 offsetPosition.ToBytes(objectData, 16);
5151 Vector3 velocity = new Vector3(0, 0, 0); 5260 Vector3 velocity = new Vector3(0, 0, 0);
5152 Vector3 acceleration = new Vector3(0, 0, 0); 5261 Vector3 acceleration = new Vector3(0, 0, 0);
5262 rotation.Normalize();
5263
5264 data.CollisionPlane.ToBytes(objectData, 0);
5265 offsetPosition.ToBytes(objectData, 16);
5153 velocity.ToBytes(objectData, 28); 5266 velocity.ToBytes(objectData, 28);
5154 acceleration.ToBytes(objectData, 40); 5267 acceleration.ToBytes(objectData, 40);
5155// data.Velocity.ToBytes(objectData, 28);
5156// data.Acceleration.ToBytes(objectData, 40);
5157 rotation.ToBytes(objectData, 52); 5268 rotation.ToBytes(objectData, 52);
5158 //data.AngularVelocity.ToBytes(objectData, 64); 5269 data.AngularVelocity.ToBytes(objectData, 64);
5159 5270
5160 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5271 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
5161 5272
@@ -5168,7 +5279,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5168 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + 5279 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
5169 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); 5280 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
5170 update.ObjectData = objectData; 5281 update.ObjectData = objectData;
5171 update.ParentID = parentID; 5282
5283 SceneObjectPart parentPart = data.ParentPart;
5284 if (parentPart != null)
5285 update.ParentID = parentPart.ParentGroup.LocalId;
5286 else
5287 update.ParentID = 0;
5288
5172 update.PathCurve = 16; 5289 update.PathCurve = 16;
5173 update.PathScaleX = 100; 5290 update.PathScaleX = 100;
5174 update.PathScaleY = 100; 5291 update.PathScaleY = 100;
@@ -5205,15 +5322,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5205 data.RelativePosition.ToBytes(objectData, 0); 5322 data.RelativePosition.ToBytes(objectData, 0);
5206 data.Velocity.ToBytes(objectData, 12); 5323 data.Velocity.ToBytes(objectData, 12);
5207 data.Acceleration.ToBytes(objectData, 24); 5324 data.Acceleration.ToBytes(objectData, 24);
5208 try 5325
5209 { 5326 Quaternion rotation = data.RotationOffset;
5210 data.RotationOffset.ToBytes(objectData, 36); 5327 rotation.Normalize();
5211 } 5328 rotation.ToBytes(objectData, 36);
5212 catch (Exception e)
5213 {
5214 m_log.Warn("[LLClientView]: exception converting quaternion to bytes, using Quaternion.Identity. Exception: " + e.ToString());
5215 OpenMetaverse.Quaternion.Identity.ToBytes(objectData, 36);
5216 }
5217 data.AngularVelocity.ToBytes(objectData, 48); 5329 data.AngularVelocity.ToBytes(objectData, 48);
5218 5330
5219 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 5331 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
@@ -5227,6 +5339,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5227 //update.JointType = 0; 5339 //update.JointType = 0;
5228 update.Material = data.Material; 5340 update.Material = data.Material;
5229 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim 5341 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
5342/*
5230 if (data.ParentGroup.IsAttachment) 5343 if (data.ParentGroup.IsAttachment)
5231 { 5344 {
5232 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID); 5345 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID);
@@ -5240,6 +5353,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5240 // case for attachments may contain conflicting values that can end up crashing the viewer. 5353 // case for attachments may contain conflicting values that can end up crashing the viewer.
5241 update.State = data.ParentGroup.RootPart.Shape.State; 5354 update.State = data.ParentGroup.RootPart.Shape.State;
5242 } 5355 }
5356 */
5357
5358 if (data.ParentGroup.IsAttachment)
5359 {
5360 if (data.IsRoot)
5361 {
5362 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID);
5363 }
5364 else
5365 update.NameValue = Utils.EmptyBytes;
5366
5367 int st = (int)data.ParentGroup.AttachmentPoint;
5368 update.State = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ;
5369 }
5370 else
5371 {
5372 update.NameValue = Utils.EmptyBytes;
5373 update.State = data.Shape.State; // not sure about this
5374 }
5375
5243 5376
5244// m_log.DebugFormat( 5377// m_log.DebugFormat(
5245// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}", 5378// "[LLCLIENTVIEW]: Sending state {0} for {1} {2} to {3}",
@@ -5387,7 +5520,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5387 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject); 5520 AddLocalPacketHandler(PacketType.RezObject, HandlerRezObject);
5388 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject); 5521 AddLocalPacketHandler(PacketType.DeRezObject, HandlerDeRezObject);
5389 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand); 5522 AddLocalPacketHandler(PacketType.ModifyLand, HandlerModifyLand);
5390 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply); 5523 AddLocalPacketHandler(PacketType.RegionHandshakeReply, HandlerRegionHandshakeReply, false);
5391 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest); 5524 AddLocalPacketHandler(PacketType.AgentWearablesRequest, HandlerAgentWearablesRequest);
5392 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance); 5525 AddLocalPacketHandler(PacketType.AgentSetAppearance, HandlerAgentSetAppearance);
5393 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing); 5526 AddLocalPacketHandler(PacketType.AgentIsNowWearing, HandlerAgentIsNowWearing);
@@ -5448,8 +5581,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5448 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false); 5581 AddLocalPacketHandler(PacketType.ScriptAnswerYes, HandleScriptAnswerYes, false);
5449 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false); 5582 AddLocalPacketHandler(PacketType.ObjectClickAction, HandleObjectClickAction, false);
5450 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false); 5583 AddLocalPacketHandler(PacketType.ObjectMaterial, HandleObjectMaterial, false);
5451 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage); 5584 AddLocalPacketHandler(PacketType.RequestImage, HandleRequestImage, false);
5452 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest); 5585 AddLocalPacketHandler(PacketType.TransferRequest, HandleTransferRequest, false);
5453 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest); 5586 AddLocalPacketHandler(PacketType.AssetUploadRequest, HandleAssetUploadRequest);
5454 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer); 5587 AddLocalPacketHandler(PacketType.RequestXfer, HandleRequestXfer);
5455 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket); 5588 AddLocalPacketHandler(PacketType.SendXferPacket, HandleSendXferPacket);
@@ -5481,7 +5614,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5481 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel); 5614 AddLocalPacketHandler(PacketType.TeleportCancel, HandleTeleportCancel);
5482 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest); 5615 AddLocalPacketHandler(PacketType.TeleportLocationRequest, HandleTeleportLocationRequest);
5483 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false); 5616 AddLocalPacketHandler(PacketType.UUIDNameRequest, HandleUUIDNameRequest, false);
5484 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest); 5617 AddLocalPacketHandler(PacketType.RegionHandleRequest, HandleRegionHandleRequest, false);
5485 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest); 5618 AddLocalPacketHandler(PacketType.ParcelInfoRequest, HandleParcelInfoRequest);
5486 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false); 5619 AddLocalPacketHandler(PacketType.ParcelAccessListRequest, HandleParcelAccessListRequest, false);
5487 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false); 5620 AddLocalPacketHandler(PacketType.ParcelAccessListUpdate, HandleParcelAccessListUpdate, false);
@@ -5594,82 +5727,146 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5594 5727
5595 #region Packet Handlers 5728 #region Packet Handlers
5596 5729
5730 public int TotalAgentUpdates { get; set; }
5731
5597 #region Scene/Avatar 5732 #region Scene/Avatar
5598 5733
5599 private bool HandleAgentUpdate(IClientAPI sener, Packet packet) 5734 // Threshold for body rotation to be a significant agent update
5735 // use the abs of cos
5736 private const float QDELTABody = 1.0f - 0.0001f;
5737 private const float QDELTAHead = 1.0f - 0.0001f;
5738 // Threshold for camera rotation to be a significant agent update
5739 private const float VDELTA = 0.01f;
5740
5741 /// <summary>
5742 /// This checks the update significance against the last update made.
5743 /// </summary>
5744 /// <remarks>Can only be called by one thread at a time</remarks>
5745 /// <returns></returns>
5746 /// <param name='x'></param>
5747 public bool CheckAgentUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5600 { 5748 {
5601 if (OnAgentUpdate != null) 5749 return CheckAgentMovementUpdateSignificance(x) || CheckAgentCameraUpdateSignificance(x);
5750 }
5751
5752 /// <summary>
5753 /// This checks the movement/state update significance against the last update made.
5754 /// </summary>
5755 /// <remarks>Can only be called by one thread at a time</remarks>
5756 /// <returns></returns>
5757 /// <param name='x'></param>
5758 private bool CheckAgentMovementUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5759 {
5760 float qdelta1 = Math.Abs(Quaternion.Dot(x.BodyRotation, m_thisAgentUpdateArgs.BodyRotation));
5761 //qdelta2 = Math.Abs(Quaternion.Dot(x.HeadRotation, m_thisAgentUpdateArgs.HeadRotation));
5762
5763 bool movementSignificant =
5764 (x.ControlFlags != m_thisAgentUpdateArgs.ControlFlags) // significant if control flags changed
5765 || (x.ControlFlags != (byte)AgentManager.ControlFlags.NONE) // significant if user supplying any movement update commands
5766 || (x.Flags != m_thisAgentUpdateArgs.Flags) // significant if Flags changed
5767 || (x.State != m_thisAgentUpdateArgs.State) // significant if Stats changed
5768 || (qdelta1 < QDELTABody) // significant if body rotation above(below cos) threshold
5769 // Ignoring head rotation altogether, because it's not being used for anything interesting up the stack
5770 // || (qdelta2 < QDELTAHead) // significant if head rotation above(below cos) threshold
5771 || (Math.Abs(x.Far - m_thisAgentUpdateArgs.Far) >= 32) // significant if far distance changed
5772 ;
5773 //if (movementSignificant)
5774 //{
5775 //m_log.DebugFormat("[LLCLIENTVIEW]: Bod {0} {1}",
5776 // qdelta1, qdelta2);
5777 //m_log.DebugFormat("[LLCLIENTVIEW]: St {0} {1} {2} {3}",
5778 // x.ControlFlags, x.Flags, x.Far, x.State);
5779 //}
5780 return movementSignificant;
5781 }
5782
5783 /// <summary>
5784 /// This checks the camera update significance against the last update made.
5785 /// </summary>
5786 /// <remarks>Can only be called by one thread at a time</remarks>
5787 /// <returns></returns>
5788 /// <param name='x'></param>
5789 private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x)
5790 {
5791 float vdelta1 = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis);
5792 float vdelta2 = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter);
5793 float vdelta3 = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis);
5794 float vdelta4 = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis);
5795
5796 bool cameraSignificant =
5797 (vdelta1 > VDELTA) ||
5798 (vdelta2 > VDELTA) ||
5799 (vdelta3 > VDELTA) ||
5800 (vdelta4 > VDELTA)
5801 ;
5802
5803 //if (cameraSignificant)
5804 //{
5805 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam1 {0} {1}",
5806 // x.CameraAtAxis, x.CameraCenter);
5807 //m_log.DebugFormat("[LLCLIENTVIEW]: Cam2 {0} {1}",
5808 // x.CameraLeftAxis, x.CameraUpAxis);
5809 //}
5810
5811 return cameraSignificant;
5812 }
5813
5814 private bool HandleAgentUpdate(IClientAPI sender, Packet packet)
5815 {
5816 // We got here, which means that something in agent update was significant
5817
5818 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet;
5819 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData;
5820
5821 if (x.AgentID != AgentId || x.SessionID != SessionId)
5602 { 5822 {
5603 AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; 5823 PacketPool.Instance.ReturnPacket(packet);
5824 return false;
5825 }
5604 5826
5605 #region Packet Session and User Check 5827 TotalAgentUpdates++;
5606 if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId)
5607 {
5608 PacketPool.Instance.ReturnPacket(packet);
5609 return false;
5610 }
5611 #endregion
5612 5828
5613 bool update = false; 5829 bool movement = CheckAgentMovementUpdateSignificance(x);
5614 AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; 5830 bool camera = CheckAgentCameraUpdateSignificance(x);
5615
5616 if (m_lastAgentUpdateArgs != null)
5617 {
5618 // These should be ordered from most-likely to
5619 // least likely to change. I've made an initial
5620 // guess at that.
5621 update =
5622 (
5623 (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) ||
5624 (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) ||
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 5831
5644 if (update) 5832 // Was there a significant movement/state change?
5645 { 5833 if (movement)
5646// m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); 5834 {
5835 m_thisAgentUpdateArgs.BodyRotation = x.BodyRotation;
5836 m_thisAgentUpdateArgs.ControlFlags = x.ControlFlags;
5837 m_thisAgentUpdateArgs.Far = x.Far;
5838 m_thisAgentUpdateArgs.Flags = x.Flags;
5839 m_thisAgentUpdateArgs.HeadRotation = x.HeadRotation;
5840// m_thisAgentUpdateArgs.SessionID = x.SessionID;
5841 m_thisAgentUpdateArgs.State = x.State;
5647 5842
5648 m_lastAgentUpdateArgs.AgentID = x.AgentID; 5843 UpdateAgent handlerAgentUpdate = OnAgentUpdate;
5649 m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; 5844 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate;
5650 m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5651 m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter;
5652 m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5653 m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5654 m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags;
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 5845
5661 UpdateAgent handlerAgentUpdate = OnAgentUpdate; 5846 if (handlerPreAgentUpdate != null)
5662 UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; 5847 OnPreAgentUpdate(this, m_thisAgentUpdateArgs);
5663 5848
5664 if (handlerPreAgentUpdate != null) 5849 if (handlerAgentUpdate != null)
5665 OnPreAgentUpdate(this, m_lastAgentUpdateArgs); 5850 OnAgentUpdate(this, m_thisAgentUpdateArgs);
5666 5851
5667 if (handlerAgentUpdate != null) 5852 handlerAgentUpdate = null;
5668 OnAgentUpdate(this, m_lastAgentUpdateArgs); 5853 handlerPreAgentUpdate = null;
5854 }
5669 5855
5670 handlerAgentUpdate = null; 5856 // Was there a significant camera(s) change?
5671 handlerPreAgentUpdate = null; 5857 if (camera)
5672 } 5858 {
5859 m_thisAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis;
5860 m_thisAgentUpdateArgs.CameraCenter = x.CameraCenter;
5861 m_thisAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis;
5862 m_thisAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis;
5863
5864 UpdateAgent handlerAgentCameraUpdate = OnAgentCameraUpdate;
5865
5866 if (handlerAgentCameraUpdate != null)
5867 handlerAgentCameraUpdate(this, m_thisAgentUpdateArgs);
5868
5869 handlerAgentCameraUpdate = null;
5673 } 5870 }
5674 5871
5675 PacketPool.Instance.ReturnPacket(packet); 5872 PacketPool.Instance.ReturnPacket(packet);
@@ -6260,6 +6457,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6260 //m_log.Info("[LAND]: LAND:" + modify.ToString()); 6457 //m_log.Info("[LAND]: LAND:" + modify.ToString());
6261 if (modify.ParcelData.Length > 0) 6458 if (modify.ParcelData.Length > 0)
6262 { 6459 {
6460 // Note: the ModifyTerrain event handler sends out updated packets before the end of this event. Therefore,
6461 // a simple boolean value should work and perhaps queue up just a few terrain patch packets at the end of the edit.
6462 m_justEditedTerrain = true; // Prevent terrain packet (Land layer) from being queued, make it unreliable
6263 if (OnModifyTerrain != null) 6463 if (OnModifyTerrain != null)
6264 { 6464 {
6265 for (int i = 0; i < modify.ParcelData.Length; i++) 6465 for (int i = 0; i < modify.ParcelData.Length; i++)
@@ -6275,6 +6475,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6275 } 6475 }
6276 } 6476 }
6277 } 6477 }
6478 m_justEditedTerrain = false; // Queue terrain packet (Land layer) if necessary, make it reliable again
6278 } 6479 }
6279 6480
6280 return true; 6481 return true;
@@ -6343,7 +6544,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6343 6544
6344 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; 6545 WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length];
6345 for (int i=0; i<appear.WearableData.Length;i++) 6546 for (int i=0; i<appear.WearableData.Length;i++)
6346 cacheitems[i] = new WearableCacheItem(){CacheId = appear.WearableData[i].CacheID,TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)}; 6547 cacheitems[i] = new WearableCacheItem(){
6548 CacheId = appear.WearableData[i].CacheID,
6549 TextureIndex=Convert.ToUInt32(appear.WearableData[i].TextureIndex)
6550 };
6347 6551
6348 6552
6349 6553
@@ -6549,8 +6753,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6549 return true; 6753 return true;
6550 } 6754 }
6551 6755
6552 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack) 6756 private bool HandleCompleteAgentMovement(IClientAPI sender, Packet Pack)
6553 { 6757 {
6758 m_log.DebugFormat("[LLClientView] HandleCompleteAgentMovement");
6759
6554 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion; 6760 Action<IClientAPI, bool> handlerCompleteMovementToRegion = OnCompleteMovementToRegion;
6555 if (handlerCompleteMovementToRegion != null) 6761 if (handlerCompleteMovementToRegion != null)
6556 { 6762 {
@@ -6636,6 +6842,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6636 } 6842 }
6637 #endregion 6843 #endregion
6638 6844
6845 if (SceneAgent.IsChildAgent)
6846 {
6847 SendCantSitBecauseChildAgentResponse();
6848 return true;
6849 }
6850
6639 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit; 6851 AgentRequestSit handlerAgentRequestSit = OnAgentRequestSit;
6640 6852
6641 if (handlerAgentRequestSit != null) 6853 if (handlerAgentRequestSit != null)
@@ -6660,6 +6872,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6660 } 6872 }
6661 #endregion 6873 #endregion
6662 6874
6875 if (SceneAgent.IsChildAgent)
6876 {
6877 SendCantSitBecauseChildAgentResponse();
6878 return true;
6879 }
6880
6663 AgentSit handlerAgentSit = OnAgentSit; 6881 AgentSit handlerAgentSit = OnAgentSit;
6664 if (handlerAgentSit != null) 6882 if (handlerAgentSit != null)
6665 { 6883 {
@@ -6669,6 +6887,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
6669 return true; 6887 return true;
6670 } 6888 }
6671 6889
6890 /// <summary>
6891 /// Used when a child agent gets a sit response which should not be fulfilled.
6892 /// </summary>
6893 private void SendCantSitBecauseChildAgentResponse()
6894 {
6895 SendAlertMessage("Try moving closer. Can't sit on object because it is not in the same region as you.");
6896 }
6897
6672 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack) 6898 private bool HandleSoundTrigger(IClientAPI sender, Packet Pack)
6673 { 6899 {
6674 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack; 6900 SoundTriggerPacket soundTriggerPacket = (SoundTriggerPacket)Pack;
@@ -7879,129 +8105,145 @@ namespace OpenSim.Region.ClientStack.LindenUDP
7879 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request"); 8105 //m_log.Debug("ClientView.ProcessPackets.cs:ProcessInPacket() - Got transfer request");
7880 8106
7881 TransferRequestPacket transfer = (TransferRequestPacket)Pack; 8107 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; 8108 UUID taskID = UUID.Zero;
7887 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) 8109 if (transfer.TransferInfo.SourceType == (int)SourceType.SimInventoryItem)
7888 { 8110 {
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())) 8111 if (!(((Scene)m_scene).Permissions.BypassPermissions()))
7898 { 8112 {
7899 if (taskID != UUID.Zero) // Prim 8113 // We're spawning a thread because the permissions check can block this thread
8114 Util.FireAndForget(delegate
7900 { 8115 {
7901 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID); 8116 // This requests the asset if needed
8117 HandleSimInventoryTransferRequestWithPermsCheck(sender, transfer);
8118 });
8119 return true;
8120 }
8121 }
8122 else if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate)
8123 {
8124 //TransferRequestPacket does not include covenant uuid?
8125 //get scene covenant uuid
8126 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
8127 }
7902 8128
7903 if (part == null) 8129 // This is non-blocking
7904 { 8130 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 8131
7911 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID); 8132 return true;
7912 if (tii == null) 8133 }
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 8134
7920 if (tii.Type == (int)AssetType.LSLText) 8135 private void HandleSimInventoryTransferRequestWithPermsCheck(IClientAPI sender, TransferRequestPacket transfer)
7921 { 8136 {
7922 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId)) 8137 UUID taskID = new UUID(transfer.TransferInfo.Params, 48);
7923 return true; 8138 UUID itemID = new UUID(transfer.TransferInfo.Params, 64);
7924 } 8139 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 8140
7942 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) 8141 //m_log.DebugFormat(
7943 { 8142 // "[CLIENT]: Got request for asset {0} from item {1} in prim {2} by {3}",
7944 m_log.WarnFormat( 8143 // 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 8144
7950 if (tii.OwnerID != AgentId) 8145 //m_log.Debug("Transfer Request: " + transfer.ToString());
7951 { 8146 // Validate inventory transfers
7952 m_log.WarnFormat( 8147 // 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}", 8148 //
7954 Name, requestID, itemID, taskID, tii.OwnerID); 8149 if (taskID != UUID.Zero) // Prim
7955 return true; 8150 {
7956 } 8151 SceneObjectPart part = ((Scene)m_scene).GetSceneObjectPart(taskID);
7957 8152
7958 if (( 8153 if (part == null)
7959 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8154 {
7960 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) 8155 m_log.WarnFormat(
7961 { 8156 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but prim does not exist",
7962 m_log.WarnFormat( 8157 Name, requestID, itemID, taskID);
7963 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer", 8158 return;
7964 Name, requestID, itemID, taskID); 8159 }
7965 return true;
7966 }
7967 8160
7968 if (tii.AssetID != requestID) 8161 TaskInventoryItem tii = part.Inventory.GetInventoryItem(itemID);
7969 { 8162 if (tii == null)
7970 m_log.WarnFormat( 8163 {
7971 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}", 8164 m_log.WarnFormat(
7972 Name, requestID, itemID, taskID, tii.AssetID); 8165 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item does not exist",
7973 return true; 8166 Name, requestID, itemID, taskID);
7974 } 8167 return;
7975 } 8168 }
8169
8170 if (tii.Type == (int)AssetType.LSLText)
8171 {
8172 if (!((Scene)m_scene).Permissions.CanEditScript(itemID, taskID, AgentId))
8173 return;
8174 }
8175 else if (tii.Type == (int)AssetType.Notecard)
8176 {
8177 if (!((Scene)m_scene).Permissions.CanEditNotecard(itemID, taskID, AgentId))
8178 return;
8179 }
8180 else
8181 {
8182 // TODO: Change this code to allow items other than notecards and scripts to be successfully
8183 // shared with group. In fact, this whole block of permissions checking should move to an IPermissionsModule
8184 if (part.OwnerID != AgentId)
8185 {
8186 m_log.WarnFormat(
8187 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the prim is owned by {4}",
8188 Name, requestID, itemID, taskID, part.OwnerID);
8189 return;
7976 } 8190 }
7977 else // Agent 8191
8192 if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0)
7978 { 8193 {
7979 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 8194 m_log.WarnFormat(
7980 if (invAccess != null) 8195 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but modify permissions are not set",
7981 { 8196 Name, requestID, itemID, taskID);
7982 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID)) 8197 return;
7983 return false; 8198 }
7984 } 8199
7985 else 8200 if (tii.OwnerID != AgentId)
7986 { 8201 {
7987 return false; 8202 m_log.WarnFormat(
7988 } 8203 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but the item is owned by {4}",
8204 Name, requestID, itemID, taskID, tii.OwnerID);
8205 return;
8206 }
8207
8208 if ((
8209 tii.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8210 != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer))
8211 {
8212 m_log.WarnFormat(
8213 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but item permissions are not modify/copy/transfer",
8214 Name, requestID, itemID, taskID);
8215 return;
8216 }
8217
8218 if (tii.AssetID != requestID)
8219 {
8220 m_log.WarnFormat(
8221 "[CLIENT]: {0} requested asset {1} from item {2} in prim {3} but this does not match item's asset {4}",
8222 Name, requestID, itemID, taskID, tii.AssetID);
8223 return;
7989 } 8224 }
7990 } 8225 }
7991 } 8226 }
7992 else 8227 else // Agent
7993 if (transfer.TransferInfo.SourceType == (int)SourceType.SimEstate) 8228 {
8229 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
8230 if (invAccess != null)
8231 {
8232 if (!invAccess.CanGetAgentInventoryItem(this, itemID, requestID))
8233 return;
8234 }
8235 else
7994 { 8236 {
7995 //TransferRequestPacket does not include covenant uuid? 8237 return;
7996 //get scene covenant uuid
7997 taskID = m_scene.RegionInfo.RegionSettings.Covenant;
7998 } 8238 }
8239 }
7999 8240
8241 // Permissions out of the way, let's request the asset
8000 MakeAssetRequest(transfer, taskID); 8242 MakeAssetRequest(transfer, taskID);
8001 8243
8002 return true;
8003 } 8244 }
8004 8245
8246
8005 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack) 8247 private bool HandleAssetUploadRequest(IClientAPI sender, Packet Pack)
8006 { 8248 {
8007 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack; 8249 AssetUploadRequestPacket request = (AssetUploadRequestPacket)Pack;
@@ -11732,8 +11974,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11732 } 11974 }
11733 11975
11734 /// <summary> 11976 /// <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> 11977 /// </summary>
11738 /// <remarks> 11978 /// <remarks>
11739 /// At the moment, we always reply that there is no cached texture. 11979 /// At the moment, we always reply that there is no cached texture.
@@ -11741,6 +11981,35 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11741 /// <param name="simclient"></param> 11981 /// <param name="simclient"></param>
11742 /// <param name="packet"></param> 11982 /// <param name="packet"></param>
11743 /// <returns></returns> 11983 /// <returns></returns>
11984 // TODO: Convert old handler to use new method
11985 /*protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11986 {
11987 AgentCachedTexturePacket cachedtex = (AgentCachedTexturePacket)packet;
11988
11989 if (cachedtex.AgentData.SessionID != SessionId)
11990 return false;
11991
11992
11993 List<CachedTextureRequestArg> requestArgs = new List<CachedTextureRequestArg>();
11994
11995 for (int i = 0; i < cachedtex.WearableData.Length; i++)
11996 {
11997 CachedTextureRequestArg arg = new CachedTextureRequestArg();
11998 arg.BakedTextureIndex = cachedtex.WearableData[i].TextureIndex;
11999 arg.WearableHashID = cachedtex.WearableData[i].ID;
12000
12001 requestArgs.Add(arg);
12002 }
12003
12004 CachedTextureRequest handlerCachedTextureRequest = OnCachedTextureRequest;
12005 if (handlerCachedTextureRequest != null)
12006 {
12007 handlerCachedTextureRequest(simclient,cachedtex.AgentData.SerialNum,requestArgs);
12008 }
12009
12010 return true;
12011 }*/
12012
11744 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet) 12013 protected bool HandleAgentTextureCached(IClientAPI simclient, Packet packet)
11745 { 12014 {
11746 //m_log.Debug("texture cached: " + packet.ToString()); 12015 //m_log.Debug("texture cached: " + packet.ToString());
@@ -11749,156 +12018,105 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11749 12018
11750 if (cachedtex.AgentData.SessionID != SessionId) 12019 if (cachedtex.AgentData.SessionID != SessionId)
11751 return false; 12020 return false;
11752
11753 12021
11754 // TODO: don't create new blocks if recycling an old packet 12022 // TODO: don't create new blocks if recycling an old packet
11755 cachedresp.AgentData.AgentID = AgentId; 12023 cachedresp.AgentData.AgentID = AgentId;
11756 cachedresp.AgentData.SessionID = m_sessionId; 12024 cachedresp.AgentData.SessionID = m_sessionId;
11757 cachedresp.AgentData.SerialNum = m_cachedTextureSerial; 12025 cachedresp.AgentData.SerialNum = cachedtex.AgentData.SerialNum;
11758 m_cachedTextureSerial++;
11759 cachedresp.WearableData = 12026 cachedresp.WearableData =
11760 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length]; 12027 new AgentCachedTextureResponsePacket.WearableDataBlock[cachedtex.WearableData.Length];
11761 12028
11762 //IAvatarFactoryModule fac = m_scene.RequestModuleInterface<IAvatarFactoryModule>();
11763 // var item = fac.GetBakedTextureFaces(AgentId);
11764 //WearableCacheItem[] items = fac.GetCachedItems(AgentId);
11765
11766 IAssetService cache = m_scene.AssetService;
11767 IBakedTextureModule bakedTextureModule = m_scene.RequestModuleInterface<IBakedTextureModule>();
11768 //bakedTextureModule = null;
11769 int maxWearablesLoop = cachedtex.WearableData.Length; 12029 int maxWearablesLoop = cachedtex.WearableData.Length;
11770 if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES) 12030 if (maxWearablesLoop > AvatarWearable.MAX_WEARABLES)
11771 maxWearablesLoop = AvatarWearable.MAX_WEARABLES; 12031 maxWearablesLoop = AvatarWearable.MAX_WEARABLES;
11772 12032
11773 if (bakedTextureModule != null && cache != null) 12033 int cacheHits = 0;
11774 {
11775 // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
11776 12034
11777 WearableCacheItem[] cacheItems = null; 12035 // We need to make sure the asset stored in the bake is available on this server also by it's assetid before we map it to a Cacheid
11778 ScenePresence p = m_scene.GetScenePresence(AgentId);
11779 if (p.Appearance != null)
11780 if (p.Appearance.WearableCacheItems == null || p.Appearance.WearableCacheItemsDirty)
11781 {
11782 try
11783 {
11784 cacheItems = bakedTextureModule.Get(AgentId);
11785 p.Appearance.WearableCacheItems = cacheItems;
11786 p.Appearance.WearableCacheItemsDirty = false;
11787 }
11788 12036
11789 /* 12037 WearableCacheItem[] cacheItems = null;
11790 * The following Catch types DO NOT WORK, it jumps to the General Packet Exception Handler if you don't catch Exception!
11791 *
11792 catch (System.Net.Sockets.SocketException)
11793 {
11794 cacheItems = null;
11795 }
11796 catch (WebException)
11797 {
11798 cacheItems = null;
11799 }
11800 catch (InvalidOperationException)
11801 {
11802 cacheItems = null;
11803 } */
11804 catch (Exception)
11805 {
11806 cacheItems = null;
11807 }
11808
11809 }
11810 else if (p.Appearance.WearableCacheItems != null)
11811 {
11812 cacheItems = p.Appearance.WearableCacheItems;
11813 }
11814 12038
11815 if (cache != null && cacheItems != null) 12039 ScenePresence p = m_scene.GetScenePresence(AgentId);
11816 {
11817 foreach (WearableCacheItem item in cacheItems)
11818 {
11819
11820 if (cache.GetCached(item.TextureID.ToString()) == null)
11821 {
11822 item.TextureAsset.Temporary = true;
11823 cache.Store(item.TextureAsset);
11824 }
11825 12040
12041 if (p != null && p.Appearance != null)
12042 {
12043 cacheItems = p.Appearance.WearableCacheItems;
12044 }
11826 12045
11827 } 12046 if (cacheItems != null)
11828 } 12047 {
11829 12048 for (int i = 0; i < maxWearablesLoop; i++)
11830 if (cacheItems != null)
11831 { 12049 {
11832 12050 int idx = cachedtex.WearableData[i].TextureIndex;
11833 for (int i = 0; i < maxWearablesLoop; i++)
11834 {
11835 WearableCacheItem item =
11836 WearableCacheItem.SearchTextureIndex(cachedtex.WearableData[i].TextureIndex,cacheItems);
11837 12051
11838 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12052 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11839 cachedresp.WearableData[i].TextureIndex= cachedtex.WearableData[i].TextureIndex; 12053 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11840 cachedresp.WearableData[i].HostName = new byte[0]; 12054 cachedresp.WearableData[i].HostName = new byte[0];
11841 if (item != null && cachedtex.WearableData[i].ID == item.CacheId) 12055 if (cachedtex.WearableData[i].ID == cacheItems[idx].CacheId)
11842 { 12056 {
11843 12057 cachedresp.WearableData[i].TextureID = cacheItems[idx].TextureID;
11844 cachedresp.WearableData[i].TextureID = item.TextureID; 12058 cacheHits++;
11845 }
11846 else
11847 {
11848 cachedresp.WearableData[i].TextureID = UUID.Zero;
11849 }
11850 } 12059 }
11851 } 12060 else
11852 else
11853 {
11854 for (int i = 0; i < maxWearablesLoop; i++)
11855 { 12061 {
11856 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11857 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11858 cachedresp.WearableData[i].TextureID = UUID.Zero; 12062 cachedresp.WearableData[i].TextureID = UUID.Zero;
11859 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11860 cachedresp.WearableData[i].HostName = new byte[0];
11861 } 12063 }
11862 } 12064 }
11863 } 12065 }
11864 else 12066 else
11865 { 12067 {
11866 if (cache == null) 12068 for (int i = 0; i < maxWearablesLoop; i++)
11867 { 12069 {
11868 for (int i = 0; i < maxWearablesLoop; i++) 12070 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11869 { 12071 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11870 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock(); 12072 cachedresp.WearableData[i].TextureID = UUID.Zero;
11871 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex; 12073 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11872 cachedresp.WearableData[i].TextureID = UUID.Zero; 12074 cachedresp.WearableData[i].HostName = new byte[0];
11873 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11874 cachedresp.WearableData[i].HostName = new byte[0];
11875 }
11876 } 12075 }
11877 else 12076 }
11878 {
11879 for (int i = 0; i < maxWearablesLoop; i++)
11880 {
11881 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
11882 cachedresp.WearableData[i].TextureIndex = cachedtex.WearableData[i].TextureIndex;
11883
11884 12077
12078 m_log.DebugFormat("texture cached: hits {0}", cacheHits);
11885 12079
11886 if (cache.GetCached(cachedresp.WearableData[i].TextureID.ToString()) == null)
11887 cachedresp.WearableData[i].TextureID = UUID.Zero;
11888 //UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11889 else
11890 cachedresp.WearableData[i].TextureID = UUID.Zero;
11891 // UUID.Parse("8334fb6e-c2f5-46ee-807d-a435f61a8d46");
11892 cachedresp.WearableData[i].HostName = new byte[0];
11893 }
11894 }
11895 }
11896 cachedresp.Header.Zerocoded = true; 12080 cachedresp.Header.Zerocoded = true;
11897 OutPacket(cachedresp, ThrottleOutPacketType.Task); 12081 OutPacket(cachedresp, ThrottleOutPacketType.Task);
11898 12082
11899 return true; 12083 return true;
11900 } 12084 }
11901 12085
12086 /// <summary>
12087 /// Send a response back to a client when it asks the asset server (via the region server) if it has
12088 /// its appearance texture cached.
12089 /// </summary>
12090 /// <param name="avatar"></param>
12091 /// <param name="serial"></param>
12092 /// <param name="cachedTextures"></param>
12093 /// <returns></returns>
12094 public void SendCachedTextureResponse(ISceneEntity avatar, int serial, List<CachedTextureResponseArg> cachedTextures)
12095 {
12096 ScenePresence presence = avatar as ScenePresence;
12097 if (presence == null)
12098 return;
12099
12100 AgentCachedTextureResponsePacket cachedresp = (AgentCachedTextureResponsePacket)PacketPool.Instance.GetPacket(PacketType.AgentCachedTextureResponse);
12101
12102 // TODO: don't create new blocks if recycling an old packet
12103 cachedresp.AgentData.AgentID = m_agentId;
12104 cachedresp.AgentData.SessionID = m_sessionId;
12105 cachedresp.AgentData.SerialNum = serial;
12106 cachedresp.WearableData = new AgentCachedTextureResponsePacket.WearableDataBlock[cachedTextures.Count];
12107
12108 for (int i = 0; i < cachedTextures.Count; i++)
12109 {
12110 cachedresp.WearableData[i] = new AgentCachedTextureResponsePacket.WearableDataBlock();
12111 cachedresp.WearableData[i].TextureIndex = (byte)cachedTextures[i].BakedTextureIndex;
12112 cachedresp.WearableData[i].TextureID = cachedTextures[i].BakedTextureID;
12113 cachedresp.WearableData[i].HostName = new byte[0];
12114 }
12115
12116 cachedresp.Header.Zerocoded = true;
12117 OutPacket(cachedresp, ThrottleOutPacketType.Task);
12118 }
12119
11902 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet) 12120 protected bool HandleMultipleObjUpdate(IClientAPI simClient, Packet packet)
11903 { 12121 {
11904 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet; 12122 MultipleObjectUpdatePacket multipleupdate = (MultipleObjectUpdatePacket)packet;
@@ -11924,8 +12142,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11924 if (part == null) 12142 if (part == null)
11925 { 12143 {
11926 // It's a ghost! tell the client to delete it from view. 12144 // It's a ghost! tell the client to delete it from view.
11927 simClient.SendKillObject(Scene.RegionInfo.RegionHandle, 12145 simClient.SendKillObject(new List<uint> { localId });
11928 new List<uint> { localId });
11929 } 12146 }
11930 else 12147 else
11931 { 12148 {
@@ -12129,7 +12346,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12129 /// <param name="throttles"></param> 12346 /// <param name="throttles"></param>
12130 public void SetChildAgentThrottle(byte[] throttles) 12347 public void SetChildAgentThrottle(byte[] throttles)
12131 { 12348 {
12132 m_udpClient.SetThrottles(throttles); 12349 SetChildAgentThrottle(throttles, 1.0f);
12350 }
12351
12352 public void SetChildAgentThrottle(byte[] throttles,float factor)
12353 {
12354 m_udpClient.SetThrottles(throttles, factor);
12133 GenericCall2 handler = OnUpdateThrottles; 12355 GenericCall2 handler = OnUpdateThrottles;
12134 if (handler != null) 12356 if (handler != null)
12135 { 12357 {
@@ -12138,16 +12360,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12138 } 12360 }
12139 12361
12140 /// <summary> 12362 /// <summary>
12141 /// Sets the throttles from values supplied by the client 12363 /// Sets the throttles from values supplied caller
12142 /// </summary> 12364 /// </summary>
12143 /// <param name="throttles"></param> 12365 /// <param name="throttles"></param>
12144 public void SetAgentThrottleSilent(int throttle, int setting) 12366 public void SetAgentThrottleSilent(int throttle, int setting)
12145 { 12367 {
12146 m_udpClient.ForceThrottleSetting(throttle,setting); 12368 m_udpClient.ForceThrottleSetting(throttle,setting);
12147 //m_udpClient.SetThrottles(throttles);
12148
12149 } 12369 }
12150 12370
12371 public int GetAgentThrottleSilent(int throttle)
12372 {
12373 return m_udpClient.GetThrottleSetting(throttle);
12374 }
12151 12375
12152 /// <summary> 12376 /// <summary>
12153 /// Get the current throttles for this client as a packed byte array 12377 /// Get the current throttles for this client as a packed byte array
@@ -12250,8 +12474,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12250 uint regionY = 0; 12474 uint regionY = 0;
12251 12475
12252 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY); 12476 Utils.LongToUInts(m_scene.RegionInfo.RegionHandle, out regionX, out regionY);
12253 locx = Convert.ToSingle(args[0]) - (float)regionX; 12477 locx = (float)(Convert.ToDouble(args[0]) - (double)regionX);
12254 locy = Convert.ToSingle(args[1]) - (float)regionY; 12478 locy = (float)(Convert.ToDouble(args[1]) - (double)regionY);
12255 locz = Convert.ToSingle(args[2]); 12479 locz = Convert.ToSingle(args[2]);
12256 12480
12257 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo; 12481 Action<Vector3, bool, bool> handlerAutoPilotGo = OnAutoPilotGo;
@@ -12299,6 +12523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12299 12523
12300 shape.PCode = addPacket.ObjectData.PCode; 12524 shape.PCode = addPacket.ObjectData.PCode;
12301 shape.State = addPacket.ObjectData.State; 12525 shape.State = addPacket.ObjectData.State;
12526 shape.LastAttachPoint = addPacket.ObjectData.State;
12302 shape.PathBegin = addPacket.ObjectData.PathBegin; 12527 shape.PathBegin = addPacket.ObjectData.PathBegin;
12303 shape.PathEnd = addPacket.ObjectData.PathEnd; 12528 shape.PathEnd = addPacket.ObjectData.PathEnd;
12304 shape.PathScaleX = addPacket.ObjectData.PathScaleX; 12529 shape.PathScaleX = addPacket.ObjectData.PathScaleX;
@@ -12329,7 +12554,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12329 ClientInfo info = m_udpClient.GetClientInfo(); 12554 ClientInfo info = m_udpClient.GetClientInfo();
12330 12555
12331 info.proxyEP = null; 12556 info.proxyEP = null;
12332 info.agentcircuit = RequestClientInfo(); 12557 if (info.agentcircuit == null)
12558 info.agentcircuit = RequestClientInfo();
12333 12559
12334 return info; 12560 return info;
12335 } 12561 }
@@ -12712,11 +12938,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
12712 OutPacket(dialog, ThrottleOutPacketType.Task); 12938 OutPacket(dialog, ThrottleOutPacketType.Task);
12713 } 12939 }
12714 12940
12715 public void StopFlying(ISceneEntity p) 12941 public void SendAgentTerseUpdate(ISceneEntity p)
12716 { 12942 {
12717 if (p is ScenePresence) 12943 if (p is ScenePresence)
12718 { 12944 {
12719 ScenePresence presence = p as ScenePresence; 12945// m_log.DebugFormat(
12946// "[LLCLIENTVIEW]: Immediately sending terse agent update for {0} to {1} in {2}",
12947// p.Name, Name, Scene.Name);
12948
12720 // It turns out to get the agent to stop flying, you have to feed it stop flying velocities 12949 // 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 12950 // 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 12951 // velocity, collision plane and avatar height
@@ -12724,34 +12953,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 12953 // 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 12954 // when the avatar stands up
12726 12955
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 = 12956 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block =
12749 CreateImprovedTerseBlock(p, false); 12957 CreateImprovedTerseBlock(p, false);
12750 12958
12751 const float TIME_DILATION = 1.0f; 12959 const float TIME_DILATION = 1.0f;
12752 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); 12960 ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f);
12753 12961
12754
12755 ImprovedTerseObjectUpdatePacket packet 12962 ImprovedTerseObjectUpdatePacket packet
12756 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( 12963 = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(
12757 PacketType.ImprovedTerseObjectUpdate); 12964 PacketType.ImprovedTerseObjectUpdate);