aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs1576
1 files changed, 797 insertions, 779 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 05a2a63..b027882 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -51,6 +51,44 @@ using Nini.Config;
51 51
52namespace OpenSim.Region.ClientStack.LindenUDP 52namespace OpenSim.Region.ClientStack.LindenUDP
53{ 53{
54 #region Enums
55
56 /// <summary>
57 /// Specifies the fields that have been changed when sending a prim or
58 /// avatar update
59 /// </summary>
60 [Flags]
61 public enum PrimUpdateFlags : uint
62 {
63 None = 0,
64 AttachmentPoint = 1 << 0,
65 Material = 1 << 1,
66 ClickAction = 1 << 2,
67 Scale = 1 << 3,
68 ParentID = 1 << 4,
69 PrimFlags = 1 << 5,
70 PrimData = 1 << 6,
71 MediaURL = 1 << 7,
72 ScratchPad = 1 << 8,
73 Textures = 1 << 9,
74 TextureAnim = 1 << 10,
75 NameValue = 1 << 11,
76 Position = 1 << 12,
77 Rotation = 1 << 13,
78 Velocity = 1 << 14,
79 Acceleration = 1 << 15,
80 AngularVelocity = 1 << 16,
81 CollisionPlane = 1 << 17,
82 Text = 1 << 18,
83 Particles = 1 << 19,
84 ExtraData = 1 << 20,
85 Sound = 1 << 21,
86 Joint = 1 << 22,
87 FullUpdate = UInt32.MaxValue
88 }
89
90 #endregion Enums
91
54 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 92 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
55 93
56 /// <summary> 94 /// <summary>
@@ -257,6 +295,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 public event MuteListRequest OnMuteListRequest; 295 public event MuteListRequest OnMuteListRequest;
258 public event AvatarInterestUpdate OnAvatarInterestUpdate; 296 public event AvatarInterestUpdate OnAvatarInterestUpdate;
259 public event PlacesQuery OnPlacesQuery; 297 public event PlacesQuery OnPlacesQuery;
298 public event AgentFOV OnAgentFOV;
260 299
261 #endregion Events 300 #endregion Events
262 301
@@ -282,12 +321,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
282 private readonly IGroupsModule m_GroupsModule; 321 private readonly IGroupsModule m_GroupsModule;
283 322
284 private int m_cachedTextureSerial; 323 private int m_cachedTextureSerial;
285 private Timer m_avatarTerseUpdateTimer; 324 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
286 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 325 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
287 private Timer m_primTerseUpdateTimer; 326 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
288 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
289 private Timer m_primFullUpdateTimer;
290 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = new List<ObjectUpdatePacket.ObjectDataBlock>();
291 private int m_moneyBalance; 327 private int m_moneyBalance;
292 private int m_animationSequenceNumber = 1; 328 private int m_animationSequenceNumber = 1;
293 private bool m_SendLogoutPacketWhenClosing = true; 329 private bool m_SendLogoutPacketWhenClosing = true;
@@ -296,26 +332,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
296 332
297 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); 333 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>();
298 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 334 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
299 protected IScene m_scene; 335 protected Scene m_scene;
300 protected LLImageManager m_imageManager; 336 protected LLImageManager m_imageManager;
301 protected string m_firstName; 337 protected string m_firstName;
302 protected string m_lastName; 338 protected string m_lastName;
303 protected Thread m_clientThread; 339 protected Thread m_clientThread;
304 protected Vector3 m_startpos; 340 protected Vector3 m_startpos;
305 protected EndPoint m_userEndPoint; 341 protected EndPoint m_userEndPoint;
306 protected UUID m_activeGroupID = UUID.Zero; 342 protected UUID m_activeGroupID;
307 protected string m_activeGroupName = String.Empty; 343 protected string m_activeGroupName = String.Empty;
308 protected ulong m_activeGroupPowers; 344 protected ulong m_activeGroupPowers;
309 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); 345 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>();
310 protected int m_terrainCheckerCount; 346 protected int m_terrainCheckerCount;
311 347 protected uint m_agentFOVCounter;
312 // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet 348
313 protected int m_primTerseUpdatesPerPacket = 10; 349 // These numbers are guesses at a decent tradeoff between responsiveness
314 protected int m_primFullUpdatesPerPacket = 14; 350 // of the interest list and throughput. Lower is more responsive, higher
315 protected int m_primTerseUpdateRate = 10; 351 // is better throughput
316 protected int m_primFullUpdateRate = 14; 352 protected int m_primTerseUpdatesPerPacket = 25;
317 protected int m_avatarTerseUpdateRate = 50; 353 protected int m_primFullUpdatesPerPacket = 100;
318 protected int m_avatarTerseUpdatesPerPacket = 5; 354 protected int m_avatarTerseUpdatesPerPacket = 10;
319 /// <summary>Number of texture packets to put on the queue each time the 355 /// <summary>Number of texture packets to put on the queue each time the
320 /// OnQueueEmpty event is triggered for the texture category</summary> 356 /// OnQueueEmpty event is triggered for the texture category</summary>
321 protected int m_textureSendLimit = 20; 357 protected int m_textureSendLimit = 20;
@@ -369,21 +405,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
369 /// <summary> 405 /// <summary>
370 /// Constructor 406 /// Constructor
371 /// </summary> 407 /// </summary>
372 public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, 408 public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
373 UUID agentId, UUID sessionId, uint circuitCode) 409 UUID agentId, UUID sessionId, uint circuitCode)
374 { 410 {
375 RegisterInterface<IClientIM>(this); 411 RegisterInterface<IClientIM>(this);
376 RegisterInterface<IClientChat>(this); 412 RegisterInterface<IClientChat>(this);
377 RegisterInterface<IClientIPEndpoint>(this); 413 RegisterInterface<IClientIPEndpoint>(this);
378 414
379 InitDefaultAnimations(); 415 InitDefaultAnimations();
380 416
381 m_scene = scene; 417 m_scene = scene;
418
419 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
420 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
421 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
422
382 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 423 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
383 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>(); 424 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>();
384 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); 425 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
385 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>()); 426 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
386 m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); 427 m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion());
387 m_agentId = agentId; 428 m_agentId = agentId;
388 m_sessionId = sessionId; 429 m_sessionId = sessionId;
389 m_secureSessionId = sessionInfo.LoginInfo.SecureSession; 430 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
@@ -438,25 +479,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
438 // Remove ourselves from the scene 479 // Remove ourselves from the scene
439 m_scene.RemoveClient(AgentId); 480 m_scene.RemoveClient(AgentId);
440 481
441 // Shut down timers. Thread Context of this method is murky. Lock all timers
442 if (m_avatarTerseUpdateTimer.Enabled)
443 lock (m_avatarTerseUpdateTimer)
444 m_avatarTerseUpdateTimer.Stop();
445 if (m_primTerseUpdateTimer.Enabled)
446 lock (m_primTerseUpdateTimer)
447 m_primTerseUpdateTimer.Stop();
448 if (m_primFullUpdateTimer.Enabled)
449 lock (m_primFullUpdateTimer)
450 m_primFullUpdateTimer.Stop();
451
452 // We can't reach into other scenes and close the connection 482 // We can't reach into other scenes and close the connection
453 // We need to do this over grid communications 483 // We need to do this over grid communications
454 //m_scene.CloseAllAgents(CircuitCode); 484 //m_scene.CloseAllAgents(CircuitCode);
455 485
456 m_avatarTerseUpdateTimer.Dispose();
457 m_primTerseUpdateTimer.Dispose();
458 m_primFullUpdateTimer.Dispose();
459
460 // Disable UDP handling for this client 486 // Disable UDP handling for this client
461 m_udpClient.Shutdown(); 487 m_udpClient.Shutdown();
462 488
@@ -474,7 +500,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 kupack.UserInfo.SessionID = SessionId; 500 kupack.UserInfo.SessionID = SessionId;
475 kupack.TargetBlock.TargetIP = 0; 501 kupack.TargetBlock.TargetIP = 0;
476 kupack.TargetBlock.TargetPort = 0; 502 kupack.TargetBlock.TargetPort = 0;
477 kupack.UserInfo.Reason = Utils.StringToBytes(message); 503 kupack.UserInfo.Reason = Util.StringToBytes256(message);
478 OutPacket(kupack, ThrottleOutPacketType.Task); 504 OutPacket(kupack, ThrottleOutPacketType.Task);
479 // You must sleep here or users get no message! 505 // You must sleep here or users get no message!
480 Thread.Sleep(500); 506 Thread.Sleep(500);
@@ -483,18 +509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 509
484 public void Stop() 510 public void Stop()
485 { 511 {
486 // Shut down timers. Thread Context is Murky, lock all timers!
487 if (m_avatarTerseUpdateTimer.Enabled)
488 lock (m_avatarTerseUpdateTimer)
489 m_avatarTerseUpdateTimer.Stop();
490
491 if (m_primTerseUpdateTimer.Enabled)
492 lock (m_primTerseUpdateTimer)
493 m_primTerseUpdateTimer.Stop();
494 512
495 if (m_primFullUpdateTimer.Enabled)
496 lock (m_primFullUpdateTimer)
497 m_primFullUpdateTimer.Stop();
498 } 513 }
499 514
500 #endregion Client Methods 515 #endregion Client Methods
@@ -590,18 +605,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
590 605
591 public virtual void Start() 606 public virtual void Start()
592 { 607 {
593 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
594 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
595 m_avatarTerseUpdateTimer.AutoReset = false;
596
597 m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
598 m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
599 m_primTerseUpdateTimer.AutoReset = false;
600
601 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
602 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
603 m_primFullUpdateTimer.AutoReset = false;
604
605 m_scene.AddNewClient(this); 608 m_scene.AddNewClient(this);
606 609
607 RefreshGroupMembership(); 610 RefreshGroupMembership();
@@ -642,7 +645,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
642 handshake.RegionInfo.WaterHeight = args.waterHeight; 645 handshake.RegionInfo.WaterHeight = args.waterHeight;
643 646
644 handshake.RegionInfo.RegionFlags = args.regionFlags; 647 handshake.RegionInfo.RegionFlags = args.regionFlags;
645 handshake.RegionInfo.SimName = Utils.StringToBytes(args.regionName); 648 handshake.RegionInfo.SimName = Util.StringToBytes256(args.regionName);
646 handshake.RegionInfo.SimOwner = args.SimOwner; 649 handshake.RegionInfo.SimOwner = args.SimOwner;
647 handshake.RegionInfo.TerrainBase0 = args.terrainBase0; 650 handshake.RegionInfo.TerrainBase0 = args.terrainBase0;
648 handshake.RegionInfo.TerrainBase1 = args.terrainBase1; 651 handshake.RegionInfo.TerrainBase1 = args.terrainBase1;
@@ -698,11 +701,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
698 { 701 {
699 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 702 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
700 reply.ChatData.Audible = audible; 703 reply.ChatData.Audible = audible;
701 reply.ChatData.Message = Utils.StringToBytes(message); 704 reply.ChatData.Message = Util.StringToBytes1024(message);
702 reply.ChatData.ChatType = type; 705 reply.ChatData.ChatType = type;
703 reply.ChatData.SourceType = source; 706 reply.ChatData.SourceType = source;
704 reply.ChatData.Position = fromPos; 707 reply.ChatData.Position = fromPos;
705 reply.ChatData.FromName = Utils.StringToBytes(fromName); 708 reply.ChatData.FromName = Util.StringToBytes256(fromName);
706 reply.ChatData.OwnerID = fromAgentID; 709 reply.ChatData.OwnerID = fromAgentID;
707 reply.ChatData.SourceID = fromAgentID; 710 reply.ChatData.SourceID = fromAgentID;
708 711
@@ -723,7 +726,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
723 726
724 msg.AgentData.AgentID = new UUID(im.fromAgentID); 727 msg.AgentData.AgentID = new UUID(im.fromAgentID);
725 msg.AgentData.SessionID = UUID.Zero; 728 msg.AgentData.SessionID = UUID.Zero;
726 msg.MessageBlock.FromAgentName = Utils.StringToBytes(im.fromAgentName); 729 msg.MessageBlock.FromAgentName = Util.StringToBytes256(im.fromAgentName);
727 msg.MessageBlock.Dialog = im.dialog; 730 msg.MessageBlock.Dialog = im.dialog;
728 msg.MessageBlock.FromGroup = im.fromGroup; 731 msg.MessageBlock.FromGroup = im.fromGroup;
729 if (im.imSessionID == UUID.Zero.Guid) 732 if (im.imSessionID == UUID.Zero.Guid)
@@ -736,12 +739,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
736 msg.MessageBlock.RegionID = new UUID(im.RegionID); 739 msg.MessageBlock.RegionID = new UUID(im.RegionID);
737 msg.MessageBlock.Timestamp = im.timestamp; 740 msg.MessageBlock.Timestamp = im.timestamp;
738 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID); 741 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID);
739 // Cap the message length at 1099. There is a limit in ImprovedInstantMessagePacket 742 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
740 // the limit is 1100 but a 0 byte gets added to mark the end of the string
741 if (im.message != null && im.message.Length > 1099)
742 msg.MessageBlock.Message = Utils.StringToBytes(im.message.Substring(0, 1099));
743 else
744 msg.MessageBlock.Message = Utils.StringToBytes(im.message);
745 msg.MessageBlock.BinaryBucket = im.binaryBucket; 743 msg.MessageBlock.BinaryBucket = im.binaryBucket;
746 744
747 if (im.message.StartsWith("[grouptest]")) 745 if (im.message.StartsWith("[grouptest]"))
@@ -759,7 +757,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
759 eq.ChatterboxInvitation( 757 eq.ChatterboxInvitation(
760 new UUID("00000000-68f9-1111-024e-222222111123"), 758 new UUID("00000000-68f9-1111-024e-222222111123"),
761 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0, 759 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
762 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Utils.StringToBytes("OpenSimulator Testing")); 760 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
763 761
764 eq.ChatterBoxSessionAgentListUpdates( 762 eq.ChatterBoxSessionAgentListUpdates(
765 new UUID("00000000-68f9-1111-024e-222222111123"), 763 new UUID("00000000-68f9-1111-024e-222222111123"),
@@ -776,13 +774,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
776 public void SendGenericMessage(string method, List<string> message) 774 public void SendGenericMessage(string method, List<string> message)
777 { 775 {
778 GenericMessagePacket gmp = new GenericMessagePacket(); 776 GenericMessagePacket gmp = new GenericMessagePacket();
779 gmp.MethodData.Method = Utils.StringToBytes(method); 777 gmp.MethodData.Method = Util.StringToBytes256(method);
780 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; 778 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
781 int i = 0; 779 int i = 0;
782 foreach (string val in message) 780 foreach (string val in message)
783 { 781 {
784 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); 782 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
785 gmp.ParamList[i++].Parameter = Utils.StringToBytes(val); 783 gmp.ParamList[i++].Parameter = Util.StringToBytes256(val);
786 } 784 }
787 OutPacket(gmp, ThrottleOutPacketType.Task); 785 OutPacket(gmp, ThrottleOutPacketType.Task);
788 } 786 }
@@ -1046,7 +1044,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1046 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8; 1044 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
1047 newSimPack.RegionData.SimIP += (uint)byteIP[0]; 1045 newSimPack.RegionData.SimIP += (uint)byteIP[0];
1048 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port; 1046 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
1049 newSimPack.RegionData.SeedCapability = Utils.StringToBytes(capsURL); 1047 newSimPack.RegionData.SeedCapability = Util.StringToBytes256(capsURL);
1050 1048
1051 // Hack to get this out immediately and skip throttles 1049 // Hack to get this out immediately and skip throttles
1052 OutPacket(newSimPack, ThrottleOutPacketType.Unknown); 1050 OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
@@ -1124,7 +1122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1124 teleport.Info.RegionHandle = regionHandle; 1122 teleport.Info.RegionHandle = regionHandle;
1125 teleport.Info.SimAccess = simAccess; 1123 teleport.Info.SimAccess = simAccess;
1126 1124
1127 teleport.Info.SeedCapability = Utils.StringToBytes(capsURL); 1125 teleport.Info.SeedCapability = Util.StringToBytes256(capsURL);
1128 1126
1129 IPAddress oIP = newRegionEndPoint.Address; 1127 IPAddress oIP = newRegionEndPoint.Address;
1130 byte[] byteIP = oIP.GetAddressBytes(); 1128 byte[] byteIP = oIP.GetAddressBytes();
@@ -1149,7 +1147,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1149 { 1147 {
1150 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed); 1148 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
1151 tpFailed.Info.AgentID = AgentId; 1149 tpFailed.Info.AgentID = AgentId;
1152 tpFailed.Info.Reason = Utils.StringToBytes(reason); 1150 tpFailed.Info.Reason = Util.StringToBytes256(reason);
1153 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0]; 1151 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0];
1154 1152
1155 // Hack to get this out immediately and skip throttles 1153 // Hack to get this out immediately and skip throttles
@@ -1881,11 +1879,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1881 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); 1879 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
1882 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid; 1880 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
1883 sendAgentDataUpdate.AgentData.AgentID = agentid; 1881 sendAgentDataUpdate.AgentData.AgentID = agentid;
1884 sendAgentDataUpdate.AgentData.FirstName = Utils.StringToBytes(firstname); 1882 sendAgentDataUpdate.AgentData.FirstName = Util.StringToBytes256(firstname);
1885 sendAgentDataUpdate.AgentData.GroupName = Utils.StringToBytes(groupname); 1883 sendAgentDataUpdate.AgentData.GroupName = Util.StringToBytes256(groupname);
1886 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers; 1884 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
1887 sendAgentDataUpdate.AgentData.GroupTitle = Utils.StringToBytes(grouptitle); 1885 sendAgentDataUpdate.AgentData.GroupTitle = Util.StringToBytes256(grouptitle);
1888 sendAgentDataUpdate.AgentData.LastName = Utils.StringToBytes(lastname); 1886 sendAgentDataUpdate.AgentData.LastName = Util.StringToBytes256(lastname);
1889 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task); 1887 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
1890 } 1888 }
1891 1889
@@ -1898,7 +1896,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1898 { 1896 {
1899 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage); 1897 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
1900 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock(); 1898 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock();
1901 alertPack.AlertData.Message = Utils.StringToBytes(message); 1899 alertPack.AlertData.Message = Util.StringToBytes256(message);
1902 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0]; 1900 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0];
1903 OutPacket(alertPack, ThrottleOutPacketType.Task); 1901 OutPacket(alertPack, ThrottleOutPacketType.Task);
1904 } 1902 }
@@ -1925,7 +1923,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1925 { 1923 {
1926 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); 1924 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
1927 alertPack.AgentData.AgentID = AgentId; 1925 alertPack.AgentData.AgentID = AgentId;
1928 alertPack.AlertData.Message = Utils.StringToBytes(message); 1926 alertPack.AlertData.Message = Util.StringToBytes256(message);
1929 alertPack.AlertData.Modal = modal; 1927 alertPack.AlertData.Modal = modal;
1930 1928
1931 return alertPack; 1929 return alertPack;
@@ -1935,12 +1933,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1935 string url) 1933 string url)
1936 { 1934 {
1937 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL); 1935 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
1938 loadURL.Data.ObjectName = Utils.StringToBytes(objectname); 1936 loadURL.Data.ObjectName = Util.StringToBytes256(objectname);
1939 loadURL.Data.ObjectID = objectID; 1937 loadURL.Data.ObjectID = objectID;
1940 loadURL.Data.OwnerID = ownerID; 1938 loadURL.Data.OwnerID = ownerID;
1941 loadURL.Data.OwnerIsGroup = groupOwned; 1939 loadURL.Data.OwnerIsGroup = groupOwned;
1942 loadURL.Data.Message = Utils.StringToBytes(message); 1940 loadURL.Data.Message = Util.StringToBytes256(message);
1943 loadURL.Data.URL = Utils.StringToBytes(url); 1941 loadURL.Data.URL = Util.StringToBytes256(url);
1944 OutPacket(loadURL, ThrottleOutPacketType.Task); 1942 OutPacket(loadURL, ThrottleOutPacketType.Task);
1945 } 1943 }
1946 1944
@@ -1948,18 +1946,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1948 { 1946 {
1949 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); 1947 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
1950 dialog.Data.ObjectID = objectID; 1948 dialog.Data.ObjectID = objectID;
1951 dialog.Data.ObjectName = Utils.StringToBytes(objectname); 1949 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
1952 // this is the username of the *owner* 1950 // this is the username of the *owner*
1953 dialog.Data.FirstName = Utils.StringToBytes(ownerFirstName); 1951 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
1954 dialog.Data.LastName = Utils.StringToBytes(ownerLastName); 1952 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
1955 dialog.Data.Message = Utils.StringToBytes(msg); 1953 dialog.Data.Message = Util.StringToBytes1024(msg);
1956 dialog.Data.ImageID = textureID; 1954 dialog.Data.ImageID = textureID;
1957 dialog.Data.ChatChannel = ch; 1955 dialog.Data.ChatChannel = ch;
1958 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; 1956 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
1959 for (int i = 0; i < buttonlabels.Length; i++) 1957 for (int i = 0; i < buttonlabels.Length; i++)
1960 { 1958 {
1961 buttons[i] = new ScriptDialogPacket.ButtonsBlock(); 1959 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
1962 buttons[i].ButtonLabel = Utils.StringToBytes(buttonlabels[i]); 1960 buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]);
1963 } 1961 }
1964 dialog.Buttons = buttons; 1962 dialog.Buttons = buttons;
1965 OutPacket(dialog, ThrottleOutPacketType.Task); 1963 OutPacket(dialog, ThrottleOutPacketType.Task);
@@ -2115,19 +2113,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2115 avatarReply.AgentData.AgentID = AgentId; 2113 avatarReply.AgentData.AgentID = AgentId;
2116 avatarReply.AgentData.AvatarID = avatarID; 2114 avatarReply.AgentData.AvatarID = avatarID;
2117 if (aboutText != null) 2115 if (aboutText != null)
2118 avatarReply.PropertiesData.AboutText = Utils.StringToBytes(aboutText); 2116 avatarReply.PropertiesData.AboutText = Util.StringToBytes1024(aboutText);
2119 else 2117 else
2120 avatarReply.PropertiesData.AboutText = Utils.StringToBytes(""); 2118 avatarReply.PropertiesData.AboutText = Utils.EmptyBytes;
2121 avatarReply.PropertiesData.BornOn = Utils.StringToBytes(bornOn); 2119 avatarReply.PropertiesData.BornOn = Util.StringToBytes256(bornOn);
2122 avatarReply.PropertiesData.CharterMember = charterMember; 2120 avatarReply.PropertiesData.CharterMember = charterMember;
2123 if (flAbout != null) 2121 if (flAbout != null)
2124 avatarReply.PropertiesData.FLAboutText = Utils.StringToBytes(flAbout); 2122 avatarReply.PropertiesData.FLAboutText = Util.StringToBytes256(flAbout);
2125 else 2123 else
2126 avatarReply.PropertiesData.FLAboutText = Utils.StringToBytes(""); 2124 avatarReply.PropertiesData.FLAboutText = Utils.EmptyBytes;
2127 avatarReply.PropertiesData.Flags = flags; 2125 avatarReply.PropertiesData.Flags = flags;
2128 avatarReply.PropertiesData.FLImageID = flImageID; 2126 avatarReply.PropertiesData.FLImageID = flImageID;
2129 avatarReply.PropertiesData.ImageID = imageID; 2127 avatarReply.PropertiesData.ImageID = imageID;
2130 avatarReply.PropertiesData.ProfileURL = Utils.StringToBytes(profileURL); 2128 avatarReply.PropertiesData.ProfileURL = Util.StringToBytes256(profileURL);
2131 avatarReply.PropertiesData.PartnerID = partnerID; 2129 avatarReply.PropertiesData.PartnerID = partnerID;
2132 OutPacket(avatarReply, ThrottleOutPacketType.Task); 2130 OutPacket(avatarReply, ThrottleOutPacketType.Task);
2133 } 2131 }
@@ -2254,7 +2252,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2254 Group.Contribution = GroupMembership[i].Contribution; 2252 Group.Contribution = GroupMembership[i].Contribution;
2255 Group.GroupID = GroupMembership[i].GroupID; 2253 Group.GroupID = GroupMembership[i].GroupID;
2256 Group.GroupInsigniaID = GroupMembership[i].GroupPicture; 2254 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
2257 Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); 2255 Group.GroupName = Util.StringToBytes256(GroupMembership[i].GroupName);
2258 Group.GroupPowers = GroupMembership[i].GroupPowers; 2256 Group.GroupPowers = GroupMembership[i].GroupPowers;
2259 Groups[i] = Group; 2257 Groups[i] = Group;
2260 2258
@@ -2288,7 +2286,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2288 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; 2286 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
2289 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); 2287 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
2290 uidnamebloc.ID = groupLLUID; 2288 uidnamebloc.ID = groupLLUID;
2291 uidnamebloc.GroupName = Utils.StringToBytes(GroupName); 2289 uidnamebloc.GroupName = Util.StringToBytes256(GroupName);
2292 uidnameblock[0] = uidnamebloc; 2290 uidnameblock[0] = uidnamebloc;
2293 pack.UUIDNameBlock = uidnameblock; 2291 pack.UUIDNameBlock = uidnameblock;
2294 OutPacket(pack, ThrottleOutPacketType.Task); 2292 OutPacket(pack, ThrottleOutPacketType.Task);
@@ -2313,8 +2311,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2313 lsrepdb.Score = lsrpia[i].Score; 2311 lsrepdb.Score = lsrpia[i].Score;
2314 lsrepdb.TaskID = lsrpia[i].TaskID; 2312 lsrepdb.TaskID = lsrpia[i].TaskID;
2315 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; 2313 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
2316 lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); 2314 lsrepdb.TaskName = Util.StringToBytes256(lsrpia[i].TaskName);
2317 lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); 2315 lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName);
2318 lsrepdba[i] = lsrepdb; 2316 lsrepdba[i] = lsrepdb;
2319 } 2317 }
2320 lsrp.ReportData = lsrepdba; 2318 lsrp.ReportData = lsrepdba;
@@ -3127,7 +3125,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3127 3125
3128 avp.Sender.IsTrial = false; 3126 avp.Sender.IsTrial = false;
3129 avp.Sender.ID = agentID; 3127 avp.Sender.ID = agentID;
3130 OutPacket(avp, ThrottleOutPacketType.State); 3128 OutPacket(avp, ThrottleOutPacketType.Task);
3131 } 3129 }
3132 3130
3133 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3131 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3159,123 +3157,174 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3159 3157
3160 #endregion 3158 #endregion
3161 3159
3162 #region Avatar Packet/data sending Methods 3160 #region Prim/Avatar Updates
3163 3161
3164 /// <summary> 3162 /*void SendObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3165 /// send a objectupdate packet with information about the clients avatar
3166 /// </summary>
3167 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID,
3168 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
3169 { 3163 {
3170 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3164 bool canUseCompressed, canUseImproved;
3171 // TODO: don't create new blocks if recycling an old packet 3165 UpdateFlagsToPacketType(creatorFlags, updateFlags, out canUseCompressed, out canUseImproved);
3172 objupdate.RegionData.RegionHandle = regionHandle;
3173 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3174 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3175 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry);
3176 3166
3177 //give this avatar object a local id and assign the user a name 3167 if (!canUseImproved && !canUseCompressed)
3178 objupdate.ObjectData[0].ID = avatarLocalID; 3168 SendFullObjectUpdate(obj, creatorFlags, updateFlags);
3179 objupdate.ObjectData[0].FullID = avatarID; 3169 else if (!canUseImproved)
3180 objupdate.ObjectData[0].ParentID = parentID; 3170 SendObjectUpdateCompressed(obj, creatorFlags, updateFlags);
3181 objupdate.ObjectData[0].NameValue = 3171 else
3182 Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); 3172 SendImprovedTerseObjectUpdate(obj, creatorFlags, updateFlags);
3173 }
3183 3174
3184 Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); 3175 void SendFullObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3185 byte[] pb = pos2.GetBytes(); 3176 {
3186 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); 3177 IClientAPI owner;
3178 if (m_scene.ClientManager.TryGetValue(obj.OwnerID, out owner) && owner is LLClientView)
3179 {
3180 LLClientView llOwner = (LLClientView)owner;
3187 3181
3188 byte[] rot = rotation.GetBytes(); 3182 // Send an update out to the owner
3189 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); 3183 ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket();
3184 updateToOwner.RegionData.RegionHandle = obj.RegionHandle;
3185 //updateToOwner.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3186 updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3187 updateToOwner.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags | creatorFlags | PrimFlags.ObjectYouOwner, 0);
3190 3188
3191 objupdate.Header.Zerocoded = true; 3189 m_udpServer.SendPacket(llOwner.UDPClient, updateToOwner, ThrottleOutPacketType.State, true);
3192 OutPacket(objupdate, ThrottleOutPacketType.Task); 3190 }
3191
3192 // Send an update out to everyone else
3193 ObjectUpdatePacket updateToOthers = new ObjectUpdatePacket();
3194 updateToOthers.RegionData.RegionHandle = obj.RegionHandle;
3195 //updateToOthers.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3196 updateToOthers.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3197 updateToOthers.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags, 0);
3198
3199 m_scene.ClientManager.ForEach(
3200 delegate(IClientAPI client)
3201 {
3202 if (client.AgentId != obj.OwnerID && client is LLClientView)
3203 {
3204 LLClientView llClient = (LLClientView)client;
3205 m_udpServer.SendPacket(llClient.UDPClient, updateToOthers, ThrottleOutPacketType.State, true);
3206 }
3207 }
3208 );
3193 } 3209 }
3194 3210
3195 /// <summary> 3211 void SendObjectUpdateCompressed(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3196 /// Send a terse positional/rotation/velocity update about an avatar
3197 /// to the client. This avatar can be that of the client itself.
3198 /// </summary>
3199 public virtual void SendAvatarTerseUpdate(ulong regionHandle,
3200 ushort timeDilation, uint localID, Vector3 position,
3201 Vector3 velocity, Quaternion rotation, UUID agentid)
3202 { 3212 {
3203 if (rotation.X == rotation.Y && 3213 }
3204 rotation.Y == rotation.Z &&
3205 rotation.Z == rotation.W && rotation.W == 0)
3206 rotation = Quaternion.Identity;
3207 3214
3208 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = 3215 void SendImprovedTerseObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3209 CreateAvatarImprovedBlock(localID, position, velocity,rotation); 3216 {
3210 3217 }
3211 lock (m_avatarTerseUpdates)
3212 {
3213 m_avatarTerseUpdates.Add(terseBlock);
3214 3218
3215 // If packet is full or own movement packet, send it. 3219 void UpdateFlagsToPacketType(PrimFlags creatorFlags, PrimUpdateFlags updateFlags, out bool canUseCompressed, out bool canUseImproved)
3216 if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) 3220 {
3221 canUseCompressed = true;
3222 canUseImproved = true;
3223
3224 if ((updateFlags & PrimUpdateFlags.FullUpdate) == PrimUpdateFlags.FullUpdate || creatorFlags != PrimFlags.None)
3225 {
3226 canUseCompressed = false;
3227 canUseImproved = false;
3228 }
3229 else
3230 {
3231 if ((updateFlags & PrimUpdateFlags.Velocity) != 0 ||
3232 (updateFlags & PrimUpdateFlags.Acceleration) != 0 ||
3233 (updateFlags & PrimUpdateFlags.CollisionPlane) != 0 ||
3234 (updateFlags & PrimUpdateFlags.Joint) != 0)
3217 { 3235 {
3218 ProcessAvatarTerseUpdates(this, null); 3236 canUseCompressed = false;
3219 } 3237 }
3220 else if (m_avatarTerseUpdates.Count == 1) 3238
3239 if ((updateFlags & PrimUpdateFlags.PrimFlags) != 0 ||
3240 (updateFlags & PrimUpdateFlags.ParentID) != 0 ||
3241 (updateFlags & PrimUpdateFlags.Scale) != 0 ||
3242 (updateFlags & PrimUpdateFlags.PrimData) != 0 ||
3243 (updateFlags & PrimUpdateFlags.Text) != 0 ||
3244 (updateFlags & PrimUpdateFlags.NameValue) != 0 ||
3245 (updateFlags & PrimUpdateFlags.ExtraData) != 0 ||
3246 (updateFlags & PrimUpdateFlags.TextureAnim) != 0 ||
3247 (updateFlags & PrimUpdateFlags.Sound) != 0 ||
3248 (updateFlags & PrimUpdateFlags.Particles) != 0 ||
3249 (updateFlags & PrimUpdateFlags.Material) != 0 ||
3250 (updateFlags & PrimUpdateFlags.ClickAction) != 0 ||
3251 (updateFlags & PrimUpdateFlags.MediaURL) != 0 ||
3252 (updateFlags & PrimUpdateFlags.Joint) != 0)
3221 { 3253 {
3222 lock (m_avatarTerseUpdateTimer) 3254 canUseImproved = false;
3223 m_avatarTerseUpdateTimer.Start();
3224 } 3255 }
3225 } 3256 }
3226 } 3257 }*/
3258
3259 #endregion Prim/Avatar Updates
3260
3261 #region Avatar Packet/Data Sending Methods
3227 3262
3228 private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) 3263 /// <summary>
3264 /// Send an ObjectUpdate packet with information about an avatar
3265 /// </summary>
3266 public void SendAvatarData(SendAvatarData data)
3229 { 3267 {
3230 lock (m_avatarTerseUpdates) 3268 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3231 { 3269 objupdate.Header.Zerocoded = true;
3232 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3233 3270
3234 terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); 3271 objupdate.RegionData.RegionHandle = data.RegionHandle;
3272 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3273
3274 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3275 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data);
3235 3276
3236 terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; 3277 OutPacket(objupdate, ThrottleOutPacketType.Task);
3237 terse.RegionData.TimeDilation = 3278 }
3238 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3239 3279
3240 int max = m_avatarTerseUpdatesPerPacket; 3280 /// <summary>
3241 if (max > m_avatarTerseUpdates.Count) 3281 /// Send a terse positional/rotation/velocity update about an avatar
3242 max = m_avatarTerseUpdates.Count; 3282 /// to the client. This avatar can be that of the client itself.
3283 /// </summary>
3284 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
3285 {
3286 if (data.Priority == double.NaN)
3287 {
3288 m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
3289 return;
3290 }
3243 3291
3244 int count = 0; 3292 Quaternion rotation = data.Rotation;
3245 int size = 0; 3293 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3294 rotation = Quaternion.Identity;
3246 3295
3247 byte[] zerobuffer = new byte[1024]; 3296 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data);
3248 byte[] blockbuffer = new byte[1024];
3249 3297
3250 for (count = 0 ; count < max ; count++) 3298 lock (m_avatarTerseUpdates.SyncRoot)
3251 { 3299 m_avatarTerseUpdates.Enqueue(data.Priority, terseBlock, data.LocalID);
3252 int length = 0;
3253 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length);
3254 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3255 if (size + length > Packet.MTU)
3256 break;
3257 size += length;
3258 }
3259 3300
3260 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; 3301 // If we received an update about our own avatar, process the avatar update priority queue immediately
3302 if (data.AgentID == m_agentId)
3303 ProcessAvatarTerseUpdates();
3304 }
3261 3305
3262 for (int i = 0 ; i < count ; i++) 3306 private void ProcessAvatarTerseUpdates()
3263 { 3307 {
3264 terse.ObjectData[i] = m_avatarTerseUpdates[0]; 3308 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3265 m_avatarTerseUpdates.RemoveAt(0); 3309 terse.Header.Reliable = false;
3266 } 3310 terse.Header.Zerocoded = true;
3267 3311
3268 terse.Header.Reliable = false; 3312 //terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock();
3269 terse.Header.Zerocoded = true; 3313 terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3270 // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed 3314 terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3271 OutPacket(terse, ThrottleOutPacketType.Task);
3272 3315
3273 if (m_avatarTerseUpdates.Count == 0) 3316 lock (m_avatarTerseUpdates.SyncRoot)
3274 { 3317 {
3275 lock (m_avatarTerseUpdateTimer) 3318 int count = Math.Min(m_avatarTerseUpdates.Count, m_avatarTerseUpdatesPerPacket);
3276 m_avatarTerseUpdateTimer.Stop(); 3319 if (count == 0)
3277 } 3320 return;
3321
3322 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3323 for (int i = 0; i < count; i++)
3324 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
3278 } 3325 }
3326
3327 OutPacket(terse, ThrottleOutPacketType.Task);
3279 } 3328 }
3280 3329
3281 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 3330 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
@@ -3314,319 +3363,231 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3314 OutPacket(loc, ThrottleOutPacketType.Task); 3363 OutPacket(loc, ThrottleOutPacketType.Task);
3315 } 3364 }
3316 3365
3317 #endregion 3366 #endregion Avatar Packet/Data Sending Methods
3318 3367
3319 #region Primitive Packet/data Sending Methods 3368 #region Primitive Packet/Data Sending Methods
3320 3369
3321 /// <summary> 3370 public void SendPrimitiveToClient(SendPrimitiveData data)
3322 ///
3323 /// </summary>
3324 /// <param name="localID"></param>
3325 /// <param name="rotation"></param>
3326 /// <param name="attachPoint"></param>
3327 public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
3328 { 3371 {
3329 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3372 if (data.priority == double.NaN)
3373 {
3374 m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
3330 return; 3375 return;
3376 }
3331 3377
3332 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); 3378 Quaternion rotation = data.rotation;
3333 // TODO: don't create new blocks if recycling an old packet 3379 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3334 attach.AgentData.AgentID = AgentId; 3380 rotation = Quaternion.Identity;
3335 attach.AgentData.SessionID = m_sessionId;
3336 attach.AgentData.AttachmentPoint = attachPoint;
3337 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
3338 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
3339 attach.ObjectData[0].ObjectLocalID = localID;
3340 attach.ObjectData[0].Rotation = rotation;
3341 attach.Header.Zerocoded = true;
3342 OutPacket(attach, ThrottleOutPacketType.Task);
3343 }
3344
3345 public void SendPrimitiveToClient(
3346 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3347 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
3348 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
3349 uint parentID, byte[] particleSystem, byte clickAction, byte material)
3350 {
3351 byte[] textureanim = new byte[0];
3352
3353 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel,
3354 acc, rotation, rvel, flags,
3355 objectID, ownerID, text, color, parentID, particleSystem,
3356 clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0);
3357 }
3358
3359 public void SendPrimitiveToClient(
3360 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3361 Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity,
3362 uint flags,
3363 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
3364 byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius)
3365 {
3366 3381
3367 if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3382 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
3368 return; 3383 return;
3369 if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) 3384 if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9)
3370 return; 3385 return;
3371 3386
3372 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3387 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data);
3373 rotation = Quaternion.Identity;
3374 3388
3375 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); 3389 lock (m_primFullUpdates.SyncRoot)
3390 m_primFullUpdates.Enqueue(data.priority, objectData, data.localID);
3391 }
3376 3392
3377 objectData.ID = localID; 3393 void ProcessPrimFullUpdates()
3378 objectData.FullID = objectID; 3394 {
3379 objectData.OwnerID = ownerID; 3395 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3396 outPacket.Header.Zerocoded = true;
3380 3397
3381 objectData.Text = Util.StringToBytes256(text); 3398 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3382 objectData.TextColor[0] = color[0]; 3399 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3383 objectData.TextColor[1] = color[1];
3384 objectData.TextColor[2] = color[2];
3385 objectData.TextColor[3] = color[3];
3386 objectData.ParentID = parentID;
3387 objectData.PSBlock = particleSystem;
3388 objectData.ClickAction = clickAction;
3389 objectData.Material = material;
3390 objectData.Flags = 0;
3391 3400
3392 if (attachment) 3401 lock (m_primFullUpdates.SyncRoot)
3393 { 3402 {
3394 // Necessary??? 3403 int count = Math.Min(m_primFullUpdates.Count, m_primFullUpdatesPerPacket);
3395 objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); 3404 if (count == 0)
3396 objectData.JointPivot = new Vector3(0, 0, 0); 3405 return;
3397
3398 // Item from inventory???
3399 objectData.NameValue =
3400 Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid);
3401 objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16));
3402 }
3403 3406
3404 // Xantor 20080528: Send sound info as well 3407 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count];
3405 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again 3408 for (int i = 0; i < count; i++)
3406 objectData.Sound = SoundId; 3409 outPacket.ObjectData[i] = m_primFullUpdates.Dequeue();
3407 if (SoundId == UUID.Zero)
3408 {
3409 objectData.OwnerID = UUID.Zero;
3410 objectData.Gain = 0.0f;
3411 objectData.Radius = 0.0f;
3412 objectData.Flags = 0;
3413 } 3410 }
3414 else
3415 {
3416 objectData.OwnerID = ownerID;
3417 objectData.Gain = (float)SoundGain;
3418 objectData.Radius = (float)SoundRadius;
3419 objectData.Flags = SoundFlags;
3420 }
3421
3422 byte[] pb = pos.GetBytes();
3423 Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length);
3424
3425 byte[] vel = velocity.GetBytes();
3426 Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length);
3427 3411
3428 byte[] rot = rotation.GetBytes(); 3412 OutPacket(outPacket, ThrottleOutPacketType.State);
3429 Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); 3413 }
3430
3431 byte[] rvel = rotational_velocity.GetBytes();
3432 Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length);
3433 3414
3434 if (textureanim.Length > 0) 3415 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
3416 {
3417 if (data.Priority == double.NaN)
3435 { 3418 {
3436 objectData.TextureAnim = textureanim; 3419 m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update");
3420 return;
3437 } 3421 }
3438 3422
3439 lock (m_primFullUpdates) 3423 Quaternion rotation = data.Rotation;
3440 { 3424 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3441 if (m_primFullUpdates.Count == 0) 3425 rotation = Quaternion.Identity;
3442 m_primFullUpdateTimer.Start();
3443 3426
3444 m_primFullUpdates.Add(objectData); 3427 if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD
3428 return;
3445 3429
3446 if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) 3430 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data);
3447 ProcessPrimFullUpdates(this, null);
3448 }
3449 }
3450 3431
3451 void HandleQueueEmpty(ThrottleOutPacketType queue) 3432 lock (m_primTerseUpdates.SyncRoot)
3452 { 3433 m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID);
3453 switch (queue)
3454 {
3455 case ThrottleOutPacketType.Texture:
3456 ProcessTextureRequests();
3457 break;
3458 }
3459 } 3434 }
3460 3435
3461 void ProcessTextureRequests() 3436 void ProcessPrimTerseUpdates()
3462 { 3437 {
3463 if (m_imageManager != null) 3438 ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3464 m_imageManager.ProcessImageQueue(m_textureSendLimit); 3439 outPacket.Header.Reliable = false;
3465 } 3440 outPacket.Header.Zerocoded = true;
3466 3441
3467 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) 3442 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3468 { 3443 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3469 lock (m_primFullUpdates)
3470 {
3471 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3472 {
3473 lock (m_primFullUpdateTimer)
3474 m_primFullUpdateTimer.Stop();
3475 3444
3445 lock (m_primTerseUpdates.SyncRoot)
3446 {
3447 int count = Math.Min(m_primTerseUpdates.Count, m_primTerseUpdatesPerPacket);
3448 if (count == 0)
3476 return; 3449 return;
3477 }
3478
3479 ObjectUpdatePacket outPacket =
3480 (ObjectUpdatePacket)PacketPool.Instance.GetPacket(
3481 PacketType.ObjectUpdate);
3482
3483 outPacket.RegionData.RegionHandle =
3484 Scene.RegionInfo.RegionHandle;
3485 outPacket.RegionData.TimeDilation =
3486 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3487 3450
3488 int max = m_primFullUpdates.Count; 3451 outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3489 if (max > m_primFullUpdatesPerPacket) 3452 for (int i = 0; i < count; i++)
3490 max = m_primFullUpdatesPerPacket; 3453 outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
3491 3454 }
3492 int count = 0;
3493 int size = 0;
3494 3455
3495 byte[] zerobuffer = new byte[1024]; 3456 OutPacket(outPacket, ThrottleOutPacketType.State);
3496 byte[] blockbuffer = new byte[1024]; 3457 }
3497 3458
3498 for (count = 0 ; count < max ; count++) 3459 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
3460 {
3461 PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler =
3462 delegate(ref double priority, uint local_id)
3499 { 3463 {
3500 int length = 0; 3464 priority = handler(new UpdatePriorityData(priority, local_id));
3501 m_primFullUpdates[count].ToBytes(blockbuffer, ref length); 3465 return priority != double.NaN;
3502 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3466 };
3503 if (size + length > Packet.MTU) 3467 PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
3504 break; 3468 delegate(ref double priority, uint local_id)
3505 size += length; 3469 {
3506 } 3470 priority = handler(new UpdatePriorityData(priority, local_id));
3471 return priority != double.NaN;
3472 };
3507 3473
3508 outPacket.ObjectData = 3474 if ((type & StateUpdateTypes.AvatarTerse) != 0)
3509 new ObjectUpdatePacket.ObjectDataBlock[count]; 3475 {
3476 lock (m_avatarTerseUpdates.SyncRoot)
3477 m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler);
3478 }
3510 3479
3511 for (int index = 0 ; index < count ; index++) 3480 if ((type & StateUpdateTypes.PrimitiveFull) != 0)
3512 { 3481 {
3513 outPacket.ObjectData[index] = m_primFullUpdates[0]; 3482 lock (m_primFullUpdates.SyncRoot)
3514 m_primFullUpdates.RemoveAt(0); 3483 m_primFullUpdates.Reprioritize(update_priority_handler);
3515 } 3484 }
3516 3485
3517 outPacket.Header.Zerocoded = true; 3486 if ((type & StateUpdateTypes.PrimitiveTerse) != 0)
3518 OutPacket(outPacket, ThrottleOutPacketType.State); 3487 {
3488 lock (m_primTerseUpdates.SyncRoot)
3489 m_primTerseUpdates.Reprioritize(terse_update_priority_handler);
3490 }
3491 }
3519 3492
3520 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) 3493 public void FlushPrimUpdates()
3521 lock (m_primFullUpdateTimer) 3494 {
3522 m_primFullUpdateTimer.Stop(); 3495 while (m_primFullUpdates.Count > 0)
3496 {
3497 ProcessPrimFullUpdates();
3498 }
3499 while (m_primTerseUpdates.Count > 0)
3500 {
3501 ProcessPrimTerseUpdates();
3502 }
3503 while (m_avatarTerseUpdates.Count > 0)
3504 {
3505 ProcessAvatarTerseUpdates();
3523 } 3506 }
3524 } 3507 }
3525 3508
3509 #endregion Primitive Packet/Data Sending Methods
3510
3526 /// <summary> 3511 /// <summary>
3527 /// 3512 ///
3528 /// </summary> 3513 /// </summary>
3529 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 3514 /// <param name="localID"></param>
3530 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) 3515 /// <param name="rotation"></param>
3516 /// <param name="attachPoint"></param>
3517 public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
3531 { 3518 {
3532 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3519 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD
3533 return; 3520 return;
3534 3521
3535 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3522 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach);
3536 rotation = Quaternion.Identity; 3523 // TODO: don't create new blocks if recycling an old packet
3537 3524 attach.AgentData.AgentID = AgentId;
3538 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = 3525 attach.AgentData.SessionID = m_sessionId;
3539 CreatePrimImprovedBlock(localID, position, rotation, 3526 attach.AgentData.AttachmentPoint = attachPoint;
3540 velocity, rotationalvelocity, state); 3527 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
3541 3528 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
3542 lock (m_primTerseUpdates) 3529 attach.ObjectData[0].ObjectLocalID = localID;
3543 { 3530 attach.ObjectData[0].Rotation = rotation;
3544 if (m_primTerseUpdates.Count == 0) 3531 attach.Header.Zerocoded = true;
3545 m_primTerseUpdateTimer.Start(); 3532 OutPacket(attach, ThrottleOutPacketType.Task);
3546
3547 m_primTerseUpdates.Add(objectData);
3548
3549 if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket)
3550 ProcessPrimTerseUpdates(this, null);
3551 }
3552 } 3533 }
3553 3534
3554 void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) 3535 void HandleQueueEmpty(ThrottleOutPacketType queue)
3555 { 3536 {
3556 lock (m_primTerseUpdates) 3537 switch (queue)
3557 { 3538 {
3558 if (m_primTerseUpdates.Count == 0) 3539 case ThrottleOutPacketType.Texture:
3559 { 3540 ProcessTextureRequests();
3560 lock (m_primTerseUpdateTimer) 3541 break;
3561 m_primTerseUpdateTimer.Stop(); 3542 case ThrottleOutPacketType.Task:
3562 3543 if (Monitor.TryEnter(m_avatarTerseUpdates.SyncRoot, 1))
3563 return; 3544 {
3564 } 3545 try
3565 3546 {
3566 ImprovedTerseObjectUpdatePacket outPacket = 3547 if (m_avatarTerseUpdates.Count > 0)
3567 (ImprovedTerseObjectUpdatePacket) 3548 {
3568 PacketPool.Instance.GetPacket(
3569 PacketType.ImprovedTerseObjectUpdate);
3570
3571 outPacket.RegionData.RegionHandle =
3572 Scene.RegionInfo.RegionHandle;
3573 outPacket.RegionData.TimeDilation =
3574 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3575
3576 int max = m_primTerseUpdates.Count;
3577 if (max > m_primTerseUpdatesPerPacket)
3578 max = m_primTerseUpdatesPerPacket;
3579
3580 int count = 0;
3581 int size = 0;
3582
3583 byte[] zerobuffer = new byte[1024];
3584 byte[] blockbuffer = new byte[1024];
3585
3586 for (count = 0 ; count < max ; count++)
3587 {
3588 int length = 0;
3589 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length);
3590 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3591 if (size + length > Packet.MTU)
3592 break;
3593 size += length;
3594 }
3595
3596 outPacket.ObjectData =
3597 new ImprovedTerseObjectUpdatePacket.
3598 ObjectDataBlock[count];
3599
3600 for (int index = 0 ; index < count ; index++)
3601 {
3602 outPacket.ObjectData[index] = m_primTerseUpdates[0];
3603 m_primTerseUpdates.RemoveAt(0);
3604 }
3605 3549
3606 outPacket.Header.Reliable = false; 3550 ProcessAvatarTerseUpdates();
3607 outPacket.Header.Zerocoded = true; 3551 return;
3608 OutPacket(outPacket, ThrottleOutPacketType.State); 3552 }
3553 }
3554 finally { Monitor.Exit(m_avatarTerseUpdates.SyncRoot); }
3555 }
3556 break;
3557 case ThrottleOutPacketType.State:
3558 if (Monitor.TryEnter(m_primFullUpdates.SyncRoot, 1))
3559 {
3560 try
3561 {
3562 if (m_primFullUpdates.Count > 0)
3563 {
3564 ProcessPrimFullUpdates();
3565 return;
3566 }
3567 }
3568 finally { Monitor.Exit(m_primFullUpdates.SyncRoot); }
3569 }
3609 3570
3610 if (m_primTerseUpdates.Count == 0) 3571 if (Monitor.TryEnter(m_primTerseUpdates.SyncRoot, 1))
3611 lock (m_primTerseUpdateTimer) 3572 {
3612 m_primTerseUpdateTimer.Stop(); 3573 try
3574 {
3575 if (m_primTerseUpdates.Count > 0)
3576 {
3577 ProcessPrimTerseUpdates();
3578 return;
3579 }
3580 }
3581 finally { Monitor.Exit(m_primTerseUpdates.SyncRoot); }
3582 }
3583 break;
3613 } 3584 }
3614 } 3585 }
3615 3586
3616 public void FlushPrimUpdates() 3587 void ProcessTextureRequests()
3617 { 3588 {
3618 while (m_primFullUpdates.Count > 0) 3589 if (m_imageManager != null)
3619 { 3590 m_imageManager.ProcessImageQueue(m_textureSendLimit);
3620 ProcessPrimFullUpdates(this, null);
3621 }
3622 while (m_primTerseUpdates.Count > 0)
3623 {
3624 ProcessPrimTerseUpdates(this, null);
3625 }
3626 while (m_avatarTerseUpdates.Count > 0)
3627 {
3628 ProcessAvatarTerseUpdates(this, null);
3629 }
3630 } 3591 }
3631 3592
3632 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 3593 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
@@ -3810,8 +3771,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3810 OutPacket(proper, ThrottleOutPacketType.Task); 3771 OutPacket(proper, ThrottleOutPacketType.Task);
3811 } 3772 }
3812 3773
3813 #endregion
3814
3815 #region Estate Data Sending Methods 3774 #region Estate Data Sending Methods
3816 3775
3817 private static bool convertParamStringToBool(byte[] field) 3776 private static bool convertParamStringToBool(byte[] field)
@@ -4218,325 +4177,221 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4218 4177
4219 #region Helper Methods 4178 #region Helper Methods
4220 4179
4221 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, 4180 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data)
4222 Vector3 velocity,
4223 Quaternion rotation)
4224 { 4181 {
4225 byte[] bytes = new byte[60]; 4182 return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity,
4226 int i = 0; 4183 data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
4227 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4228
4229 dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry;
4230
4231 uint ID = localID;
4232
4233 bytes[i++] = (byte)(ID % 256);
4234 bytes[i++] = (byte)((ID >> 8) % 256);
4235 bytes[i++] = (byte)((ID >> 16) % 256);
4236 bytes[i++] = (byte)((ID >> 24) % 256);
4237 bytes[i++] = 0;
4238 bytes[i++] = 1;
4239 i += 14;
4240 bytes[i++] = 128;
4241 bytes[i++] = 63;
4242
4243 byte[] pb = pos.GetBytes();
4244 Array.Copy(pb, 0, bytes, i, pb.Length);
4245 i += 12;
4246
4247 Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z);
4248
4249 internDirec = internDirec / 128.0f;
4250 internDirec.X += 1;
4251 internDirec.Y += 1;
4252 internDirec.Z += 1;
4253
4254 ushort InternVelocityX = (ushort)(32768 * internDirec.X);
4255 ushort InternVelocityY = (ushort)(32768 * internDirec.Y);
4256 ushort InternVelocityZ = (ushort)(32768 * internDirec.Z);
4257
4258 ushort ac = 32767;
4259 bytes[i++] = (byte)(InternVelocityX % 256);
4260 bytes[i++] = (byte)((InternVelocityX >> 8) % 256);
4261 bytes[i++] = (byte)(InternVelocityY % 256);
4262 bytes[i++] = (byte)((InternVelocityY >> 8) % 256);
4263 bytes[i++] = (byte)(InternVelocityZ % 256);
4264 bytes[i++] = (byte)((InternVelocityZ >> 8) % 256);
4265
4266 //accel
4267 bytes[i++] = (byte)(ac % 256);
4268 bytes[i++] = (byte)((ac >> 8) % 256);
4269 bytes[i++] = (byte)(ac % 256);
4270 bytes[i++] = (byte)((ac >> 8) % 256);
4271 bytes[i++] = (byte)(ac % 256);
4272 bytes[i++] = (byte)((ac >> 8) % 256);
4273
4274 //rotation
4275 ushort rw, rx, ry, rz;
4276 rw = (ushort)(32768 * (rotation.W + 1));
4277 rx = (ushort)(32768 * (rotation.X + 1));
4278 ry = (ushort)(32768 * (rotation.Y + 1));
4279 rz = (ushort)(32768 * (rotation.Z + 1));
4280
4281 //rot
4282 bytes[i++] = (byte)(rx % 256);
4283 bytes[i++] = (byte)((rx >> 8) % 256);
4284 bytes[i++] = (byte)(ry % 256);
4285 bytes[i++] = (byte)((ry >> 8) % 256);
4286 bytes[i++] = (byte)(rz % 256);
4287 bytes[i++] = (byte)((rz >> 8) % 256);
4288 bytes[i++] = (byte)(rw % 256);
4289 bytes[i++] = (byte)((rw >> 8) % 256);
4290
4291 //rotation vel
4292 bytes[i++] = (byte)(ac % 256);
4293 bytes[i++] = (byte)((ac >> 8) % 256);
4294 bytes[i++] = (byte)(ac % 256);
4295 bytes[i++] = (byte)((ac >> 8) % 256);
4296 bytes[i++] = (byte)(ac % 256);
4297 bytes[i++] = (byte)((ac >> 8) % 256);
4298
4299 dat.Data = bytes;
4300
4301 return (dat);
4302 } 4184 }
4303 4185
4304 /// <summary> 4186 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data)
4305 ///
4306 /// </summary>
4307 /// <param name="localID"></param>
4308 /// <param name="position"></param>
4309 /// <param name="rotation"></param>
4310 /// <returns></returns>
4311 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID,
4312 Vector3 position,
4313 Quaternion rotation,
4314 Vector3 velocity,
4315 Vector3 rotationalvelocity,
4316 byte state)
4317 { 4187 {
4318 uint ID = localID; 4188 return CreateImprovedTerseBlock(false, data.LocalID, data.State, Vector4.Zero, data.Position, data.Velocity,
4319 byte[] bytes = new byte[60]; 4189 data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry);
4320
4321 int i = 0;
4322 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4323 dat.TextureEntry = new byte[0];
4324 bytes[i++] = (byte)(ID % 256);
4325 bytes[i++] = (byte)((ID >> 8) % 256);
4326 bytes[i++] = (byte)((ID >> 16) % 256);
4327 bytes[i++] = (byte)((ID >> 24) % 256);
4328 bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4));
4329 bytes[i++] = 0;
4330
4331 byte[] pb = position.GetBytes();
4332 Array.Copy(pb, 0, bytes, i, pb.Length);
4333 i += 12;
4334 ushort ac = 32767;
4335
4336 ushort velx, vely, velz;
4337 Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z);
4338
4339 vel = vel / 128.0f;
4340 vel.X += 1;
4341 vel.Y += 1;
4342 vel.Z += 1;
4343 //vel
4344 velx = (ushort)(32768 * (vel.X));
4345 vely = (ushort)(32768 * (vel.Y));
4346 velz = (ushort)(32768 * (vel.Z));
4347
4348 bytes[i++] = (byte)(velx % 256);
4349 bytes[i++] = (byte)((velx >> 8) % 256);
4350 bytes[i++] = (byte)(vely % 256);
4351 bytes[i++] = (byte)((vely >> 8) % 256);
4352 bytes[i++] = (byte)(velz % 256);
4353 bytes[i++] = (byte)((velz >> 8) % 256);
4354
4355 //accel
4356 bytes[i++] = (byte)(ac % 256);
4357 bytes[i++] = (byte)((ac >> 8) % 256);
4358 bytes[i++] = (byte)(ac % 256);
4359 bytes[i++] = (byte)((ac >> 8) % 256);
4360 bytes[i++] = (byte)(ac % 256);
4361 bytes[i++] = (byte)((ac >> 8) % 256);
4362
4363 ushort rw, rx, ry, rz;
4364 rw = (ushort)(32768 * (rotation.W + 1));
4365 rx = (ushort)(32768 * (rotation.X + 1));
4366 ry = (ushort)(32768 * (rotation.Y + 1));
4367 rz = (ushort)(32768 * (rotation.Z + 1));
4368
4369 //rot
4370 bytes[i++] = (byte)(rx % 256);
4371 bytes[i++] = (byte)((rx >> 8) % 256);
4372 bytes[i++] = (byte)(ry % 256);
4373 bytes[i++] = (byte)((ry >> 8) % 256);
4374 bytes[i++] = (byte)(rz % 256);
4375 bytes[i++] = (byte)((rz >> 8) % 256);
4376 bytes[i++] = (byte)(rw % 256);
4377 bytes[i++] = (byte)((rw >> 8) % 256);
4378
4379 //rotation vel
4380 Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z);
4381
4382 rvel = rvel / 128.0f;
4383 rvel.X += 1;
4384 rvel.Y += 1;
4385 rvel.Z += 1;
4386 //vel
4387 ushort rvelx = (ushort)(32768 * (rvel.X));
4388 ushort rvely = (ushort)(32768 * (rvel.Y));
4389 ushort rvelz = (ushort)(32768 * (rvel.Z));
4390
4391 bytes[i++] = (byte)(rvelx % 256);
4392 bytes[i++] = (byte)((rvelx >> 8) % 256);
4393 bytes[i++] = (byte)(rvely % 256);
4394 bytes[i++] = (byte)((rvely >> 8) % 256);
4395 bytes[i++] = (byte)(rvelz % 256);
4396 bytes[i++] = (byte)((rvelz >> 8) % 256);
4397 dat.Data = bytes;
4398
4399 return dat;
4400 } 4190 }
4401 4191
4402 /// <summary> 4192 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, byte state,
4403 /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) 4193 Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
4404 /// </summary> 4194 Vector3 angularVelocity, byte[] textureEntry)
4405 /// <param name="primData"></param> 4195 {
4406 /// <returns></returns> 4196 int pos = 0;
4407 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) 4197 byte[] data = new byte[(avatar ? 60 : 44)];
4408 {
4409 ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock<ObjectUpdatePacket.ObjectDataBlock>();
4410 SetDefaultPrimPacketValues(objupdate);
4411 objupdate.UpdateFlags = flags;
4412 SetPrimPacketShapeData(objupdate, primShape);
4413
4414 if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass))
4415 {
4416 objupdate.Data = new byte[1];
4417 objupdate.Data[0] = primShape.State;
4418 }
4419 return objupdate;
4420 }
4421
4422 protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData)
4423 {
4424 objectData.TextureEntry = primData.TextureEntry;
4425 objectData.PCode = primData.PCode;
4426 objectData.State = primData.State;
4427 objectData.PathBegin = primData.PathBegin;
4428 objectData.PathEnd = primData.PathEnd;
4429 objectData.PathScaleX = primData.PathScaleX;
4430 objectData.PathScaleY = primData.PathScaleY;
4431 objectData.PathShearX = primData.PathShearX;
4432 objectData.PathShearY = primData.PathShearY;
4433 objectData.PathSkew = primData.PathSkew;
4434 objectData.ProfileBegin = primData.ProfileBegin;
4435 objectData.ProfileEnd = primData.ProfileEnd;
4436 objectData.Scale = primData.Scale;
4437 objectData.PathCurve = primData.PathCurve;
4438 objectData.ProfileCurve = primData.ProfileCurve;
4439 objectData.ProfileHollow = primData.ProfileHollow;
4440 objectData.PathRadiusOffset = primData.PathRadiusOffset;
4441 objectData.PathRevolutions = primData.PathRevolutions;
4442 objectData.PathTaperX = primData.PathTaperX;
4443 objectData.PathTaperY = primData.PathTaperY;
4444 objectData.PathTwist = primData.PathTwist;
4445 objectData.PathTwistBegin = primData.PathTwistBegin;
4446 objectData.ExtraParams = primData.ExtraParams;
4447 }
4448 4198
4449 /// <summary> 4199 // LocalID
4450 /// Set some default values in a ObjectUpdatePacket 4200 Utils.UIntToBytes(localID, data, pos);
4451 /// </summary> 4201 pos += 4;
4452 /// <param name="objdata"></param>
4453 protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata)
4454 {
4455 objdata.PSBlock = new byte[0];
4456 objdata.ExtraParams = new byte[1];
4457 objdata.MediaURL = new byte[0];
4458 objdata.NameValue = new byte[0];
4459 objdata.Text = new byte[0];
4460 objdata.TextColor = new byte[4];
4461 objdata.JointAxisOrAnchor = new Vector3(0, 0, 0);
4462 objdata.JointPivot = new Vector3(0, 0, 0);
4463 objdata.Material = 3;
4464 objdata.TextureAnim = new byte[0];
4465 objdata.Sound = UUID.Zero;
4466 objdata.State = 0;
4467 objdata.Data = new byte[0];
4468
4469 objdata.ObjectData = new byte[60];
4470 objdata.ObjectData[46] = 128;
4471 objdata.ObjectData[47] = 63;
4472 }
4473 4202
4474 /// <summary> 4203 // Avatar/CollisionPlane
4475 /// 4204 data[pos++] = state;
4476 /// </summary> 4205 if (avatar)
4477 /// <returns></returns> 4206 {
4478 public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) 4207 data[pos++] = 1;
4479 {
4480 ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock<ObjectUpdatePacket.ObjectDataBlock>();
4481 // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i);
4482 4208
4483 SetDefaultAvatarPacketValues(ref objdata); 4209 if (collisionPlane == Vector4.Zero)
4484 objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); 4210 collisionPlane = Vector4.UnitW;
4485 objdata.PathCurve = 16; 4211
4486 objdata.ProfileCurve = 1; 4212 collisionPlane.ToBytes(data, pos);
4487 objdata.PathScaleX = 100; 4213 pos += 16;
4488 objdata.PathScaleY = 100; 4214 }
4489 objdata.ParentID = 0; 4215 else
4490 objdata.OwnerID = UUID.Zero;
4491 objdata.Scale = new Vector3(1, 1, 1);
4492 objdata.PCode = (byte)PCode.Avatar;
4493 if (textureEntry != null)
4494 { 4216 {
4495 objdata.TextureEntry = textureEntry; 4217 ++pos;
4496 } 4218 }
4497 Vector3 pos = new Vector3(objdata.ObjectData, 16);
4498 pos.X = 100f;
4499 objdata.ID = 8880000;
4500 objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User ");
4501 //Vector3 pos2 = new Vector3(100f, 100f, 23f);
4502 //objdata.FullID=user.AgentId;
4503 byte[] pb = pos.GetBytes();
4504 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
4505 4219
4506 return objdata; 4220 // Position
4507 } 4221 position.ToBytes(data, pos);
4222 pos += 12;
4508 4223
4509 /// <summary> 4224 // Velocity
4510 /// 4225 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2;
4511 /// </summary> 4226 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2;
4512 /// <param name="objdata"></param> 4227 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2;
4513 protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) 4228
4514 { 4229 // Acceleration
4515 objdata.PSBlock = new byte[0]; 4230 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2;
4516 objdata.ExtraParams = new byte[1]; 4231 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2;
4517 objdata.MediaURL = new byte[0]; 4232 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2;
4518 objdata.NameValue = new byte[0]; 4233
4519 objdata.Text = new byte[0]; 4234 // Rotation
4520 objdata.TextColor = new byte[4]; 4235 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.X, -1.0f, 1.0f), data, pos); pos += 2;
4521 objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); 4236 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Y, -1.0f, 1.0f), data, pos); pos += 2;
4522 objdata.JointPivot = new Vector3(0, 0, 0); 4237 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Z, -1.0f, 1.0f), data, pos); pos += 2;
4523 objdata.Material = 4; 4238 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2;
4524 objdata.TextureAnim = new byte[0]; 4239
4525 objdata.Sound = UUID.Zero; 4240 // Angular Velocity
4526 Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); 4241 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2;
4527 objdata.TextureEntry = ntex.GetBytes(); 4242 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
4528 4243 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
4529 objdata.State = 0; 4244
4530 objdata.Data = new byte[0]; 4245 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
4531 4246 block.Data = data;
4532 objdata.ObjectData = new byte[76]; 4247
4533 objdata.ObjectData[15] = 128; 4248 if (textureEntry != null && textureEntry.Length > 0)
4534 objdata.ObjectData[16] = 63; 4249 {
4535 objdata.ObjectData[56] = 128; 4250 byte[] teBytesFinal = new byte[textureEntry.Length + 4];
4536 objdata.ObjectData[61] = 102; 4251
4537 objdata.ObjectData[62] = 40; 4252 // Texture Length
4538 objdata.ObjectData[63] = 61; 4253 Utils.IntToBytes(textureEntry.Length, textureEntry, 0);
4539 objdata.ObjectData[64] = 189; 4254 // Texture
4255 Buffer.BlockCopy(textureEntry, 0, teBytesFinal, 4, textureEntry.Length);
4256
4257 block.TextureEntry = teBytesFinal;
4258 }
4259 else
4260 {
4261 block.TextureEntry = Utils.EmptyBytes;
4262 }
4263
4264 return block;
4265 }
4266
4267 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data)
4268 {
4269 byte[] objectData = new byte[60];
4270 data.Position.ToBytes(objectData, 0);
4271 //data.Velocity.ToBytes(objectData, 12);
4272 //data.Acceleration.ToBytes(objectData, 24);
4273 data.Rotation.ToBytes(objectData, 36);
4274 //data.AngularVelocity.ToBytes(objectData, 48);
4275
4276 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4277
4278 update.Data = Utils.EmptyBytes;
4279 update.ExtraParams = new byte[1];
4280 update.FullID = data.AvatarID;
4281 update.ID = data.AvatarLocalID;
4282 update.Material = (byte)Material.Flesh;
4283 update.MediaURL = Utils.EmptyBytes;
4284 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " +
4285 data.LastName + "\nTitle STRING RW SV " + data.GroupTitle);
4286 update.ObjectData = objectData;
4287 update.ParentID = data.ParentID;
4288 update.PathCurve = 16;
4289 update.PathScaleX = 100;
4290 update.PathScaleY = 100;
4291 update.PCode = (byte)PCode.Avatar;
4292 update.ProfileCurve = 1;
4293 update.PSBlock = Utils.EmptyBytes;
4294 update.Scale = Vector3.One;
4295 update.Text = Utils.EmptyBytes;
4296 update.TextColor = new byte[4];
4297 update.TextureAnim = Utils.EmptyBytes;
4298 update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes;
4299 update.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags
4300
4301 return update;
4302 }
4303
4304 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data)
4305 {
4306 byte[] objectData = new byte[60];
4307 data.pos.ToBytes(objectData, 0);
4308 data.vel.ToBytes(objectData, 12);
4309 data.acc.ToBytes(objectData, 24);
4310 data.rotation.ToBytes(objectData, 36);
4311 data.rvel.ToBytes(objectData, 48);
4312
4313 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4314 update.ClickAction = (byte)data.clickAction;
4315 update.CRC = 0;
4316 update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes;
4317 update.FullID = data.objectID;
4318 update.ID = data.localID;
4319 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
4320 //update.JointPivot = Vector3.Zero;
4321 //update.JointType = 0;
4322 update.Material = data.material;
4323 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
4324 if (data.attachment)
4325 {
4326 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId);
4327 update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16));
4328 }
4329 else
4330 {
4331 update.NameValue = Utils.EmptyBytes;
4332 update.State = data.primShape.State;
4333 }
4334 update.ObjectData = objectData;
4335 update.ParentID = data.parentID;
4336 update.PathBegin = data.primShape.PathBegin;
4337 update.PathCurve = data.primShape.PathCurve;
4338 update.PathEnd = data.primShape.PathEnd;
4339 update.PathRadiusOffset = data.primShape.PathRadiusOffset;
4340 update.PathRevolutions = data.primShape.PathRevolutions;
4341 update.PathScaleX = data.primShape.PathScaleX;
4342 update.PathScaleY = data.primShape.PathScaleY;
4343 update.PathShearX = data.primShape.PathShearX;
4344 update.PathShearY = data.primShape.PathShearY;
4345 update.PathSkew = data.primShape.PathSkew;
4346 update.PathTaperX = data.primShape.PathTaperX;
4347 update.PathTaperY = data.primShape.PathTaperY;
4348 update.PathTwist = data.primShape.PathTwist;
4349 update.PathTwistBegin = data.primShape.PathTwistBegin;
4350 update.PCode = data.primShape.PCode;
4351 update.ProfileBegin = data.primShape.ProfileBegin;
4352 update.ProfileCurve = data.primShape.ProfileCurve;
4353 update.ProfileEnd = data.primShape.ProfileEnd;
4354 update.ProfileHollow = data.primShape.ProfileHollow;
4355 update.PSBlock = data.particleSystem ?? Utils.EmptyBytes;
4356 update.TextColor = data.color ?? Color4.Black.GetBytes(true);
4357 update.TextureAnim = data.textureanim ?? Utils.EmptyBytes;
4358 update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes;
4359 update.Scale = data.primShape.Scale;
4360 update.Text = Util.StringToBytes256(data.text);
4361 update.UpdateFlags = (uint)data.flags;
4362
4363 if (data.SoundId != UUID.Zero)
4364 {
4365 update.Sound = data.SoundId;
4366 update.OwnerID = data.ownerID;
4367 update.Gain = (float)data.SoundVolume;
4368 update.Radius = (float)data.SoundRadius;
4369 update.Flags = data.SoundFlags;
4370 }
4371
4372 switch ((PCode)data.primShape.PCode)
4373 {
4374 case PCode.Grass:
4375 case PCode.Tree:
4376 case PCode.NewTree:
4377 update.Data = new byte[] { data.primShape.State };
4378 break;
4379 default:
4380 // TODO: Support ScratchPad
4381 //if (prim.ScratchPad != null)
4382 //{
4383 // update.Data = new byte[prim.ScratchPad.Length];
4384 // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length);
4385 //}
4386 //else
4387 //{
4388 // update.Data = Utils.EmptyBytes;
4389 //}
4390 update.Data = Utils.EmptyBytes;
4391 break;
4392 }
4393
4394 return update;
4540 } 4395 }
4541 4396
4542 public void SendNameReply(UUID profileId, string firstname, string lastname) 4397 public void SendNameReply(UUID profileId, string firstname, string lastname)
@@ -4546,8 +4401,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4546 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; 4401 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
4547 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); 4402 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
4548 packet.UUIDNameBlock[0].ID = profileId; 4403 packet.UUIDNameBlock[0].ID = profileId;
4549 packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); 4404 packet.UUIDNameBlock[0].FirstName = Util.StringToBytes256(firstname);
4550 packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); 4405 packet.UUIDNameBlock[0].LastName = Util.StringToBytes256(lastname);
4551 4406
4552 OutPacket(packet, ThrottleOutPacketType.Task); 4407 OutPacket(packet, ThrottleOutPacketType.Task);
4553 } 4408 }
@@ -4743,8 +4598,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4743 scriptQuestion.Data.TaskID = taskID; 4598 scriptQuestion.Data.TaskID = taskID;
4744 scriptQuestion.Data.ItemID = itemID; 4599 scriptQuestion.Data.ItemID = itemID;
4745 scriptQuestion.Data.Questions = question; 4600 scriptQuestion.Data.Questions = question;
4746 scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); 4601 scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName);
4747 scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); 4602 scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName);
4748 4603
4749 OutPacket(scriptQuestion, ThrottleOutPacketType.Task); 4604 OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
4750 } 4605 }
@@ -5138,7 +4993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5138 if (m_moneyBalance + debit >= 0) 4993 if (m_moneyBalance + debit >= 0)
5139 { 4994 {
5140 m_moneyBalance += debit; 4995 m_moneyBalance += debit;
5141 SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); 4996 SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance);
5142 return true; 4997 return true;
5143 } 4998 }
5144 return false; 4999 return false;
@@ -8736,19 +8591,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8736 8591
8737 #endregion 8592 #endregion
8738 8593
8594 case PacketType.AgentFOV:
8595 AgentFOVPacket fovPacket = (AgentFOVPacket)Pack;
8739 8596
8740 #region unimplemented handlers 8597 if (fovPacket.FOVBlock.GenCounter > m_agentFOVCounter)
8741 8598 {
8742 case PacketType.StartPingCheck: 8599 m_agentFOVCounter = fovPacket.FOVBlock.GenCounter;
8743 StartPingCheckPacket pingStart = (StartPingCheckPacket)Pack; 8600 AgentFOV handlerAgentFOV = OnAgentFOV;
8744 CompletePingCheckPacket pingComplete = new CompletePingCheckPacket(); 8601 if (handlerAgentFOV != null)
8745 pingComplete.PingID.PingID = pingStart.PingID.PingID; 8602 {
8746 m_udpServer.SendPacket(m_udpClient, pingComplete, ThrottleOutPacketType.Unknown, false); 8603 handlerAgentFOV(this, fovPacket.FOVBlock.VerticalAngle);
8604 }
8605 }
8747 break; 8606 break;
8748 8607
8749 case PacketType.CompletePingCheck: 8608 #region unimplemented handlers
8750 // TODO: Do stats tracking or something with these?
8751 break;
8752 8609
8753 case PacketType.ViewerStats: 8610 case PacketType.ViewerStats:
8754 // TODO: handle this packet 8611 // TODO: handle this packet
@@ -9080,7 +8937,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9080 new GroupTitlesReplyPacket.GroupDataBlock(); 8937 new GroupTitlesReplyPacket.GroupDataBlock();
9081 8938
9082 groupTitlesReply.GroupData[i].Title = 8939 groupTitlesReply.GroupData[i].Title =
9083 Utils.StringToBytes(d.Name); 8940 Util.StringToBytes256(d.Name);
9084 groupTitlesReply.GroupData[i].RoleID = 8941 groupTitlesReply.GroupData[i].RoleID =
9085 d.UUID; 8942 d.UUID;
9086 groupTitlesReply.GroupData[i].Selected = 8943 groupTitlesReply.GroupData[i].Selected =
@@ -9117,10 +8974,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9117 groupProfileRequest.GroupData.GroupID); 8974 groupProfileRequest.GroupData.GroupID);
9118 8975
9119 groupProfileReply.GroupData.GroupID = d.GroupID; 8976 groupProfileReply.GroupData.GroupID = d.GroupID;
9120 groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); 8977 groupProfileReply.GroupData.Name = Util.StringToBytes256(d.Name);
9121 groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); 8978 groupProfileReply.GroupData.Charter = Util.StringToBytes1024(d.Charter);
9122 groupProfileReply.GroupData.ShowInList = d.ShowInList; 8979 groupProfileReply.GroupData.ShowInList = d.ShowInList;
9123 groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); 8980 groupProfileReply.GroupData.MemberTitle = Util.StringToBytes256(d.MemberTitle);
9124 groupProfileReply.GroupData.PowersMask = d.PowersMask; 8981 groupProfileReply.GroupData.PowersMask = d.PowersMask;
9125 groupProfileReply.GroupData.InsigniaID = d.InsigniaID; 8982 groupProfileReply.GroupData.InsigniaID = d.InsigniaID;
9126 groupProfileReply.GroupData.FounderID = d.FounderID; 8983 groupProfileReply.GroupData.FounderID = d.FounderID;
@@ -9192,11 +9049,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9192 groupMembersReply.MemberData[i].Contribution = 9049 groupMembersReply.MemberData[i].Contribution =
9193 m.Contribution; 9050 m.Contribution;
9194 groupMembersReply.MemberData[i].OnlineStatus = 9051 groupMembersReply.MemberData[i].OnlineStatus =
9195 Utils.StringToBytes(m.OnlineStatus); 9052 Util.StringToBytes256(m.OnlineStatus);
9196 groupMembersReply.MemberData[i].AgentPowers = 9053 groupMembersReply.MemberData[i].AgentPowers =
9197 m.AgentPowers; 9054 m.AgentPowers;
9198 groupMembersReply.MemberData[i].Title = 9055 groupMembersReply.MemberData[i].Title =
9199 Utils.StringToBytes(m.Title); 9056 Util.StringToBytes256(m.Title);
9200 groupMembersReply.MemberData[i].IsOwner = 9057 groupMembersReply.MemberData[i].IsOwner =
9201 m.IsOwner; 9058 m.IsOwner;
9202 } 9059 }
@@ -9257,11 +9114,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9257 groupRolesReply.RoleData[i].RoleID = 9114 groupRolesReply.RoleData[i].RoleID =
9258 d.RoleID; 9115 d.RoleID;
9259 groupRolesReply.RoleData[i].Name = 9116 groupRolesReply.RoleData[i].Name =
9260 Utils.StringToBytes(d.Name); 9117 Util.StringToBytes256(d.Name);
9261 groupRolesReply.RoleData[i].Title = 9118 groupRolesReply.RoleData[i].Title =
9262 Utils.StringToBytes(d.Title); 9119 Util.StringToBytes256(d.Title);
9263 groupRolesReply.RoleData[i].Description = 9120 groupRolesReply.RoleData[i].Description =
9264 Utils.StringToBytes(d.Description); 9121 Util.StringToBytes1024(d.Description);
9265 groupRolesReply.RoleData[i].Powers = 9122 groupRolesReply.RoleData[i].Powers =
9266 d.Powers; 9123 d.Powers;
9267 groupRolesReply.RoleData[i].Members = 9124 groupRolesReply.RoleData[i].Members =
@@ -9488,9 +9345,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9488 groupNoticesListReply.Data[i].Timestamp = 9345 groupNoticesListReply.Data[i].Timestamp =
9489 g.Timestamp; 9346 g.Timestamp;
9490 groupNoticesListReply.Data[i].FromName = 9347 groupNoticesListReply.Data[i].FromName =
9491 Utils.StringToBytes(g.FromName); 9348 Util.StringToBytes256(g.FromName);
9492 groupNoticesListReply.Data[i].Subject = 9349 groupNoticesListReply.Data[i].Subject =
9493 Utils.StringToBytes(g.Subject); 9350 Util.StringToBytes256(g.Subject);
9494 groupNoticesListReply.Data[i].HasAttachment = 9351 groupNoticesListReply.Data[i].HasAttachment =
9495 g.HasAttachment; 9352 g.HasAttachment;
9496 groupNoticesListReply.Data[i].AssetType = 9353 groupNoticesListReply.Data[i].AssetType =
@@ -10089,12 +9946,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10089 byte mediaLoop) 9946 byte mediaLoop)
10090 { 9947 {
10091 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); 9948 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket();
10092 updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); 9949 updatePacket.DataBlock.MediaURL = Util.StringToBytes256(mediaUrl);
10093 updatePacket.DataBlock.MediaID = mediaTextureID; 9950 updatePacket.DataBlock.MediaID = mediaTextureID;
10094 updatePacket.DataBlock.MediaAutoScale = autoScale; 9951 updatePacket.DataBlock.MediaAutoScale = autoScale;
10095 9952
10096 updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); 9953 updatePacket.DataBlockExtended.MediaType = Util.StringToBytes256(mediaType);
10097 updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); 9954 updatePacket.DataBlockExtended.MediaDesc = Util.StringToBytes256(mediaDesc);
10098 updatePacket.DataBlockExtended.MediaWidth = mediaWidth; 9955 updatePacket.DataBlockExtended.MediaWidth = mediaWidth;
10099 updatePacket.DataBlockExtended.MediaHeight = mediaHeight; 9956 updatePacket.DataBlockExtended.MediaHeight = mediaHeight;
10100 updatePacket.DataBlockExtended.MediaLoop = mediaLoop; 9957 updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
@@ -10371,5 +10228,166 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10371 pack.TextureData.TextureID = textureID; 10228 pack.TextureData.TextureID = textureID;
10372 OutPacket(pack, ThrottleOutPacketType.Task); 10229 OutPacket(pack, ThrottleOutPacketType.Task);
10373 } 10230 }
10231
10232 #region PriorityQueue
10233 private class PriorityQueue<TPriority, TValue>
10234 {
10235 internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id);
10236
10237 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
10238 private Dictionary<uint, LookupItem> m_lookupTable;
10239 private Comparison<TPriority> m_comparison;
10240 private object m_syncRoot = new object();
10241
10242 internal PriorityQueue() :
10243 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<TPriority>.Default) { }
10244 internal PriorityQueue(int capacity) :
10245 this(capacity, Comparer<TPriority>.Default) { }
10246 internal PriorityQueue(IComparer<TPriority> comparer) :
10247 this(new Comparison<TPriority>(comparer.Compare)) { }
10248 internal PriorityQueue(Comparison<TPriority> comparison) :
10249 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
10250 internal PriorityQueue(int capacity, IComparer<TPriority> comparer) :
10251 this(capacity, new Comparison<TPriority>(comparer.Compare)) { }
10252 internal PriorityQueue(int capacity, Comparison<TPriority> comparison)
10253 {
10254 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
10255
10256 for (int i = 0; i < m_heaps.Length; ++i)
10257 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
10258 this.m_comparison = comparison;
10259 }
10260
10261 internal object SyncRoot { get { return this.m_syncRoot; } }
10262 internal int Count
10263 {
10264 get
10265 {
10266 int count = 0;
10267 for (int i = 0; i < m_heaps.Length; ++i)
10268 count = m_heaps[i].Count;
10269 return count;
10270 }
10271 }
10272
10273 internal bool Enqueue(TPriority priority, TValue value, uint local_id)
10274 {
10275 LookupItem item;
10276
10277 if (m_lookupTable.TryGetValue(local_id, out item))
10278 {
10279 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
10280 return false;
10281 }
10282 else
10283 {
10284 item.Heap = m_heaps[0];
10285 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
10286 m_lookupTable.Add(local_id, item);
10287 return true;
10288 }
10289 }
10290
10291 internal TValue Peek()
10292 {
10293 for (int i = 0; i < m_heaps.Length; ++i)
10294 if (m_heaps[i].Count > 0)
10295 return m_heaps[i].Min().Value;
10296 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10297 }
10298
10299 internal TValue Dequeue()
10300 {
10301 for (int i = 0; i < m_heaps.Length; ++i)
10302 {
10303 if (m_heaps[i].Count > 0)
10304 {
10305 MinHeapItem item = m_heaps[i].RemoveMin();
10306 m_lookupTable.Remove(item.LocalID);
10307 return item.Value;
10308 }
10309 }
10310 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10311 }
10312
10313 internal void Reprioritize(UpdatePriorityHandler handler)
10314 {
10315 MinHeapItem item;
10316 TPriority priority;
10317
10318 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
10319 {
10320 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
10321 {
10322 priority = item.Priority;
10323 if (handler(ref priority, item.LocalID))
10324 {
10325 if (lookup.Heap.ContainsHandle(lookup.Handle))
10326 lookup.Heap[lookup.Handle] =
10327 new MinHeapItem(priority, item.Value, item.LocalID);
10328 }
10329 else
10330 {
10331 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
10332 lookup.Heap.Remove(lookup.Handle);
10333 this.m_lookupTable.Remove(item.LocalID);
10334 }
10335 }
10336 }
10337 }
10338
10339 #region MinHeapItem
10340 private struct MinHeapItem : IComparable<MinHeapItem>
10341 {
10342 private TPriority priority;
10343 private TValue value;
10344 private uint local_id;
10345 private Comparison<TPriority> comparison;
10346
10347 internal MinHeapItem(TPriority priority, TValue value, uint local_id) :
10348 this(priority, value, local_id, Comparer<TPriority>.Default) { }
10349 internal MinHeapItem(TPriority priority, TValue value, uint local_id, IComparer<TPriority> comparer) :
10350 this(priority, value, local_id, new Comparison<TPriority>(comparer.Compare)) { }
10351 internal MinHeapItem(TPriority priority, TValue value, uint local_id, Comparison<TPriority> comparison)
10352 {
10353 this.priority = priority;
10354 this.value = value;
10355 this.local_id = local_id;
10356 this.comparison = comparison;
10357 }
10358
10359 internal TPriority Priority { get { return this.priority; } }
10360 internal TValue Value { get { return this.value; } }
10361 internal uint LocalID { get { return this.local_id; } }
10362
10363 public override string ToString()
10364 {
10365 StringBuilder sb = new StringBuilder();
10366 sb.Append("[");
10367 if (this.priority != null)
10368 sb.Append(this.priority.ToString());
10369 sb.Append(",");
10370 if (this.value != null)
10371 sb.Append(this.value.ToString());
10372 sb.Append("]");
10373 return sb.ToString();
10374 }
10375
10376 public int CompareTo(MinHeapItem other)
10377 {
10378 return this.comparison(this.priority, other.priority);
10379 }
10380 }
10381 #endregion
10382
10383 #region LookupItem
10384 private struct LookupItem {
10385 internal MinHeap<MinHeapItem> Heap;
10386 internal IHandle Handle;
10387 }
10388 #endregion
10389 }
10390 #endregion
10391
10374 } 10392 }
10375} 10393}