diff options
Diffstat (limited to 'OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs')
-rw-r--r-- | OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | 626 |
1 files changed, 299 insertions, 327 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 1f3582c..11dca8d 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs | |||
@@ -50,43 +50,17 @@ using Nini.Config; | |||
50 | 50 | ||
51 | namespace OpenSim.Region.ClientStack.LindenUDP | 51 | namespace OpenSim.Region.ClientStack.LindenUDP |
52 | { | 52 | { |
53 | #region Enums | 53 | public class EntityUpdate |
54 | |||
55 | /// <summary> | ||
56 | /// Specifies the fields that have been changed when sending a prim or | ||
57 | /// avatar update | ||
58 | /// </summary> | ||
59 | [Flags] | ||
60 | public enum PrimUpdateFlags : uint | ||
61 | { | 54 | { |
62 | None = 0, | 55 | public ISceneEntity Entity; |
63 | AttachmentPoint = 1 << 0, | 56 | public PrimUpdateFlags Flags; |
64 | Material = 1 << 1, | ||
65 | ClickAction = 1 << 2, | ||
66 | Scale = 1 << 3, | ||
67 | ParentID = 1 << 4, | ||
68 | PrimFlags = 1 << 5, | ||
69 | PrimData = 1 << 6, | ||
70 | MediaURL = 1 << 7, | ||
71 | ScratchPad = 1 << 8, | ||
72 | Textures = 1 << 9, | ||
73 | TextureAnim = 1 << 10, | ||
74 | NameValue = 1 << 11, | ||
75 | Position = 1 << 12, | ||
76 | Rotation = 1 << 13, | ||
77 | Velocity = 1 << 14, | ||
78 | Acceleration = 1 << 15, | ||
79 | AngularVelocity = 1 << 16, | ||
80 | CollisionPlane = 1 << 17, | ||
81 | Text = 1 << 18, | ||
82 | Particles = 1 << 19, | ||
83 | ExtraData = 1 << 20, | ||
84 | Sound = 1 << 21, | ||
85 | Joint = 1 << 22, | ||
86 | FullUpdate = UInt32.MaxValue | ||
87 | } | ||
88 | 57 | ||
89 | #endregion Enums | 58 | public EntityUpdate(ISceneEntity entity, PrimUpdateFlags flags) |
59 | { | ||
60 | Entity = entity; | ||
61 | Flags = flags; | ||
62 | } | ||
63 | } | ||
90 | 64 | ||
91 | public delegate bool PacketMethod(IClientAPI simClient, Packet packet); | 65 | public delegate bool PacketMethod(IClientAPI simClient, Packet packet); |
92 | 66 | ||
@@ -350,9 +324,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
350 | private readonly IGroupsModule m_GroupsModule; | 324 | private readonly IGroupsModule m_GroupsModule; |
351 | 325 | ||
352 | private int m_cachedTextureSerial; | 326 | private int m_cachedTextureSerial; |
353 | protected PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates; | 327 | private PriorityQueue<double, EntityUpdate> m_entityUpdates; |
354 | private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates; | ||
355 | private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates; | ||
356 | 328 | ||
357 | /// <value> | 329 | /// <value> |
358 | /// List used in construction of data blocks for an object update packet. This is to stop us having to | 330 | /// List used in construction of data blocks for an object update packet. This is to stop us having to |
@@ -463,9 +435,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
463 | 435 | ||
464 | m_scene = scene; | 436 | m_scene = scene; |
465 | 437 | ||
466 | m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); | 438 | m_entityUpdates = new PriorityQueue<double, EntityUpdate>(m_scene.Entities.Count); |
467 | m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); | ||
468 | m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count); | ||
469 | m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); | 439 | m_fullUpdateDataBlocksBuilder = new List<ObjectUpdatePacket.ObjectDataBlock>(); |
470 | m_killRecord = new HashSet<uint>(); | 440 | m_killRecord = new HashSet<uint>(); |
471 | 441 | ||
@@ -1519,7 +1489,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
1519 | kill.Header.Reliable = true; | 1489 | kill.Header.Reliable = true; |
1520 | kill.Header.Zerocoded = true; | 1490 | kill.Header.Zerocoded = true; |
1521 | 1491 | ||
1522 | lock (m_primFullUpdates.SyncRoot) | 1492 | lock (m_entityUpdates.SyncRoot) |
1523 | { | 1493 | { |
1524 | m_killRecord.Add(localID); | 1494 | m_killRecord.Add(localID); |
1525 | OutPacket(kill, ThrottleOutPacketType.State); | 1495 | OutPacket(kill, ThrottleOutPacketType.State); |
@@ -3419,71 +3389,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3419 | /// <summary> | 3389 | /// <summary> |
3420 | /// Send an ObjectUpdate packet with information about an avatar | 3390 | /// Send an ObjectUpdate packet with information about an avatar |
3421 | /// </summary> | 3391 | /// </summary> |
3422 | public void SendAvatarData(SendAvatarData data) | 3392 | public void SendAvatarDataImmediate(ISceneEntity avatar) |
3423 | { | 3393 | { |
3394 | ScenePresence presence = avatar as ScenePresence; | ||
3395 | if (presence == null) | ||
3396 | return; | ||
3397 | |||
3424 | ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); | 3398 | ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); |
3425 | objupdate.Header.Zerocoded = true; | 3399 | objupdate.Header.Zerocoded = true; |
3426 | 3400 | ||
3427 | objupdate.RegionData.RegionHandle = data.RegionHandle; | 3401 | objupdate.RegionData.RegionHandle = presence.RegionHandle; |
3428 | objupdate.RegionData.TimeDilation = ushort.MaxValue; | 3402 | objupdate.RegionData.TimeDilation = ushort.MaxValue; |
3429 | 3403 | ||
3430 | objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; | 3404 | objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; |
3431 | objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data); | 3405 | objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); |
3432 | 3406 | ||
3433 | OutPacket(objupdate, ThrottleOutPacketType.Task); | 3407 | OutPacket(objupdate, ThrottleOutPacketType.Task); |
3434 | } | 3408 | } |
3435 | 3409 | ||
3436 | /// <summary> | ||
3437 | /// Send a terse positional/rotation/velocity update about an avatar | ||
3438 | /// to the client. This avatar can be that of the client itself. | ||
3439 | /// </summary> | ||
3440 | public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data) | ||
3441 | { | ||
3442 | if (data.Priority == double.NaN) | ||
3443 | { | ||
3444 | m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update"); | ||
3445 | return; | ||
3446 | } | ||
3447 | |||
3448 | Quaternion rotation = data.Rotation; | ||
3449 | if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f) | ||
3450 | rotation = Quaternion.Identity; | ||
3451 | |||
3452 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data); | ||
3453 | |||
3454 | lock (m_avatarTerseUpdates.SyncRoot) | ||
3455 | m_avatarTerseUpdates.Enqueue(data.Priority, terseBlock, data.LocalID); | ||
3456 | |||
3457 | // If we received an update about our own avatar, process the avatar update priority queue immediately | ||
3458 | if (data.AgentID == m_agentId) | ||
3459 | ProcessAvatarTerseUpdates(); | ||
3460 | } | ||
3461 | |||
3462 | protected void ProcessAvatarTerseUpdates() | ||
3463 | { | ||
3464 | ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
3465 | terse.Header.Reliable = false; | ||
3466 | terse.Header.Zerocoded = true; | ||
3467 | |||
3468 | //terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); | ||
3469 | terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; | ||
3470 | terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); | ||
3471 | |||
3472 | lock (m_avatarTerseUpdates.SyncRoot) | ||
3473 | { | ||
3474 | int count = Math.Min(m_avatarTerseUpdates.Count, m_udpServer.AvatarTerseUpdatesPerPacket); | ||
3475 | if (count == 0) | ||
3476 | return; | ||
3477 | |||
3478 | terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; | ||
3479 | for (int i = 0; i < count; i++) | ||
3480 | terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue(); | ||
3481 | } | ||
3482 | |||
3483 | // HACK: Using the task category until the tiered reprioritization code is in | ||
3484 | OutPacket(terse, ThrottleOutPacketType.Task); | ||
3485 | } | ||
3486 | |||
3487 | public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) | 3410 | public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) |
3488 | { | 3411 | { |
3489 | if (!IsActive) return; // We don't need to update inactive clients. | 3412 | if (!IsActive) return; // We don't need to update inactive clients. |
@@ -3528,172 +3451,187 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3528 | 3451 | ||
3529 | #region Primitive Packet/Data Sending Methods | 3452 | #region Primitive Packet/Data Sending Methods |
3530 | 3453 | ||
3531 | public void SendPrimitiveToClient(SendPrimitiveData data) | 3454 | /// <summary> |
3455 | /// Generate one of the object update packets based on PrimUpdateFlags | ||
3456 | /// and broadcast the packet to clients | ||
3457 | /// </summary> | ||
3458 | public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags) | ||
3532 | { | 3459 | { |
3533 | // string text = data.text; | 3460 | double priority; |
3534 | // if (text.IndexOf("\n") >= 0) | ||
3535 | // text = text.Remove(text.IndexOf("\n")); | ||
3536 | // m_log.DebugFormat( | ||
3537 | // "[CLIENT]: Placing request to send full info about prim {0} text {1} to client {2}", | ||
3538 | // data.localID, text, Name); | ||
3539 | |||
3540 | if (data.priority == double.NaN) | ||
3541 | { | ||
3542 | m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update"); | ||
3543 | return; | ||
3544 | } | ||
3545 | |||
3546 | Quaternion rotation = data.rotation; | ||
3547 | if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f) | ||
3548 | rotation = Quaternion.Identity; | ||
3549 | |||
3550 | if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD | ||
3551 | return; | ||
3552 | if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9) | ||
3553 | return; | ||
3554 | 3461 | ||
3555 | ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data); | 3462 | if (entity is SceneObjectPart) |
3463 | priority = ((SceneObjectPart)entity).ParentGroup.GetUpdatePriority(this); | ||
3464 | else if (entity is ScenePresence) | ||
3465 | priority = ((ScenePresence)entity).GetUpdatePriority(this); | ||
3466 | else | ||
3467 | priority = 0.0d; | ||
3556 | 3468 | ||
3557 | lock (m_primFullUpdates.SyncRoot) | 3469 | lock (m_entityUpdates.SyncRoot) |
3558 | m_primFullUpdates.Enqueue(data.priority, objectData, data.localID); | 3470 | m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags), entity.LocalId); |
3559 | } | 3471 | } |
3560 | 3472 | ||
3561 | void ProcessPrimFullUpdates() | 3473 | private void ProcessEntityUpdates(int maxUpdates) |
3562 | { | 3474 | { |
3563 | ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); | 3475 | Lazy<List<ObjectUpdatePacket.ObjectDataBlock>> objectUpdateBlocks = new Lazy<List<ObjectUpdatePacket.ObjectDataBlock>>(); |
3564 | outPacket.Header.Zerocoded = true; | 3476 | Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>> compressedUpdateBlocks = new Lazy<List<ObjectUpdateCompressedPacket.ObjectDataBlock>>(); |
3477 | Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>> terseUpdateBlocks = new Lazy<List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>>(); | ||
3565 | 3478 | ||
3566 | outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; | 3479 | if (maxUpdates <= 0) maxUpdates = Int32.MaxValue; |
3567 | outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); | 3480 | int updatesThisCall = 0; |
3568 | 3481 | ||
3569 | lock (m_primFullUpdates.SyncRoot) | 3482 | lock (m_entityUpdates.SyncRoot) |
3570 | { | 3483 | { |
3571 | int count = Math.Min(m_primFullUpdates.Count, m_udpServer.PrimFullUpdatesPerPacket); | 3484 | EntityUpdate update; |
3572 | if (count == 0) | 3485 | while (updatesThisCall < maxUpdates && m_entityUpdates.TryDequeue(out update)) |
3573 | return; | ||
3574 | |||
3575 | m_fullUpdateDataBlocksBuilder.Clear(); | ||
3576 | |||
3577 | for (int i = 0; i < count; i++) | ||
3578 | { | 3486 | { |
3579 | ObjectUpdatePacket.ObjectDataBlock block = m_primFullUpdates.Dequeue(); | 3487 | ++updatesThisCall; |
3488 | |||
3489 | #region UpdateFlags to packet type conversion | ||
3580 | 3490 | ||
3581 | if (!m_killRecord.Contains(block.ID)) | 3491 | PrimUpdateFlags updateFlags = update.Flags; |
3492 | |||
3493 | bool canUseCompressed = true; | ||
3494 | bool canUseImproved = true; | ||
3495 | |||
3496 | // Compressed object updates only make sense for LL primitives | ||
3497 | if (!(update.Entity is SceneObjectPart)) | ||
3498 | canUseCompressed = false; | ||
3499 | |||
3500 | if (updateFlags.HasFlag(PrimUpdateFlags.FullUpdate)) | ||
3582 | { | 3501 | { |
3583 | m_fullUpdateDataBlocksBuilder.Add(block); | 3502 | canUseCompressed = false; |
3584 | 3503 | canUseImproved = false; | |
3585 | // string text = Util.FieldToString(outPacket.ObjectData[i].Text); | ||
3586 | // if (text.IndexOf("\n") >= 0) | ||
3587 | // text = text.Remove(text.IndexOf("\n")); | ||
3588 | // m_log.DebugFormat( | ||
3589 | // "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", | ||
3590 | // outPacket.ObjectData[i].ID, text, Name); | ||
3591 | } | 3504 | } |
3592 | // else | 3505 | else |
3593 | // { | 3506 | { |
3594 | // m_log.WarnFormat( | 3507 | if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) || |
3595 | // "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name); | 3508 | updateFlags.HasFlag(PrimUpdateFlags.Acceleration) || |
3596 | // } | 3509 | updateFlags.HasFlag(PrimUpdateFlags.CollisionPlane) || |
3510 | updateFlags.HasFlag(PrimUpdateFlags.Joint)) | ||
3511 | { | ||
3512 | canUseCompressed = false; | ||
3513 | } | ||
3514 | |||
3515 | if (updateFlags.HasFlag(PrimUpdateFlags.PrimFlags) || | ||
3516 | updateFlags.HasFlag(PrimUpdateFlags.ParentID) || | ||
3517 | updateFlags.HasFlag(PrimUpdateFlags.Scale) || | ||
3518 | updateFlags.HasFlag(PrimUpdateFlags.PrimData) || | ||
3519 | updateFlags.HasFlag(PrimUpdateFlags.Text) || | ||
3520 | updateFlags.HasFlag(PrimUpdateFlags.NameValue) || | ||
3521 | updateFlags.HasFlag(PrimUpdateFlags.ExtraData) || | ||
3522 | updateFlags.HasFlag(PrimUpdateFlags.TextureAnim) || | ||
3523 | updateFlags.HasFlag(PrimUpdateFlags.Sound) || | ||
3524 | updateFlags.HasFlag(PrimUpdateFlags.Particles) || | ||
3525 | updateFlags.HasFlag(PrimUpdateFlags.Material) || | ||
3526 | updateFlags.HasFlag(PrimUpdateFlags.ClickAction) || | ||
3527 | updateFlags.HasFlag(PrimUpdateFlags.MediaURL) || | ||
3528 | updateFlags.HasFlag(PrimUpdateFlags.Joint)) | ||
3529 | { | ||
3530 | canUseImproved = false; | ||
3531 | } | ||
3532 | } | ||
3533 | |||
3534 | #endregion UpdateFlags to packet type conversion | ||
3535 | |||
3536 | #region Block Construction | ||
3537 | |||
3538 | // TODO: Remove this once we can build compressed updates | ||
3539 | canUseCompressed = false; | ||
3540 | |||
3541 | if (!canUseImproved && !canUseCompressed) | ||
3542 | { | ||
3543 | if (update.Entity is ScenePresence) | ||
3544 | objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); | ||
3545 | else | ||
3546 | objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); | ||
3547 | } | ||
3548 | else if (!canUseImproved) | ||
3549 | { | ||
3550 | compressedUpdateBlocks.Value.Add(CreateCompressedUpdateBlock((SceneObjectPart)update.Entity, updateFlags)); | ||
3551 | } | ||
3552 | else | ||
3553 | { | ||
3554 | terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures))); | ||
3555 | } | ||
3556 | |||
3557 | #endregion Block Construction | ||
3597 | } | 3558 | } |
3559 | } | ||
3598 | 3560 | ||
3599 | outPacket.ObjectData = m_fullUpdateDataBlocksBuilder.ToArray(); | 3561 | #region Packet Sending |
3600 | |||
3601 | OutPacket(outPacket, ThrottleOutPacketType.State); | ||
3602 | } | ||
3603 | } | ||
3604 | 3562 | ||
3605 | public void SendPrimTerseUpdate(SendPrimitiveTerseData data) | 3563 | const float TIME_DILATION = 1.0f; |
3606 | { | 3564 | ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); |
3607 | if (data.Priority == double.NaN) | 3565 | |
3566 | if (objectUpdateBlocks.IsValueCreated) | ||
3608 | { | 3567 | { |
3609 | m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update"); | 3568 | List<ObjectUpdatePacket.ObjectDataBlock> blocks = objectUpdateBlocks.Value; |
3610 | return; | ||
3611 | } | ||
3612 | 3569 | ||
3613 | Quaternion rotation = data.Rotation; | 3570 | ObjectUpdatePacket packet = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); |
3614 | if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f) | 3571 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3615 | rotation = Quaternion.Identity; | 3572 | packet.RegionData.TimeDilation = timeDilation; |
3573 | packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | ||
3616 | 3574 | ||
3617 | if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD | 3575 | for (int i = 0; i < blocks.Count; i++) |
3618 | return; | 3576 | packet.ObjectData[i] = blocks[i]; |
3577 | |||
3578 | OutPacket(packet, ThrottleOutPacketType.Task, true); | ||
3579 | } | ||
3619 | 3580 | ||
3620 | ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data); | 3581 | if (compressedUpdateBlocks.IsValueCreated) |
3582 | { | ||
3583 | List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value; | ||
3621 | 3584 | ||
3622 | lock (m_primTerseUpdates.SyncRoot) | 3585 | ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed); |
3623 | m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID); | 3586 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; |
3624 | } | 3587 | packet.RegionData.TimeDilation = timeDilation; |
3588 | packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count]; | ||
3625 | 3589 | ||
3626 | void ProcessPrimTerseUpdates() | 3590 | for (int i = 0; i < blocks.Count; i++) |
3627 | { | 3591 | packet.ObjectData[i] = blocks[i]; |
3628 | ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); | ||
3629 | outPacket.Header.Reliable = false; | ||
3630 | outPacket.Header.Zerocoded = true; | ||
3631 | 3592 | ||
3632 | outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; | 3593 | OutPacket(packet, ThrottleOutPacketType.Task, true); |
3633 | outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); | 3594 | } |
3634 | 3595 | ||
3635 | lock (m_primTerseUpdates.SyncRoot) | 3596 | if (terseUpdateBlocks.IsValueCreated) |
3636 | { | 3597 | { |
3637 | int count = Math.Min(m_primTerseUpdates.Count, m_udpServer.PrimTerseUpdatesPerPacket); | 3598 | List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> blocks = terseUpdateBlocks.Value; |
3638 | if (count == 0) | 3599 | |
3639 | return; | 3600 | ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); |
3601 | packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; | ||
3602 | packet.RegionData.TimeDilation = timeDilation; | ||
3603 | packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; | ||
3640 | 3604 | ||
3641 | outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; | 3605 | for (int i = 0; i < blocks.Count; i++) |
3642 | for (int i = 0; i < count; i++) | 3606 | packet.ObjectData[i] = blocks[i]; |
3643 | outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue(); | 3607 | |
3608 | OutPacket(packet, ThrottleOutPacketType.Task, true); | ||
3644 | } | 3609 | } |
3645 | 3610 | ||
3646 | OutPacket(outPacket, ThrottleOutPacketType.State); | 3611 | #endregion Packet Sending |
3647 | } | 3612 | } |
3648 | 3613 | ||
3649 | public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) | 3614 | public void ReprioritizeUpdates(UpdatePriorityHandler handler) |
3650 | { | 3615 | { |
3651 | PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler = | 3616 | //m_log.Debug("[CLIENT]: Reprioritizing prim updates for " + m_firstName + " " + m_lastName); |
3652 | delegate(ref double priority, uint local_id) | 3617 | |
3653 | { | 3618 | PriorityQueue<double, EntityUpdate>.UpdatePriorityHandler update_priority_handler = |
3654 | priority = handler(new UpdatePriorityData(priority, local_id)); | ||
3655 | return priority != double.NaN; | ||
3656 | }; | ||
3657 | PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler = | ||
3658 | delegate(ref double priority, uint local_id) | 3619 | delegate(ref double priority, uint local_id) |
3659 | { | 3620 | { |
3660 | priority = handler(new UpdatePriorityData(priority, local_id)); | 3621 | priority = handler(new UpdatePriorityData(priority, local_id)); |
3661 | return priority != double.NaN; | 3622 | return priority != double.NaN; |
3662 | }; | 3623 | }; |
3663 | 3624 | ||
3664 | if ((type & StateUpdateTypes.AvatarTerse) != 0) | 3625 | lock (m_entityUpdates.SyncRoot) |
3665 | { | 3626 | m_entityUpdates.Reprioritize(update_priority_handler); |
3666 | lock (m_avatarTerseUpdates.SyncRoot) | ||
3667 | m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler); | ||
3668 | } | ||
3669 | |||
3670 | if ((type & StateUpdateTypes.PrimitiveFull) != 0) | ||
3671 | { | ||
3672 | lock (m_primFullUpdates.SyncRoot) | ||
3673 | m_primFullUpdates.Reprioritize(update_priority_handler); | ||
3674 | } | ||
3675 | |||
3676 | if ((type & StateUpdateTypes.PrimitiveTerse) != 0) | ||
3677 | { | ||
3678 | lock (m_primTerseUpdates.SyncRoot) | ||
3679 | m_primTerseUpdates.Reprioritize(terse_update_priority_handler); | ||
3680 | } | ||
3681 | } | 3627 | } |
3682 | 3628 | ||
3683 | public void FlushPrimUpdates() | 3629 | public void FlushPrimUpdates() |
3684 | { | 3630 | { |
3685 | while (m_primFullUpdates.Count > 0) | 3631 | m_log.Debug("[CLIENT]: Flushing prim updates to " + m_firstName + " " + m_lastName); |
3686 | { | 3632 | |
3687 | ProcessPrimFullUpdates(); | 3633 | while (m_entityUpdates.Count > 0) |
3688 | } | 3634 | ProcessEntityUpdates(-1); |
3689 | while (m_primTerseUpdates.Count > 0) | ||
3690 | { | ||
3691 | ProcessPrimTerseUpdates(); | ||
3692 | } | ||
3693 | while (m_avatarTerseUpdates.Count > 0) | ||
3694 | { | ||
3695 | ProcessAvatarTerseUpdates(); | ||
3696 | } | ||
3697 | } | 3635 | } |
3698 | 3636 | ||
3699 | #endregion Primitive Packet/Data Sending Methods | 3637 | #endregion Primitive Packet/Data Sending Methods |
@@ -3726,26 +3664,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
3726 | { | 3664 | { |
3727 | if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) | 3665 | if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) |
3728 | { | 3666 | { |
3729 | lock (m_avatarTerseUpdates.SyncRoot) | 3667 | if (m_entityUpdates.Count > 0) |
3730 | { | 3668 | ProcessEntityUpdates(m_udpServer.PrimUpdatesPerCallback); |
3731 | if (m_avatarTerseUpdates.Count > 0) | ||
3732 | ProcessAvatarTerseUpdates(); | ||
3733 | } | ||
3734 | } | ||
3735 | |||
3736 | if ((categories & ThrottleOutPacketTypeFlags.State) != 0) | ||
3737 | { | ||
3738 | lock (m_primFullUpdates.SyncRoot) | ||
3739 | { | ||
3740 | if (m_primFullUpdates.Count > 0) | ||
3741 | ProcessPrimFullUpdates(); | ||
3742 | } | ||
3743 | |||
3744 | lock (m_primTerseUpdates.SyncRoot) | ||
3745 | { | ||
3746 | if (m_primTerseUpdates.Count > 0) | ||
3747 | ProcessPrimTerseUpdates(); | ||
3748 | } | ||
3749 | } | 3669 | } |
3750 | 3670 | ||
3751 | if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) | 3671 | if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) |
@@ -4403,22 +4323,51 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4403 | 4323 | ||
4404 | #region Helper Methods | 4324 | #region Helper Methods |
4405 | 4325 | ||
4406 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data) | 4326 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture) |
4407 | { | 4327 | { |
4408 | return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity, | 4328 | #region ScenePresence/SOP Handling |
4409 | data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry); | ||
4410 | } | ||
4411 | 4329 | ||
4412 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data) | 4330 | bool avatar = (entity is ScenePresence); |
4413 | { | 4331 | uint localID = entity.LocalId; |
4414 | return CreateImprovedTerseBlock(false, data.LocalID, data.AttachPoint, Vector4.Zero, data.Position, data.Velocity, | 4332 | uint attachPoint; |
4415 | data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry); | 4333 | Vector4 collisionPlane; |
4416 | } | 4334 | Vector3 position, velocity, acceleration, angularVelocity; |
4335 | Quaternion rotation; | ||
4336 | byte[] textureEntry; | ||
4337 | |||
4338 | if (entity is ScenePresence) | ||
4339 | { | ||
4340 | ScenePresence presence = (ScenePresence)entity; | ||
4341 | |||
4342 | attachPoint = 0; | ||
4343 | collisionPlane = presence.CollisionPlane; | ||
4344 | position = presence.OffsetPosition; | ||
4345 | velocity = presence.Velocity; | ||
4346 | acceleration = Vector3.Zero; | ||
4347 | angularVelocity = Vector3.Zero; | ||
4348 | rotation = presence.Rotation; | ||
4349 | |||
4350 | if (sendTexture) | ||
4351 | textureEntry = presence.Appearance.Texture.GetBytes(); | ||
4352 | else | ||
4353 | textureEntry = null; | ||
4354 | } | ||
4355 | else | ||
4356 | { | ||
4357 | SceneObjectPart part = (SceneObjectPart)entity; | ||
4358 | |||
4359 | attachPoint = part.AttachmentPoint; | ||
4360 | collisionPlane = Vector4.Zero; | ||
4361 | position = part.RelativePosition; | ||
4362 | velocity = part.Velocity; | ||
4363 | acceleration = part.Acceleration; | ||
4364 | angularVelocity = part.AngularVelocity; | ||
4365 | rotation = part.RotationOffset; | ||
4366 | textureEntry = part.Shape.TextureEntry; | ||
4367 | } | ||
4368 | |||
4369 | #endregion ScenePresence/SOP Handling | ||
4417 | 4370 | ||
4418 | protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, int attachPoint, | ||
4419 | Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation, | ||
4420 | Vector3 angularVelocity, byte[] textureEntry) | ||
4421 | { | ||
4422 | int pos = 0; | 4371 | int pos = 0; |
4423 | byte[] data = new byte[(avatar ? 60 : 44)]; | 4372 | byte[] data = new byte[(avatar ? 60 : 44)]; |
4424 | 4373 | ||
@@ -4490,12 +4439,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4490 | return block; | 4439 | return block; |
4491 | } | 4440 | } |
4492 | 4441 | ||
4493 | protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data) | 4442 | protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data) |
4494 | { | 4443 | { |
4495 | byte[] objectData = new byte[76]; | 4444 | byte[] objectData = new byte[76]; |
4496 | 4445 | ||
4497 | Vector4.UnitW.ToBytes(objectData, 0); // TODO: Collision plane support | 4446 | data.CollisionPlane.ToBytes(objectData, 0); |
4498 | data.Position.ToBytes(objectData, 16); | 4447 | data.OffsetPosition.ToBytes(objectData, 16); |
4499 | //data.Velocity.ToBytes(objectData, 28); | 4448 | //data.Velocity.ToBytes(objectData, 28); |
4500 | //data.Acceleration.ToBytes(objectData, 40); | 4449 | //data.Acceleration.ToBytes(objectData, 40); |
4501 | data.Rotation.ToBytes(objectData, 52); | 4450 | data.Rotation.ToBytes(objectData, 52); |
@@ -4505,12 +4454,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4505 | 4454 | ||
4506 | update.Data = Utils.EmptyBytes; | 4455 | update.Data = Utils.EmptyBytes; |
4507 | update.ExtraParams = new byte[1]; | 4456 | update.ExtraParams = new byte[1]; |
4508 | update.FullID = data.AvatarID; | 4457 | update.FullID = data.UUID; |
4509 | update.ID = data.AvatarLocalID; | 4458 | update.ID = data.LocalId; |
4510 | update.Material = (byte)Material.Flesh; | 4459 | update.Material = (byte)Material.Flesh; |
4511 | update.MediaURL = Utils.EmptyBytes; | 4460 | update.MediaURL = Utils.EmptyBytes; |
4512 | update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " + | 4461 | update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " + |
4513 | data.LastName + "\nTitle STRING RW SV " + data.GroupTitle); | 4462 | data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle); |
4514 | update.ObjectData = objectData; | 4463 | update.ObjectData = objectData; |
4515 | update.ParentID = data.ParentID; | 4464 | update.ParentID = data.ParentID; |
4516 | update.PathCurve = 16; | 4465 | update.PathCurve = 16; |
@@ -4519,102 +4468,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4519 | update.PCode = (byte)PCode.Avatar; | 4468 | update.PCode = (byte)PCode.Avatar; |
4520 | update.ProfileCurve = 1; | 4469 | update.ProfileCurve = 1; |
4521 | update.PSBlock = Utils.EmptyBytes; | 4470 | update.PSBlock = Utils.EmptyBytes; |
4522 | update.Scale = new Vector3(0.45f,0.6f,1.9f); | 4471 | update.Scale = new Vector3(0.45f, 0.6f, 1.9f); |
4523 | update.Text = Utils.EmptyBytes; | 4472 | update.Text = Utils.EmptyBytes; |
4524 | update.TextColor = new byte[4]; | 4473 | update.TextColor = new byte[4]; |
4525 | update.TextureAnim = Utils.EmptyBytes; | 4474 | update.TextureAnim = Utils.EmptyBytes; |
4526 | update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes; | 4475 | update.TextureEntry = (data.Appearance.Texture != null) ? data.Appearance.Texture.GetBytes() : Utils.EmptyBytes; |
4527 | update.UpdateFlags = (uint)(PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | PrimFlags.ObjectOwnerModify);//61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags | 4476 | update.UpdateFlags = (uint)( |
4477 | PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner | | ||
4478 | PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer | | ||
4479 | PrimFlags.ObjectOwnerModify); | ||
4528 | 4480 | ||
4529 | return update; | 4481 | return update; |
4530 | } | 4482 | } |
4531 | 4483 | ||
4532 | protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data) | 4484 | protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) |
4533 | { | 4485 | { |
4534 | byte[] objectData = new byte[60]; | 4486 | byte[] objectData = new byte[60]; |
4535 | data.pos.ToBytes(objectData, 0); | 4487 | data.RelativePosition.ToBytes(objectData, 0); |
4536 | data.vel.ToBytes(objectData, 12); | 4488 | data.Velocity.ToBytes(objectData, 12); |
4537 | data.acc.ToBytes(objectData, 24); | 4489 | data.Acceleration.ToBytes(objectData, 24); |
4538 | data.rotation.ToBytes(objectData, 36); | 4490 | data.RotationOffset.ToBytes(objectData, 36); |
4539 | data.rvel.ToBytes(objectData, 48); | 4491 | data.AngularVelocity.ToBytes(objectData, 48); |
4540 | 4492 | ||
4541 | ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); | 4493 | ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); |
4542 | update.ClickAction = (byte)data.clickAction; | 4494 | update.ClickAction = (byte)data.ClickAction; |
4543 | update.CRC = 0; | 4495 | update.CRC = 0; |
4544 | update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes; | 4496 | update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes; |
4545 | update.FullID = data.objectID; | 4497 | update.FullID = data.UUID; |
4546 | update.ID = data.localID; | 4498 | update.ID = data.LocalId; |
4547 | //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated | 4499 | //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated |
4548 | //update.JointPivot = Vector3.Zero; | 4500 | //update.JointPivot = Vector3.Zero; |
4549 | //update.JointType = 0; | 4501 | //update.JointType = 0; |
4550 | update.Material = data.material; | 4502 | update.Material = data.Material; |
4551 | update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim | 4503 | update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim |
4552 | if (data.attachment) | 4504 | if (data.IsAttachment) |
4553 | { | 4505 | { |
4554 | update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId); | 4506 | update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID); |
4555 | update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16)); | 4507 | update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16)); |
4556 | } | 4508 | } |
4557 | else | 4509 | else |
4558 | { | 4510 | { |
4559 | update.NameValue = Utils.EmptyBytes; | 4511 | update.NameValue = Utils.EmptyBytes; |
4560 | update.State = data.primShape.State; | 4512 | update.State = data.Shape.State; |
4561 | } | 4513 | } |
4514 | |||
4562 | update.ObjectData = objectData; | 4515 | update.ObjectData = objectData; |
4563 | update.ParentID = data.parentID; | 4516 | update.ParentID = data.ParentID; |
4564 | update.PathBegin = data.primShape.PathBegin; | 4517 | update.PathBegin = data.Shape.PathBegin; |
4565 | update.PathCurve = data.primShape.PathCurve; | 4518 | update.PathCurve = data.Shape.PathCurve; |
4566 | update.PathEnd = data.primShape.PathEnd; | 4519 | update.PathEnd = data.Shape.PathEnd; |
4567 | update.PathRadiusOffset = data.primShape.PathRadiusOffset; | 4520 | update.PathRadiusOffset = data.Shape.PathRadiusOffset; |
4568 | update.PathRevolutions = data.primShape.PathRevolutions; | 4521 | update.PathRevolutions = data.Shape.PathRevolutions; |
4569 | update.PathScaleX = data.primShape.PathScaleX; | 4522 | update.PathScaleX = data.Shape.PathScaleX; |
4570 | update.PathScaleY = data.primShape.PathScaleY; | 4523 | update.PathScaleY = data.Shape.PathScaleY; |
4571 | update.PathShearX = data.primShape.PathShearX; | 4524 | update.PathShearX = data.Shape.PathShearX; |
4572 | update.PathShearY = data.primShape.PathShearY; | 4525 | update.PathShearY = data.Shape.PathShearY; |
4573 | update.PathSkew = data.primShape.PathSkew; | 4526 | update.PathSkew = data.Shape.PathSkew; |
4574 | update.PathTaperX = data.primShape.PathTaperX; | 4527 | update.PathTaperX = data.Shape.PathTaperX; |
4575 | update.PathTaperY = data.primShape.PathTaperY; | 4528 | update.PathTaperY = data.Shape.PathTaperY; |
4576 | update.PathTwist = data.primShape.PathTwist; | 4529 | update.PathTwist = data.Shape.PathTwist; |
4577 | update.PathTwistBegin = data.primShape.PathTwistBegin; | 4530 | update.PathTwistBegin = data.Shape.PathTwistBegin; |
4578 | update.PCode = data.primShape.PCode; | 4531 | update.PCode = data.Shape.PCode; |
4579 | update.ProfileBegin = data.primShape.ProfileBegin; | 4532 | update.ProfileBegin = data.Shape.ProfileBegin; |
4580 | update.ProfileCurve = data.primShape.ProfileCurve; | 4533 | update.ProfileCurve = data.Shape.ProfileCurve; |
4581 | update.ProfileEnd = data.primShape.ProfileEnd; | 4534 | update.ProfileEnd = data.Shape.ProfileEnd; |
4582 | update.ProfileHollow = data.primShape.ProfileHollow; | 4535 | update.ProfileHollow = data.Shape.ProfileHollow; |
4583 | update.PSBlock = data.particleSystem ?? Utils.EmptyBytes; | 4536 | update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes; |
4584 | update.TextColor = data.color ?? Color4.Black.GetBytes(true); | 4537 | update.TextColor = data.GetTextColor().GetBytes(false); |
4585 | update.TextureAnim = data.textureanim ?? Utils.EmptyBytes; | 4538 | update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes; |
4586 | update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes; | 4539 | update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes; |
4587 | update.Scale = data.primShape.Scale; | 4540 | update.Scale = data.Shape.Scale; |
4588 | update.Text = Util.StringToBytes256(data.text); | 4541 | update.Text = Util.StringToBytes256(data.Text); |
4589 | update.UpdateFlags = (uint)data.flags; | 4542 | |
4590 | 4543 | #region PrimFlags | |
4591 | if (data.SoundId != UUID.Zero) | 4544 | |
4592 | { | 4545 | PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID); |
4593 | update.Sound = data.SoundId; | 4546 | |
4594 | update.OwnerID = data.ownerID; | 4547 | // Don't send the CreateSelected flag to everyone |
4595 | update.Gain = (float)data.SoundVolume; | 4548 | flags &= ~PrimFlags.CreateSelected; |
4549 | |||
4550 | if (recipientID == data.OwnerID) | ||
4551 | { | ||
4552 | if ((data.Flags & PrimFlags.CreateSelected) != 0) | ||
4553 | { | ||
4554 | // Only send this flag once, then unset it | ||
4555 | flags |= PrimFlags.CreateSelected; | ||
4556 | data.Flags &= ~PrimFlags.CreateSelected; | ||
4557 | } | ||
4558 | } | ||
4559 | |||
4560 | update.UpdateFlags = (uint)flags; | ||
4561 | |||
4562 | #endregion PrimFlags | ||
4563 | |||
4564 | if (data.Sound != UUID.Zero) | ||
4565 | { | ||
4566 | update.Sound = data.Sound; | ||
4567 | update.OwnerID = data.OwnerID; | ||
4568 | update.Gain = (float)data.SoundGain; | ||
4596 | update.Radius = (float)data.SoundRadius; | 4569 | update.Radius = (float)data.SoundRadius; |
4597 | update.Flags = data.SoundFlags; | 4570 | update.Flags = data.SoundFlags; |
4598 | } | 4571 | } |
4599 | 4572 | ||
4600 | switch ((PCode)data.primShape.PCode) | 4573 | switch ((PCode)data.Shape.PCode) |
4601 | { | 4574 | { |
4602 | case PCode.Grass: | 4575 | case PCode.Grass: |
4603 | case PCode.Tree: | 4576 | case PCode.Tree: |
4604 | case PCode.NewTree: | 4577 | case PCode.NewTree: |
4605 | update.Data = new byte[] { data.primShape.State }; | 4578 | update.Data = new byte[] { data.Shape.State }; |
4606 | break; | 4579 | break; |
4607 | default: | 4580 | default: |
4608 | // TODO: Support ScratchPad | ||
4609 | //if (prim.ScratchPad != null) | ||
4610 | //{ | ||
4611 | // update.Data = new byte[prim.ScratchPad.Length]; | ||
4612 | // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length); | ||
4613 | //} | ||
4614 | //else | ||
4615 | //{ | ||
4616 | // update.Data = Utils.EmptyBytes; | ||
4617 | //} | ||
4618 | update.Data = Utils.EmptyBytes; | 4581 | update.Data = Utils.EmptyBytes; |
4619 | break; | 4582 | break; |
4620 | } | 4583 | } |
@@ -4622,6 +4585,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
4622 | return update; | 4585 | return update; |
4623 | } | 4586 | } |
4624 | 4587 | ||
4588 | protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags) | ||
4589 | { | ||
4590 | // TODO: Implement this | ||
4591 | return null; | ||
4592 | } | ||
4593 | |||
4625 | public void SendNameReply(UUID profileId, string firstname, string lastname) | 4594 | public void SendNameReply(UUID profileId, string firstname, string lastname) |
4626 | { | 4595 | { |
4627 | UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); | 4596 | UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); |
@@ -11644,7 +11613,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11644 | throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); | 11613 | throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); |
11645 | } | 11614 | } |
11646 | 11615 | ||
11647 | internal TValue Dequeue() | 11616 | internal bool TryDequeue(out TValue value) |
11648 | { | 11617 | { |
11649 | for (int i = 0; i < m_heaps.Length; ++i) | 11618 | for (int i = 0; i < m_heaps.Length; ++i) |
11650 | { | 11619 | { |
@@ -11652,10 +11621,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP | |||
11652 | { | 11621 | { |
11653 | MinHeapItem item = m_heaps[i].RemoveMin(); | 11622 | MinHeapItem item = m_heaps[i].RemoveMin(); |
11654 | m_lookupTable.Remove(item.LocalID); | 11623 | m_lookupTable.Remove(item.LocalID); |
11655 | return item.Value; | 11624 | value = item.Value; |
11625 | return true; | ||
11656 | } | 11626 | } |
11657 | } | 11627 | } |
11658 | throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); | 11628 | |
11629 | value = default(TValue); | ||
11630 | return false; | ||
11659 | } | 11631 | } |
11660 | 11632 | ||
11661 | internal void Reprioritize(UpdatePriorityHandler handler) | 11633 | internal void Reprioritize(UpdatePriorityHandler handler) |