aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/ClientStack
diff options
context:
space:
mode:
authorJohn Hurliman2009-10-15 16:35:27 -0700
committerJohn Hurliman2009-10-15 16:35:27 -0700
commit4b75353cbf50de3cae4c48ec90b55f30c1612c92 (patch)
tree2b5bf30d2a0c8558437f757e28081cb60a8b5dfc /OpenSim/Region/ClientStack
parentReplaced the update lists with a priority queue implementation in LLClientView (diff)
downloadopensim-SC-4b75353cbf50de3cae4c48ec90b55f30c1612c92.zip
opensim-SC-4b75353cbf50de3cae4c48ec90b55f30c1612c92.tar.gz
opensim-SC-4b75353cbf50de3cae4c48ec90b55f30c1612c92.tar.bz2
opensim-SC-4b75353cbf50de3cae4c48ec90b55f30c1612c92.tar.xz
Object update prioritization by Jim Greensky of Intel Labs, part one. This implements a simple distance prioritizer based on initial agent positions. Re-prioritizing and more advanced priority algorithms will follow soon
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs344
1 files changed, 135 insertions, 209 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 93fdeef..0a7d923 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -320,14 +320,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
320 private readonly IGroupsModule m_GroupsModule; 320 private readonly IGroupsModule m_GroupsModule;
321 321
322 private int m_cachedTextureSerial; 322 private int m_cachedTextureSerial;
323 private Timer m_avatarTerseUpdateTimer; 323 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates =
324 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates_ =
325 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 324 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
326 private Timer m_primTerseUpdateTimer; 325 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates =
327 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates_ =
328 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 326 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
329 private Timer m_primFullUpdateTimer; 327 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates =
330 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates_ =
331 new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(); 328 new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>();
332 private int m_moneyBalance; 329 private int m_moneyBalance;
333 private int m_animationSequenceNumber = 1; 330 private int m_animationSequenceNumber = 1;
@@ -353,9 +350,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
353 // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet 350 // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet
354 protected int m_primTerseUpdatesPerPacket = 10; 351 protected int m_primTerseUpdatesPerPacket = 10;
355 protected int m_primFullUpdatesPerPacket = 14; 352 protected int m_primFullUpdatesPerPacket = 14;
356 protected int m_primTerseUpdateRate = 10;
357 protected int m_primFullUpdateRate = 14;
358 protected int m_avatarTerseUpdateRate = 50;
359 protected int m_avatarTerseUpdatesPerPacket = 5; 353 protected int m_avatarTerseUpdatesPerPacket = 5;
360 /// <summary>Number of texture packets to put on the queue each time the 354 /// <summary>Number of texture packets to put on the queue each time the
361 /// OnQueueEmpty event is triggered for the texture category</summary> 355 /// OnQueueEmpty event is triggered for the texture category</summary>
@@ -479,25 +473,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
479 // Remove ourselves from the scene 473 // Remove ourselves from the scene
480 m_scene.RemoveClient(AgentId); 474 m_scene.RemoveClient(AgentId);
481 475
482 // Shut down timers. Thread Context of this method is murky. Lock all timers
483 if (m_avatarTerseUpdateTimer.Enabled)
484 lock (m_avatarTerseUpdateTimer)
485 m_avatarTerseUpdateTimer.Stop();
486 if (m_primTerseUpdateTimer.Enabled)
487 lock (m_primTerseUpdateTimer)
488 m_primTerseUpdateTimer.Stop();
489 if (m_primFullUpdateTimer.Enabled)
490 lock (m_primFullUpdateTimer)
491 m_primFullUpdateTimer.Stop();
492
493 // We can't reach into other scenes and close the connection 476 // We can't reach into other scenes and close the connection
494 // We need to do this over grid communications 477 // We need to do this over grid communications
495 //m_scene.CloseAllAgents(CircuitCode); 478 //m_scene.CloseAllAgents(CircuitCode);
496 479
497 m_avatarTerseUpdateTimer.Dispose();
498 m_primTerseUpdateTimer.Dispose();
499 m_primFullUpdateTimer.Dispose();
500
501 // Disable UDP handling for this client 480 // Disable UDP handling for this client
502 m_udpClient.Shutdown(); 481 m_udpClient.Shutdown();
503 482
@@ -524,18 +503,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
524 503
525 public void Stop() 504 public void Stop()
526 { 505 {
527 // Shut down timers. Thread Context is Murky, lock all timers!
528 if (m_avatarTerseUpdateTimer.Enabled)
529 lock (m_avatarTerseUpdateTimer)
530 m_avatarTerseUpdateTimer.Stop();
531
532 if (m_primTerseUpdateTimer.Enabled)
533 lock (m_primTerseUpdateTimer)
534 m_primTerseUpdateTimer.Stop();
535 506
536 if (m_primFullUpdateTimer.Enabled)
537 lock (m_primFullUpdateTimer)
538 m_primFullUpdateTimer.Stop();
539 } 507 }
540 508
541 #endregion Client Methods 509 #endregion Client Methods
@@ -631,18 +599,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
631 599
632 public virtual void Start() 600 public virtual void Start()
633 { 601 {
634 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
635 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
636 m_avatarTerseUpdateTimer.AutoReset = false;
637
638 m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
639 m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
640 m_primTerseUpdateTimer.AutoReset = false;
641
642 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
643 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
644 m_primFullUpdateTimer.AutoReset = false;
645
646 m_scene.AddNewClient(this); 602 m_scene.AddNewClient(this);
647 603
648 RefreshGroupMembership(); 604 RefreshGroupMembership();
@@ -3394,28 +3350,27 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3394 /// <summary> 3350 /// <summary>
3395 /// send a objectupdate packet with information about the clients avatar 3351 /// send a objectupdate packet with information about the clients avatar
3396 /// </summary> 3352 /// </summary>
3397 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, 3353 public void SendAvatarData(SendAvatarData data)
3398 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
3399 { 3354 {
3400 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3355 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3401 // TODO: don't create new blocks if recycling an old packet 3356 // TODO: don't create new blocks if recycling an old packet
3402 objupdate.RegionData.RegionHandle = regionHandle; 3357 objupdate.RegionData.RegionHandle = data.regionHandle;
3403 objupdate.RegionData.TimeDilation = ushort.MaxValue; 3358 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3404 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3359 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3405 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); 3360 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(data.textureEntry);
3406 3361
3407 //give this avatar object a local id and assign the user a name 3362 //give this avatar object a local id and assign the user a name
3408 objupdate.ObjectData[0].ID = avatarLocalID; 3363 objupdate.ObjectData[0].ID = data.avatarLocalID;
3409 objupdate.ObjectData[0].FullID = avatarID; 3364 objupdate.ObjectData[0].FullID = data.avatarID;
3410 objupdate.ObjectData[0].ParentID = parentID; 3365 objupdate.ObjectData[0].ParentID = data.parentID;
3411 objupdate.ObjectData[0].NameValue = 3366 objupdate.ObjectData[0].NameValue =
3412 Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); 3367 Utils.StringToBytes("FirstName STRING RW SV " + data.firstName + "\nLastName STRING RW SV " + data.lastName + "\nTitle STRING RW SV " + data.grouptitle);
3413 3368
3414 Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); 3369 Vector3 pos2 = new Vector3(data.Pos.X, data.Pos.Y, data.Pos.Z);
3415 byte[] pb = pos2.GetBytes(); 3370 byte[] pb = pos2.GetBytes();
3416 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); 3371 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
3417 3372
3418 byte[] rot = rotation.GetBytes(); 3373 byte[] rot = data.rotation.GetBytes();
3419 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); 3374 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length);
3420 3375
3421 objupdate.Header.Zerocoded = true; 3376 objupdate.Header.Zerocoded = true;
@@ -3426,38 +3381,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3426 /// Send a terse positional/rotation/velocity update about an avatar 3381 /// Send a terse positional/rotation/velocity update about an avatar
3427 /// to the client. This avatar can be that of the client itself. 3382 /// to the client. This avatar can be that of the client itself.
3428 /// </summary> 3383 /// </summary>
3429 public virtual void SendAvatarTerseUpdate(ulong regionHandle, 3384 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
3430 ushort timeDilation, uint localID, Vector3 position,
3431 Vector3 velocity, Quaternion rotation, UUID agentid)
3432 { 3385 {
3386 if (data.priority == double.NaN)
3387 {
3388 m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
3389 return;
3390 }
3391
3392 Quaternion rotation = data.rotation;
3393
3433 if (rotation.X == rotation.Y && 3394 if (rotation.X == rotation.Y &&
3434 rotation.Y == rotation.Z && 3395 rotation.Y == rotation.Z &&
3435 rotation.Z == rotation.W && rotation.W == 0) 3396 rotation.Z == rotation.W && rotation.W == 0)
3436 rotation = Quaternion.Identity; 3397 rotation = Quaternion.Identity;
3437 3398
3438 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = 3399 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock =
3439 CreateAvatarImprovedBlock(localID, position, velocity,rotation); 3400 CreateAvatarImprovedBlock(data.localID, data.position, data.velocity, rotation);
3440 3401
3441 lock (m_avatarTerseUpdates_.SyncRoot) 3402 lock (m_avatarTerseUpdates.SyncRoot)
3442 { 3403 m_avatarTerseUpdates.Enqueue(data.priority, terseBlock, data.localID);
3443 m_avatarTerseUpdates_.Enqueue(DateTime.Now.ToOADate(), terseBlock, localID);
3444
3445 // If packet is full or own movement packet, send it.
3446 if (m_avatarTerseUpdates_.Count >= m_avatarTerseUpdatesPerPacket)
3447 {
3448 ProcessAvatarTerseUpdates(this, null);
3449 }
3450 else if (m_avatarTerseUpdates_.Count == 1)
3451 {
3452 lock (m_avatarTerseUpdateTimer)
3453 m_avatarTerseUpdateTimer.Start();
3454 }
3455 }
3456 } 3404 }
3457 3405
3458 private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) 3406 private void ProcessAvatarTerseUpdates()
3459 { 3407 {
3460 lock (m_avatarTerseUpdates_.SyncRoot) 3408 lock (m_avatarTerseUpdates.SyncRoot)
3461 { 3409 {
3462 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3410 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3463 3411
@@ -3468,8 +3416,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3468 (ushort)(Scene.TimeDilation * ushort.MaxValue); 3416 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3469 3417
3470 int max = m_avatarTerseUpdatesPerPacket; 3418 int max = m_avatarTerseUpdatesPerPacket;
3471 if (max > m_avatarTerseUpdates_.Count) 3419 if (max > m_avatarTerseUpdates.Count)
3472 max = m_avatarTerseUpdates_.Count; 3420 max = m_avatarTerseUpdates.Count;
3473 3421
3474 int count = 0; 3422 int count = 0;
3475 int size = 0; 3423 int size = 0;
@@ -3482,12 +3430,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3482 for (count = 0 ; count < max ; count++) 3430 for (count = 0 ; count < max ; count++)
3483 { 3431 {
3484 int length = 0; 3432 int length = 0;
3485 m_avatarTerseUpdates_.Peek().ToBytes(blockbuffer, ref length); 3433 m_avatarTerseUpdates.Peek().ToBytes(blockbuffer, ref length);
3486 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3434 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3487 if (size + length > Packet.MTU) 3435 if (size + length > Packet.MTU)
3488 break; 3436 break;
3489 size += length; 3437 size += length;
3490 updates.Enqueue(m_avatarTerseUpdates_.Dequeue()); 3438 updates.Enqueue(m_avatarTerseUpdates.Dequeue());
3491 } 3439 }
3492 3440
3493 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; 3441 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
@@ -3497,14 +3445,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3497 3445
3498 terse.Header.Reliable = false; 3446 terse.Header.Reliable = false;
3499 terse.Header.Zerocoded = true; 3447 terse.Header.Zerocoded = true;
3500 // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed
3501 OutPacket(terse, ThrottleOutPacketType.Task);
3502 3448
3503 if (m_avatarTerseUpdates_.Count == 0) 3449 OutPacket(terse, ThrottleOutPacketType.State);
3504 {
3505 lock (m_avatarTerseUpdateTimer)
3506 m_avatarTerseUpdateTimer.Stop();
3507 }
3508 } 3450 }
3509 } 3451 }
3510 3452
@@ -3569,54 +3511,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3569 OutPacket(attach, ThrottleOutPacketType.Task); 3511 OutPacket(attach, ThrottleOutPacketType.Task);
3570 } 3512 }
3571 3513
3572 public void SendPrimitiveToClient( 3514 public void SendPrimitiveToClient(SendPrimitiveData data)
3573 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3574 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
3575 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
3576 uint parentID, byte[] particleSystem, byte clickAction, byte material)
3577 { 3515 {
3578 byte[] textureanim = new byte[0]; 3516 if (data.priority == double.NaN)
3517 {
3518 m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
3519 return;
3520 }
3579 3521
3580 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, 3522 Quaternion rotation = data.rotation;
3581 acc, rotation, rvel, flags,
3582 objectID, ownerID, text, color, parentID, particleSystem,
3583 clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0);
3584 }
3585 3523
3586 public void SendPrimitiveToClient( 3524 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
3587 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3588 Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity,
3589 uint flags,
3590 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
3591 byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius)
3592 {
3593
3594 if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD
3595 return; 3525 return;
3596 if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) 3526 if (data.primShape.PCode == 9 && data.primShape.State != 0 && data.parentID == 0)
3597 return; 3527 return;
3598 3528
3599 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3529 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0.0f)
3600 rotation = Quaternion.Identity; 3530 rotation = Quaternion.Identity;
3601 3531
3602 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); 3532 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data.primShape, data.flags);
3603 3533
3604 objectData.ID = localID; 3534 objectData.ID = data.localID;
3605 objectData.FullID = objectID; 3535 objectData.FullID = data.objectID;
3606 objectData.OwnerID = ownerID; 3536 objectData.OwnerID = data.ownerID;
3607 3537
3608 objectData.Text = Util.StringToBytes256(text); 3538 objectData.Text = Util.StringToBytes256(data.text);
3609 objectData.TextColor[0] = color[0]; 3539 objectData.TextColor[0] = data.color[0];
3610 objectData.TextColor[1] = color[1]; 3540 objectData.TextColor[1] = data.color[1];
3611 objectData.TextColor[2] = color[2]; 3541 objectData.TextColor[2] = data.color[2];
3612 objectData.TextColor[3] = color[3]; 3542 objectData.TextColor[3] = data.color[3];
3613 objectData.ParentID = parentID; 3543 objectData.ParentID = data.parentID;
3614 objectData.PSBlock = particleSystem; 3544 objectData.PSBlock = data.particleSystem;
3615 objectData.ClickAction = clickAction; 3545 objectData.ClickAction = data.clickAction;
3616 objectData.Material = material; 3546 objectData.Material = data.material;
3617 objectData.Flags = 0; 3547 objectData.Flags = 0;
3618 3548
3619 if (attachment) 3549 if (data.attachment)
3620 { 3550 {
3621 // Necessary??? 3551 // Necessary???
3622 objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); 3552 objectData.JointAxisOrAnchor = new Vector3(0, 0, 2);
@@ -3624,14 +3554,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3624 3554
3625 // Item from inventory??? 3555 // Item from inventory???
3626 objectData.NameValue = 3556 objectData.NameValue =
3627 Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); 3557 Utils.StringToBytes("AttachItemID STRING RW SV " + data.AssetId.Guid);
3628 objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); 3558 objectData.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16));
3629 } 3559 }
3630 3560
3631 // Xantor 20080528: Send sound info as well 3561 // Xantor 20080528: Send sound info as well
3632 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again 3562 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again
3633 objectData.Sound = SoundId; 3563 objectData.Sound = data.SoundId;
3634 if (SoundId == UUID.Zero) 3564 if (data.SoundId == UUID.Zero)
3635 { 3565 {
3636 objectData.OwnerID = UUID.Zero; 3566 objectData.OwnerID = UUID.Zero;
3637 objectData.Gain = 0.0f; 3567 objectData.Gain = 0.0f;
@@ -3640,39 +3570,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3640 } 3570 }
3641 else 3571 else
3642 { 3572 {
3643 objectData.OwnerID = ownerID; 3573 objectData.OwnerID = data.ownerID;
3644 objectData.Gain = (float)SoundGain; 3574 objectData.Gain = (float)data.SoundVolume;
3645 objectData.Radius = (float)SoundRadius; 3575 objectData.Radius = (float)data.SoundRadius;
3646 objectData.Flags = SoundFlags; 3576 objectData.Flags = data.SoundFlags;
3647 } 3577 }
3648 3578
3649 byte[] pb = pos.GetBytes(); 3579 byte[] pb = data.pos.GetBytes();
3650 Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); 3580 Buffer.BlockCopy(pb, 0, objectData.ObjectData, 0, pb.Length);
3651 3581
3652 byte[] vel = velocity.GetBytes(); 3582 byte[] vel = data.vel.GetBytes();
3653 Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); 3583 Buffer.BlockCopy(vel, 0, objectData.ObjectData, pb.Length, vel.Length);
3654 3584
3655 byte[] rot = rotation.GetBytes(); 3585 byte[] rot = rotation.GetBytes();
3656 Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); 3586 Buffer.BlockCopy(rot, 0, objectData.ObjectData, 36, rot.Length);
3657 3587
3658 byte[] rvel = rotational_velocity.GetBytes(); 3588 byte[] rvel = data.rvel.GetBytes();
3659 Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); 3589 Buffer.BlockCopy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length);
3660 3590
3661 if (textureanim.Length > 0) 3591 if (data.textureanim.Length > 0)
3662 { 3592 {
3663 objectData.TextureAnim = textureanim; 3593 objectData.TextureAnim = data.textureanim;
3664 } 3594 }
3665 3595
3666 lock (m_primFullUpdates_.SyncRoot) 3596 lock (m_primFullUpdates.SyncRoot)
3667 { 3597 m_primFullUpdates.Enqueue(data.priority, objectData, data.localID);
3668 if (m_primFullUpdates_.Count == 0)
3669 m_primFullUpdateTimer.Start();
3670
3671 m_primFullUpdates_.Enqueue(DateTime.Now.ToOADate(), objectData, localID);
3672
3673 if (m_primFullUpdates_.Count >= m_primFullUpdatesPerPacket)
3674 ProcessPrimFullUpdates(this, null);
3675 }
3676 } 3598 }
3677 3599
3678 void HandleQueueEmpty(ThrottleOutPacketType queue) 3600 void HandleQueueEmpty(ThrottleOutPacketType queue)
@@ -3682,6 +3604,33 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3682 case ThrottleOutPacketType.Texture: 3604 case ThrottleOutPacketType.Texture:
3683 ProcessTextureRequests(); 3605 ProcessTextureRequests();
3684 break; 3606 break;
3607 case ThrottleOutPacketType.State:
3608 int count = 0;
3609
3610 lock (m_avatarTerseUpdates.SyncRoot)
3611 count = m_avatarTerseUpdates.Count;
3612 if (count > 0)
3613 {
3614 ProcessAvatarTerseUpdates();
3615 return;
3616 }
3617
3618 lock (m_primFullUpdates.SyncRoot)
3619 count = m_primFullUpdates.Count;
3620 if (count > 0)
3621 {
3622 ProcessPrimFullUpdates();
3623 return;
3624 }
3625
3626 lock (m_primTerseUpdates.SyncRoot)
3627 count = m_primTerseUpdates.Count;
3628 if (count > 0)
3629 {
3630 ProcessPrimTerseUpdates();
3631 return;
3632 }
3633 break;
3685 } 3634 }
3686 } 3635 }
3687 3636
@@ -3691,18 +3640,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3691 m_imageManager.ProcessImageQueue(m_textureSendLimit); 3640 m_imageManager.ProcessImageQueue(m_textureSendLimit);
3692 } 3641 }
3693 3642
3694 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) 3643 void ProcessPrimFullUpdates()
3695 { 3644 {
3696 lock (m_primFullUpdates_.SyncRoot) 3645 lock (m_primFullUpdates.SyncRoot)
3697 { 3646 {
3698 if (m_primFullUpdates_.Count == 0 && m_primFullUpdateTimer.Enabled)
3699 {
3700 lock (m_primFullUpdateTimer)
3701 m_primFullUpdateTimer.Stop();
3702
3703 return;
3704 }
3705
3706 ObjectUpdatePacket outPacket = 3647 ObjectUpdatePacket outPacket =
3707 (ObjectUpdatePacket)PacketPool.Instance.GetPacket( 3648 (ObjectUpdatePacket)PacketPool.Instance.GetPacket(
3708 PacketType.ObjectUpdate); 3649 PacketType.ObjectUpdate);
@@ -3712,7 +3653,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3712 outPacket.RegionData.TimeDilation = 3653 outPacket.RegionData.TimeDilation =
3713 (ushort)(Scene.TimeDilation * ushort.MaxValue); 3654 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3714 3655
3715 int max = m_primFullUpdates_.Count; 3656 int max = m_primFullUpdates.Count;
3716 if (max > m_primFullUpdatesPerPacket) 3657 if (max > m_primFullUpdatesPerPacket)
3717 max = m_primFullUpdatesPerPacket; 3658 max = m_primFullUpdatesPerPacket;
3718 3659
@@ -3727,12 +3668,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3727 for (count = 0 ; count < max ; count++) 3668 for (count = 0 ; count < max ; count++)
3728 { 3669 {
3729 int length = 0; 3670 int length = 0;
3730 m_primFullUpdates_.Peek().ToBytes(blockbuffer, ref length); 3671 m_primFullUpdates.Peek().ToBytes(blockbuffer, ref length);
3731 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3672 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3732 if (size + length > Packet.MTU) 3673 if (size + length > Packet.MTU)
3733 break; 3674 break;
3734 size += length; 3675 size += length;
3735 updates.Enqueue(m_primFullUpdates_.Dequeue()); 3676 updates.Enqueue(m_primFullUpdates.Dequeue());
3736 } 3677 }
3737 3678
3738 outPacket.ObjectData = 3679 outPacket.ObjectData =
@@ -3743,53 +3684,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3743 3684
3744 outPacket.Header.Zerocoded = true; 3685 outPacket.Header.Zerocoded = true;
3745 OutPacket(outPacket, ThrottleOutPacketType.State); 3686 OutPacket(outPacket, ThrottleOutPacketType.State);
3746
3747 if (m_primFullUpdates_.Count == 0 && m_primFullUpdateTimer.Enabled)
3748 lock (m_primFullUpdateTimer)
3749 m_primFullUpdateTimer.Stop();
3750 } 3687 }
3751 } 3688 }
3752 3689
3753 /// <summary> 3690 /// <summary>
3754 /// 3691 ///
3755 /// </summary> 3692 /// </summary>
3756 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 3693 //public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
3757 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) 3694 // Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint)
3695 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
3758 { 3696 {
3759 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3697 if (data.priority == double.NaN)
3698 {
3699 m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update");
3700 return;
3701 }
3702
3703 Quaternion rotation = data.rotation;
3704
3705 if (data.attachPoint > 30 && data.owner != AgentId) // Someone else's HUD
3760 return; 3706 return;
3761 3707
3762 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3708 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
3763 rotation = Quaternion.Identity; 3709 rotation = Quaternion.Identity;
3764 3710
3765 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = 3711 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData =
3766 CreatePrimImprovedBlock(localID, position, rotation, 3712 CreatePrimImprovedBlock(data.localID, data.position, rotation,
3767 velocity, rotationalvelocity, state); 3713 data.velocity, data.rotationalvelocity, data.state);
3768
3769 lock (m_primTerseUpdates_.SyncRoot)
3770 {
3771 if (m_primTerseUpdates_.Count == 0)
3772 m_primTerseUpdateTimer.Start();
3773
3774 m_primTerseUpdates_.Enqueue(DateTime.Now.ToOADate(), objectData, localID);
3775 3714
3776 if (m_primTerseUpdates_.Count >= m_primTerseUpdatesPerPacket) 3715 lock (m_primTerseUpdates.SyncRoot)
3777 ProcessPrimTerseUpdates(this, null); 3716 m_primTerseUpdates.Enqueue(data.priority, objectData, data.localID);
3778 }
3779 } 3717 }
3780 3718
3781 void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) 3719 void ProcessPrimTerseUpdates()
3782 { 3720 {
3783 lock (m_primTerseUpdates_.SyncRoot) 3721 lock (m_primTerseUpdates.SyncRoot)
3784 { 3722 {
3785 if (m_primTerseUpdates_.Count == 0)
3786 {
3787 lock (m_primTerseUpdateTimer)
3788 m_primTerseUpdateTimer.Stop();
3789
3790 return;
3791 }
3792
3793 ImprovedTerseObjectUpdatePacket outPacket = 3723 ImprovedTerseObjectUpdatePacket outPacket =
3794 (ImprovedTerseObjectUpdatePacket) 3724 (ImprovedTerseObjectUpdatePacket)
3795 PacketPool.Instance.GetPacket( 3725 PacketPool.Instance.GetPacket(
@@ -3800,7 +3730,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3800 outPacket.RegionData.TimeDilation = 3730 outPacket.RegionData.TimeDilation =
3801 (ushort)(Scene.TimeDilation * ushort.MaxValue); 3731 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3802 3732
3803 int max = m_primTerseUpdates_.Count; 3733 int max = m_primTerseUpdates.Count;
3804 if (max > m_primTerseUpdatesPerPacket) 3734 if (max > m_primTerseUpdatesPerPacket)
3805 max = m_primTerseUpdatesPerPacket; 3735 max = m_primTerseUpdatesPerPacket;
3806 3736
@@ -3815,12 +3745,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3815 for (count = 0 ; count < max ; count++) 3745 for (count = 0 ; count < max ; count++)
3816 { 3746 {
3817 int length = 0; 3747 int length = 0;
3818 m_primTerseUpdates_.Peek().ToBytes(blockbuffer, ref length); 3748 m_primTerseUpdates.Peek().ToBytes(blockbuffer, ref length);
3819 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3749 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3820 if (size + length > Packet.MTU) 3750 if (size + length > Packet.MTU)
3821 break; 3751 break;
3822 size += length; 3752 size += length;
3823 updates.Enqueue(m_primTerseUpdates_.Dequeue()); 3753 updates.Enqueue(m_primTerseUpdates.Dequeue());
3824 } 3754 }
3825 3755
3826 outPacket.ObjectData = 3756 outPacket.ObjectData =
@@ -3833,26 +3763,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3833 outPacket.Header.Reliable = false; 3763 outPacket.Header.Reliable = false;
3834 outPacket.Header.Zerocoded = true; 3764 outPacket.Header.Zerocoded = true;
3835 OutPacket(outPacket, ThrottleOutPacketType.State); 3765 OutPacket(outPacket, ThrottleOutPacketType.State);
3836
3837 if (m_primTerseUpdates_.Count == 0)
3838 lock (m_primTerseUpdateTimer)
3839 m_primTerseUpdateTimer.Stop();
3840 } 3766 }
3841 } 3767 }
3842 3768
3843 public void FlushPrimUpdates() 3769 public void FlushPrimUpdates()
3844 { 3770 {
3845 while (m_primFullUpdates_.Count > 0) 3771 while (m_primFullUpdates.Count > 0)
3846 { 3772 {
3847 ProcessPrimFullUpdates(this, null); 3773 ProcessPrimFullUpdates();
3848 } 3774 }
3849 while (m_primTerseUpdates_.Count > 0) 3775 while (m_primTerseUpdates.Count > 0)
3850 { 3776 {
3851 ProcessPrimTerseUpdates(this, null); 3777 ProcessPrimTerseUpdates();
3852 } 3778 }
3853 while (m_avatarTerseUpdates_.Count > 0) 3779 while (m_avatarTerseUpdates.Count > 0)
3854 { 3780 {
3855 ProcessAvatarTerseUpdates(this, null); 3781 ProcessAvatarTerseUpdates();
3856 } 3782 }
3857 } 3783 }
3858 3784