aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs630
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs18
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs4
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandChannel.cs16
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs10
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs14
-rw-r--r--OpenSim/Region/Framework/Interfaces/ILandChannel.cs3
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs114
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs36
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs29
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs34
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs14
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs10
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs82
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs4
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs15
18 files changed, 562 insertions, 479 deletions
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 1f3582c..07c3a6a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -50,43 +50,17 @@ using Nini.Config;
50 50
51namespace OpenSim.Region.ClientStack.LindenUDP 51namespace 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); 3504 }
3586// if (text.IndexOf("\n") >= 0) 3505 else
3587// text = text.Remove(text.IndexOf("\n")); 3506 {
3588// m_log.DebugFormat( 3507 if (updateFlags.HasFlag(PrimUpdateFlags.Velocity) ||
3589// "[CLIENT]: Sending full info about prim {0} text {1} to client {2}", 3508 updateFlags.HasFlag(PrimUpdateFlags.Acceleration) ||
3590// outPacket.ObjectData[i].ID, text, Name); 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));
3591 } 3551 }
3592// else 3552 else
3593// { 3553 {
3594// m_log.WarnFormat( 3554 terseUpdateBlocks.Value.Add(CreateImprovedTerseBlock(update.Entity, updateFlags.HasFlag(PrimUpdateFlags.Textures)));
3595// "[CLIENT]: Preventing full update for {0} after kill to {1}", block.ID, Name); 3555 }
3596// } 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];
3619 3577
3620 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data); 3578 OutPacket(packet, ThrottleOutPacketType.Task, true);
3579 }
3621 3580
3622 lock (m_primTerseUpdates.SyncRoot) 3581 if (compressedUpdateBlocks.IsValueCreated)
3623 m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID); 3582 {
3624 } 3583 List<ObjectUpdateCompressedPacket.ObjectDataBlock> blocks = compressedUpdateBlocks.Value;
3625 3584
3626 void ProcessPrimTerseUpdates() 3585 ObjectUpdateCompressedPacket packet = (ObjectUpdateCompressedPacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdateCompressed);
3627 { 3586 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3628 ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3587 packet.RegionData.TimeDilation = timeDilation;
3629 outPacket.Header.Reliable = false; 3588 packet.ObjectData = new ObjectUpdateCompressedPacket.ObjectDataBlock[blocks.Count];
3630 outPacket.Header.Zerocoded = true;
3631 3589
3632 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; 3590 for (int i = 0; i < blocks.Count; i++)
3633 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue); 3591 packet.ObjectData[i] = blocks[i];
3634 3592
3635 lock (m_primTerseUpdates.SyncRoot) 3593 OutPacket(packet, ThrottleOutPacketType.Task, true);
3594 }
3595
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)
3639 return;
3640 3599
3641 outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; 3600 ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket();
3642 for (int i = 0; i < count; i++) 3601 packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle;
3643 outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue(); 3602 packet.RegionData.TimeDilation = timeDilation;
3603 packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count];
3604
3605 for (int i = 0; i < blocks.Count; i++)
3606 packet.ObjectData[i] = blocks[i];
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,55 @@ 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
4367 if (sendTexture)
4368 textureEntry = part.Shape.TextureEntry;
4369 else
4370 textureEntry = null;
4371 }
4372
4373 #endregion ScenePresence/SOP Handling
4417 4374
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; 4375 int pos = 0;
4423 byte[] data = new byte[(avatar ? 60 : 44)]; 4376 byte[] data = new byte[(avatar ? 60 : 44)];
4424 4377
@@ -4490,12 +4443,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4490 return block; 4443 return block;
4491 } 4444 }
4492 4445
4493 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data) 4446 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(ScenePresence data)
4494 { 4447 {
4495 byte[] objectData = new byte[76]; 4448 byte[] objectData = new byte[76];
4496 4449
4497 Vector4.UnitW.ToBytes(objectData, 0); // TODO: Collision plane support 4450 data.CollisionPlane.ToBytes(objectData, 0);
4498 data.Position.ToBytes(objectData, 16); 4451 data.OffsetPosition.ToBytes(objectData, 16);
4499 //data.Velocity.ToBytes(objectData, 28); 4452 //data.Velocity.ToBytes(objectData, 28);
4500 //data.Acceleration.ToBytes(objectData, 40); 4453 //data.Acceleration.ToBytes(objectData, 40);
4501 data.Rotation.ToBytes(objectData, 52); 4454 data.Rotation.ToBytes(objectData, 52);
@@ -4505,12 +4458,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4505 4458
4506 update.Data = Utils.EmptyBytes; 4459 update.Data = Utils.EmptyBytes;
4507 update.ExtraParams = new byte[1]; 4460 update.ExtraParams = new byte[1];
4508 update.FullID = data.AvatarID; 4461 update.FullID = data.UUID;
4509 update.ID = data.AvatarLocalID; 4462 update.ID = data.LocalId;
4510 update.Material = (byte)Material.Flesh; 4463 update.Material = (byte)Material.Flesh;
4511 update.MediaURL = Utils.EmptyBytes; 4464 update.MediaURL = Utils.EmptyBytes;
4512 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " + 4465 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.Firstname + "\nLastName STRING RW SV " +
4513 data.LastName + "\nTitle STRING RW SV " + data.GroupTitle); 4466 data.Lastname + "\nTitle STRING RW SV " + data.Grouptitle);
4514 update.ObjectData = objectData; 4467 update.ObjectData = objectData;
4515 update.ParentID = data.ParentID; 4468 update.ParentID = data.ParentID;
4516 update.PathCurve = 16; 4469 update.PathCurve = 16;
@@ -4519,102 +4472,116 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4519 update.PCode = (byte)PCode.Avatar; 4472 update.PCode = (byte)PCode.Avatar;
4520 update.ProfileCurve = 1; 4473 update.ProfileCurve = 1;
4521 update.PSBlock = Utils.EmptyBytes; 4474 update.PSBlock = Utils.EmptyBytes;
4522 update.Scale = new Vector3(0.45f,0.6f,1.9f); 4475 update.Scale = new Vector3(0.45f, 0.6f, 1.9f);
4523 update.Text = Utils.EmptyBytes; 4476 update.Text = Utils.EmptyBytes;
4524 update.TextColor = new byte[4]; 4477 update.TextColor = new byte[4];
4525 update.TextureAnim = Utils.EmptyBytes; 4478 update.TextureAnim = Utils.EmptyBytes;
4526 update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes; 4479 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 4480 update.UpdateFlags = (uint)(
4481 PrimFlags.Physics | PrimFlags.ObjectModify | PrimFlags.ObjectCopy | PrimFlags.ObjectAnyOwner |
4482 PrimFlags.ObjectYouOwner | PrimFlags.ObjectMove | PrimFlags.InventoryEmpty | PrimFlags.ObjectTransfer |
4483 PrimFlags.ObjectOwnerModify);
4528 4484
4529 return update; 4485 return update;
4530 } 4486 }
4531 4487
4532 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data) 4488 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID)
4533 { 4489 {
4534 byte[] objectData = new byte[60]; 4490 byte[] objectData = new byte[60];
4535 data.pos.ToBytes(objectData, 0); 4491 data.RelativePosition.ToBytes(objectData, 0);
4536 data.vel.ToBytes(objectData, 12); 4492 data.Velocity.ToBytes(objectData, 12);
4537 data.acc.ToBytes(objectData, 24); 4493 data.Acceleration.ToBytes(objectData, 24);
4538 data.rotation.ToBytes(objectData, 36); 4494 data.RotationOffset.ToBytes(objectData, 36);
4539 data.rvel.ToBytes(objectData, 48); 4495 data.AngularVelocity.ToBytes(objectData, 48);
4540 4496
4541 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); 4497 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4542 update.ClickAction = (byte)data.clickAction; 4498 update.ClickAction = (byte)data.ClickAction;
4543 update.CRC = 0; 4499 update.CRC = 0;
4544 update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes; 4500 update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes;
4545 update.FullID = data.objectID; 4501 update.FullID = data.UUID;
4546 update.ID = data.localID; 4502 update.ID = data.LocalId;
4547 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated 4503 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
4548 //update.JointPivot = Vector3.Zero; 4504 //update.JointPivot = Vector3.Zero;
4549 //update.JointType = 0; 4505 //update.JointType = 0;
4550 update.Material = data.material; 4506 update.Material = data.Material;
4551 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim 4507 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
4552 if (data.attachment) 4508 if (data.IsAttachment)
4553 { 4509 {
4554 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId); 4510 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.FromItemID);
4555 update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16)); 4511 update.State = (byte)((data.AttachmentPoint % 16) * 16 + (data.AttachmentPoint / 16));
4556 } 4512 }
4557 else 4513 else
4558 { 4514 {
4559 update.NameValue = Utils.EmptyBytes; 4515 update.NameValue = Utils.EmptyBytes;
4560 update.State = data.primShape.State; 4516 update.State = data.Shape.State;
4561 } 4517 }
4518
4562 update.ObjectData = objectData; 4519 update.ObjectData = objectData;
4563 update.ParentID = data.parentID; 4520 update.ParentID = data.ParentID;
4564 update.PathBegin = data.primShape.PathBegin; 4521 update.PathBegin = data.Shape.PathBegin;
4565 update.PathCurve = data.primShape.PathCurve; 4522 update.PathCurve = data.Shape.PathCurve;
4566 update.PathEnd = data.primShape.PathEnd; 4523 update.PathEnd = data.Shape.PathEnd;
4567 update.PathRadiusOffset = data.primShape.PathRadiusOffset; 4524 update.PathRadiusOffset = data.Shape.PathRadiusOffset;
4568 update.PathRevolutions = data.primShape.PathRevolutions; 4525 update.PathRevolutions = data.Shape.PathRevolutions;
4569 update.PathScaleX = data.primShape.PathScaleX; 4526 update.PathScaleX = data.Shape.PathScaleX;
4570 update.PathScaleY = data.primShape.PathScaleY; 4527 update.PathScaleY = data.Shape.PathScaleY;
4571 update.PathShearX = data.primShape.PathShearX; 4528 update.PathShearX = data.Shape.PathShearX;
4572 update.PathShearY = data.primShape.PathShearY; 4529 update.PathShearY = data.Shape.PathShearY;
4573 update.PathSkew = data.primShape.PathSkew; 4530 update.PathSkew = data.Shape.PathSkew;
4574 update.PathTaperX = data.primShape.PathTaperX; 4531 update.PathTaperX = data.Shape.PathTaperX;
4575 update.PathTaperY = data.primShape.PathTaperY; 4532 update.PathTaperY = data.Shape.PathTaperY;
4576 update.PathTwist = data.primShape.PathTwist; 4533 update.PathTwist = data.Shape.PathTwist;
4577 update.PathTwistBegin = data.primShape.PathTwistBegin; 4534 update.PathTwistBegin = data.Shape.PathTwistBegin;
4578 update.PCode = data.primShape.PCode; 4535 update.PCode = data.Shape.PCode;
4579 update.ProfileBegin = data.primShape.ProfileBegin; 4536 update.ProfileBegin = data.Shape.ProfileBegin;
4580 update.ProfileCurve = data.primShape.ProfileCurve; 4537 update.ProfileCurve = data.Shape.ProfileCurve;
4581 update.ProfileEnd = data.primShape.ProfileEnd; 4538 update.ProfileEnd = data.Shape.ProfileEnd;
4582 update.ProfileHollow = data.primShape.ProfileHollow; 4539 update.ProfileHollow = data.Shape.ProfileHollow;
4583 update.PSBlock = data.particleSystem ?? Utils.EmptyBytes; 4540 update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes;
4584 update.TextColor = data.color ?? Color4.Black.GetBytes(true); 4541 update.TextColor = data.GetTextColor().GetBytes(false);
4585 update.TextureAnim = data.textureanim ?? Utils.EmptyBytes; 4542 update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes;
4586 update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes; 4543 update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes;
4587 update.Scale = data.primShape.Scale; 4544 update.Scale = data.Shape.Scale;
4588 update.Text = Util.StringToBytes256(data.text); 4545 update.Text = Util.StringToBytes256(data.Text);
4589 update.UpdateFlags = (uint)data.flags; 4546
4590 4547 #region PrimFlags
4591 if (data.SoundId != UUID.Zero) 4548
4592 { 4549 PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID);
4593 update.Sound = data.SoundId; 4550
4594 update.OwnerID = data.ownerID; 4551 // Don't send the CreateSelected flag to everyone
4595 update.Gain = (float)data.SoundVolume; 4552 flags &= ~PrimFlags.CreateSelected;
4553
4554 if (recipientID == data.OwnerID)
4555 {
4556 if ((data.Flags & PrimFlags.CreateSelected) != 0)
4557 {
4558 // Only send this flag once, then unset it
4559 flags |= PrimFlags.CreateSelected;
4560 data.Flags &= ~PrimFlags.CreateSelected;
4561 }
4562 }
4563
4564 update.UpdateFlags = (uint)flags;
4565
4566 #endregion PrimFlags
4567
4568 if (data.Sound != UUID.Zero)
4569 {
4570 update.Sound = data.Sound;
4571 update.OwnerID = data.OwnerID;
4572 update.Gain = (float)data.SoundGain;
4596 update.Radius = (float)data.SoundRadius; 4573 update.Radius = (float)data.SoundRadius;
4597 update.Flags = data.SoundFlags; 4574 update.Flags = data.SoundFlags;
4598 } 4575 }
4599 4576
4600 switch ((PCode)data.primShape.PCode) 4577 switch ((PCode)data.Shape.PCode)
4601 { 4578 {
4602 case PCode.Grass: 4579 case PCode.Grass:
4603 case PCode.Tree: 4580 case PCode.Tree:
4604 case PCode.NewTree: 4581 case PCode.NewTree:
4605 update.Data = new byte[] { data.primShape.State }; 4582 update.Data = new byte[] { data.Shape.State };
4606 break; 4583 break;
4607 default: 4584 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; 4585 update.Data = Utils.EmptyBytes;
4619 break; 4586 break;
4620 } 4587 }
@@ -4622,6 +4589,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4622 return update; 4589 return update;
4623 } 4590 }
4624 4591
4592 protected ObjectUpdateCompressedPacket.ObjectDataBlock CreateCompressedUpdateBlock(SceneObjectPart part, PrimUpdateFlags updateFlags)
4593 {
4594 // TODO: Implement this
4595 return null;
4596 }
4597
4625 public void SendNameReply(UUID profileId, string firstname, string lastname) 4598 public void SendNameReply(UUID profileId, string firstname, string lastname)
4626 { 4599 {
4627 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply); 4600 UUIDNameReplyPacket packet = (UUIDNameReplyPacket)PacketPool.Instance.GetPacket(PacketType.UUIDNameReply);
@@ -11644,7 +11617,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11644 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); 11617 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
11645 } 11618 }
11646 11619
11647 internal TValue Dequeue() 11620 internal bool TryDequeue(out TValue value)
11648 { 11621 {
11649 for (int i = 0; i < m_heaps.Length; ++i) 11622 for (int i = 0; i < m_heaps.Length; ++i)
11650 { 11623 {
@@ -11652,10 +11625,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
11652 { 11625 {
11653 MinHeapItem item = m_heaps[i].RemoveMin(); 11626 MinHeapItem item = m_heaps[i].RemoveMin();
11654 m_lookupTable.Remove(item.LocalID); 11627 m_lookupTable.Remove(item.LocalID);
11655 return item.Value; 11628 value = item.Value;
11629 return true;
11656 } 11630 }
11657 } 11631 }
11658 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString())); 11632
11633 value = default(TValue);
11634 return false;
11659 } 11635 }
11660 11636
11661 internal void Reprioritize(UpdatePriorityHandler handler) 11637 internal void Reprioritize(UpdatePriorityHandler handler)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 41e41e4..1b81105 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -99,15 +99,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
99 99
100 /// <summary>The measured resolution of Environment.TickCount</summary> 100 /// <summary>The measured resolution of Environment.TickCount</summary>
101 public readonly float TickCountResolution; 101 public readonly float TickCountResolution;
102 /// <summary>Number of terse prim updates to put on the queue each time the 102 /// <summary>Number of prim updates to put on the queue each time the
103 /// OnQueueEmpty event is triggered for updates</summary> 103 /// OnQueueEmpty event is triggered for updates</summary>
104 public readonly int PrimTerseUpdatesPerPacket; 104 public readonly int PrimUpdatesPerCallback;
105 /// <summary>Number of terse avatar updates to put on the queue each time the
106 /// OnQueueEmpty event is triggered for updates</summary>
107 public readonly int AvatarTerseUpdatesPerPacket;
108 /// <summary>Number of full prim updates to put on the queue each time the
109 /// OnQueueEmpty event is triggered for updates</summary>
110 public readonly int PrimFullUpdatesPerPacket;
111 /// <summary>Number of texture packets to put on the queue each time the 105 /// <summary>Number of texture packets to put on the queue each time the
112 /// OnQueueEmpty event is triggered for textures</summary> 106 /// OnQueueEmpty event is triggered for textures</summary>
113 public readonly int TextureSendLimit; 107 public readonly int TextureSendLimit;
@@ -191,9 +185,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
191 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); 185 m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0);
192 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); 186 sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0);
193 187
194 PrimTerseUpdatesPerPacket = config.GetInt("PrimTerseUpdatesPerPacket", 25); 188 PrimUpdatesPerCallback = config.GetInt("PrimUpdatesPerCallback", 100);
195 AvatarTerseUpdatesPerPacket = config.GetInt("AvatarTerseUpdatesPerPacket", 10);
196 PrimFullUpdatesPerPacket = config.GetInt("PrimFullUpdatesPerPacket", 100);
197 TextureSendLimit = config.GetInt("TextureSendLimit", 20); 189 TextureSendLimit = config.GetInt("TextureSendLimit", 20);
198 190
199 m_defaultRTO = config.GetInt("DefaultRTO", 0); 191 m_defaultRTO = config.GetInt("DefaultRTO", 0);
@@ -201,9 +193,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
201 } 193 }
202 else 194 else
203 { 195 {
204 PrimTerseUpdatesPerPacket = 25; 196 PrimUpdatesPerCallback = 100;
205 AvatarTerseUpdatesPerPacket = 10;
206 PrimFullUpdatesPerPacket = 100;
207 TextureSendLimit = 20; 197 TextureSendLimit = 20;
208 } 198 }
209 199
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
index 6c01927..7d2dc5a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs
@@ -72,7 +72,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
72 { 72 {
73 m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); 73 m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName);
74 74
75 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 75 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
76 } 76 }
77 77
78 public void OnNewClient(IClientAPI client) 78 public void OnNewClient(IClientAPI client)
@@ -109,7 +109,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
109 { 109 {
110 // TODO: grab the parcel ID from ILandModule 110 // TODO: grab the parcel ID from ILandModule
111 // and send that along 111 // and send that along
112 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); 112 m_GridUserService.SetLastPosition(sp.UUID.ToString(), sp.ControllingClient.SessionId, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat);
113 } 113 }
114 114
115 } 115 }
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
index d914a57..76e030f 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs
@@ -162,9 +162,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
162 return m_GridUserService.SetHome(userID, homeID, homePosition, homeLookAt); 162 return m_GridUserService.SetHome(userID, homeID, homePosition, homeLookAt);
163 } 163 }
164 164
165 public bool SetLastPosition(string userID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt) 165 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt)
166 { 166 {
167 return m_GridUserService.SetLastPosition(userID, regionID, lastPosition, lastLookAt); 167 return m_GridUserService.SetLastPosition(userID, sessionID, regionID, lastPosition, lastLookAt);
168 } 168 }
169 169
170 public GridUserInfo GetGridUserInfo(string userID) 170 public GridUserInfo GetGridUserInfo(string userID)
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
index e3e2e61..fb11e9a 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs
@@ -137,9 +137,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser
137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); 137 return m_RemoteConnector.SetHome(userID, regionID, position, lookAt);
138 } 138 }
139 139
140 public bool SetLastPosition(string userID, UUID regionID, Vector3 position, Vector3 lookAt) 140 public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt)
141 { 141 {
142 return m_RemoteConnector.SetLastPosition(userID, regionID, position, lookAt); 142 return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt);
143 } 143 }
144 144
145 public GridUserInfo GetGridUserInfo(string userID) 145 public GridUserInfo GetGridUserInfo(string userID)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
index 1fbc733..1ad4db2 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs
@@ -154,6 +154,22 @@ namespace OpenSim.Region.CoreModules.World.Land
154 m_landManagementModule.UpdateLandObject(localID, data); 154 m_landManagementModule.UpdateLandObject(localID, data);
155 } 155 }
156 } 156 }
157
158 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
159 {
160 if (m_landManagementModule != null)
161 {
162 m_landManagementModule.Join(start_x, start_y, end_x, end_y, attempting_user_id);
163 }
164 }
165
166 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
167 {
168 if (m_landManagementModule != null)
169 {
170 m_landManagementModule.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
171 }
172 }
157 173
158 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 174 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
159 { 175 {
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 139e6ff..4ccd0f0 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -948,6 +948,16 @@ namespace OpenSim.Region.CoreModules.World.Land
948 masterLandObject.SendLandUpdateToAvatarsOverMe(); 948 masterLandObject.SendLandUpdateToAvatarsOverMe();
949 } 949 }
950 950
951 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
952 {
953 join(start_x, start_y, end_x, end_y, attempting_user_id);
954 }
955
956 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
957 {
958 subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
959 }
960
951 #endregion 961 #endregion
952 962
953 #region Parcel Updating 963 #region Parcel Updating
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index 09611af..aac47d1 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -528,14 +528,6 @@ namespace OpenSim.Region.Examples.SimpleModule
528 { 528 {
529 } 529 }
530 530
531 public virtual void SendAvatarData(SendAvatarData data)
532 {
533 }
534
535 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
536 {
537 }
538
539 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 531 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
540 { 532 {
541 } 533 }
@@ -548,15 +540,15 @@ namespace OpenSim.Region.Examples.SimpleModule
548 { 540 {
549 } 541 }
550 542
551 public virtual void SendPrimitiveToClient(SendPrimitiveData data) 543 public void SendAvatarDataImmediate(ISceneEntity avatar)
552 { 544 {
553 } 545 }
554 546
555 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data) 547 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
556 { 548 {
557 } 549 }
558 550
559 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 551 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
560 { 552 {
561 } 553 }
562 554
diff --git a/OpenSim/Region/Framework/Interfaces/ILandChannel.cs b/OpenSim/Region/Framework/Interfaces/ILandChannel.cs
index f71e31d..20b8ab6 100644
--- a/OpenSim/Region/Framework/Interfaces/ILandChannel.cs
+++ b/OpenSim/Region/Framework/Interfaces/ILandChannel.cs
@@ -76,5 +76,8 @@ namespace OpenSim.Region.Framework.Interfaces
76 void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel); 76 void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel);
77 void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel); 77 void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel);
78 void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime); 78 void SetParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime);
79
80 void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id);
81 void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id);
79 } 82 }
80} 83}
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index ce11267..ef13c98 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -68,8 +68,9 @@ namespace OpenSim.Region.Framework.Scenes
68 68
69 #region Fields 69 #region Fields
70 70
71 protected Dictionary<UUID, ScenePresence> m_scenePresences = new Dictionary<UUID, ScenePresence>(); 71 protected object m_presenceLock = new object();
72 protected ScenePresence[] m_scenePresenceArray = new ScenePresence[0]; 72 protected Dictionary<UUID, ScenePresence> m_scenePresenceMap = new Dictionary<UUID, ScenePresence>();
73 protected List<ScenePresence> m_scenePresenceArray = new List<ScenePresence>();
73 74
74 // SceneObjects is not currently populated or used. 75 // SceneObjects is not currently populated or used.
75 //public Dictionary<UUID, SceneObjectGroup> SceneObjects; 76 //public Dictionary<UUID, SceneObjectGroup> SceneObjects;
@@ -132,10 +133,12 @@ namespace OpenSim.Region.Framework.Scenes
132 133
133 protected internal void Close() 134 protected internal void Close()
134 { 135 {
135 lock (m_scenePresences) 136 lock (m_presenceLock)
136 { 137 {
137 m_scenePresences.Clear(); 138 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>();
138 m_scenePresenceArray = new ScenePresence[0]; 139 List<ScenePresence> newlist = new List<ScenePresence>();
140 m_scenePresenceMap = newmap;
141 m_scenePresenceArray = newlist;
139 } 142 }
140 143
141 lock (m_dictionary_lock) 144 lock (m_dictionary_lock)
@@ -518,34 +521,29 @@ namespace OpenSim.Region.Framework.Scenes
518 521
519 Entities[presence.UUID] = presence; 522 Entities[presence.UUID] = presence;
520 523
521 lock (m_scenePresences) 524 lock (m_presenceLock)
522 { 525 {
523 if (!m_scenePresences.ContainsKey(presence.UUID)) 526 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
527 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
528
529 if (!newmap.ContainsKey(presence.UUID))
524 { 530 {
525 m_scenePresences.Add(presence.UUID, presence); 531 newmap.Add(presence.UUID, presence);
526 532 newlist.Add(presence);
527 // Create a new array of ScenePresence references
528 int oldLength = m_scenePresenceArray.Length;
529 ScenePresence[] newArray = new ScenePresence[oldLength + 1];
530 Array.Copy(m_scenePresenceArray, newArray, oldLength);
531 newArray[oldLength] = presence;
532 m_scenePresenceArray = newArray;
533 } 533 }
534 else 534 else
535 { 535 {
536 m_scenePresences[presence.UUID] = presence; 536 // Remember the old presene reference from the dictionary
537 537 ScenePresence oldref = newmap[presence.UUID];
538 // Do a linear search through the array of ScenePresence references 538 // Replace the presence reference in the dictionary with the new value
539 // and update the modified entry 539 newmap[presence.UUID] = presence;
540 for (int i = 0; i < m_scenePresenceArray.Length; i++) 540 // Find the index in the list where the old ref was stored and update the reference
541 { 541 newlist[newlist.IndexOf(oldref)] = presence;
542 if (m_scenePresenceArray[i].UUID == presence.UUID)
543 {
544 m_scenePresenceArray[i] = presence;
545 break;
546 }
547 }
548 } 542 }
543
544 // Swap out the dictionary and list with new references
545 m_scenePresenceMap = newmap;
546 m_scenePresenceArray = newlist;
549 } 547 }
550 } 548 }
551 549
@@ -561,25 +559,21 @@ namespace OpenSim.Region.Framework.Scenes
561 agentID); 559 agentID);
562 } 560 }
563 561
564 lock (m_scenePresences) 562 lock (m_presenceLock)
565 { 563 {
566 if (m_scenePresences.Remove(agentID)) 564 Dictionary<UUID, ScenePresence> newmap = new Dictionary<UUID, ScenePresence>(m_scenePresenceMap);
565 List<ScenePresence> newlist = new List<ScenePresence>(m_scenePresenceArray);
566
567 // Remember the old presene reference from the dictionary
568 ScenePresence oldref = newmap[agentID];
569 // Remove the presence reference from the dictionary
570 if (newmap.Remove(agentID))
567 { 571 {
568 // Copy all of the elements from the previous array 572 // Find the index in the list where the old ref was stored and remove the reference
569 // into the new array except the removed element 573 newlist.RemoveAt(newlist.IndexOf(oldref));
570 int oldLength = m_scenePresenceArray.Length; 574 // Swap out the dictionary and list with new references
571 ScenePresence[] newArray = new ScenePresence[oldLength - 1]; 575 m_scenePresenceMap = newmap;
572 int j = 0; 576 m_scenePresenceArray = newlist;
573 for (int i = 0; i < m_scenePresenceArray.Length; i++)
574 {
575 ScenePresence presence = m_scenePresenceArray[i];
576 if (presence.UUID != agentID)
577 {
578 newArray[j] = presence;
579 ++j;
580 }
581 }
582 m_scenePresenceArray = newArray;
583 } 577 }
584 else 578 else
585 { 579 {
@@ -698,7 +692,7 @@ namespace OpenSim.Region.Framework.Scenes
698 } 692 }
699 693
700 /// <summary> 694 /// <summary>
701 /// Request a copy of m_scenePresences in this World 695 /// Get a reference to the scene presence list. Changes to the list will be done in a copy
702 /// There is no guarantee that presences will remain in the scene after the list is returned. 696 /// There is no guarantee that presences will remain in the scene after the list is returned.
703 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead 697 /// This list should remain private to SceneGraph. Callers wishing to iterate should instead
704 /// pass a delegate to ForEachScenePresence. 698 /// pass a delegate to ForEachScenePresence.
@@ -706,8 +700,7 @@ namespace OpenSim.Region.Framework.Scenes
706 /// <returns></returns> 700 /// <returns></returns>
707 private List<ScenePresence> GetScenePresences() 701 private List<ScenePresence> GetScenePresences()
708 { 702 {
709 lock (m_scenePresences) 703 return m_scenePresenceArray;
710 return new List<ScenePresence>(m_scenePresenceArray);
711 } 704 }
712 705
713 /// <summary> 706 /// <summary>
@@ -717,12 +710,10 @@ namespace OpenSim.Region.Framework.Scenes
717 /// <returns>null if the presence was not found</returns> 710 /// <returns>null if the presence was not found</returns>
718 protected internal ScenePresence GetScenePresence(UUID agentID) 711 protected internal ScenePresence GetScenePresence(UUID agentID)
719 { 712 {
720 ScenePresence sp; 713 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
721 lock (m_scenePresences) 714 ScenePresence presence;
722 { 715 presences.TryGetValue(agentID, out presence);
723 m_scenePresences.TryGetValue(agentID, out sp); 716 return presence;
724 }
725 return sp;
726 } 717 }
727 718
728 /// <summary> 719 /// <summary>
@@ -733,7 +724,8 @@ namespace OpenSim.Region.Framework.Scenes
733 /// <returns>null if the presence was not found</returns> 724 /// <returns>null if the presence was not found</returns>
734 protected internal ScenePresence GetScenePresence(string firstName, string lastName) 725 protected internal ScenePresence GetScenePresence(string firstName, string lastName)
735 { 726 {
736 foreach (ScenePresence presence in GetScenePresences()) 727 List<ScenePresence> presences = GetScenePresences();
728 foreach (ScenePresence presence in presences)
737 { 729 {
738 if (presence.Firstname == firstName && presence.Lastname == lastName) 730 if (presence.Firstname == firstName && presence.Lastname == lastName)
739 return presence; 731 return presence;
@@ -748,7 +740,8 @@ namespace OpenSim.Region.Framework.Scenes
748 /// <returns>null if the presence was not found</returns> 740 /// <returns>null if the presence was not found</returns>
749 protected internal ScenePresence GetScenePresence(uint localID) 741 protected internal ScenePresence GetScenePresence(uint localID)
750 { 742 {
751 foreach (ScenePresence presence in GetScenePresences()) 743 List<ScenePresence> presences = GetScenePresences();
744 foreach (ScenePresence presence in presences)
752 if (presence.LocalId == localID) 745 if (presence.LocalId == localID)
753 return presence; 746 return presence;
754 return null; 747 return null;
@@ -756,10 +749,8 @@ namespace OpenSim.Region.Framework.Scenes
756 749
757 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar) 750 protected internal bool TryGetScenePresence(UUID agentID, out ScenePresence avatar)
758 { 751 {
759 lock (m_scenePresences) 752 Dictionary<UUID, ScenePresence> presences = m_scenePresenceMap;
760 { 753 presences.TryGetValue(agentID, out avatar);
761 m_scenePresences.TryGetValue(agentID, out avatar);
762 }
763 return (avatar != null); 754 return (avatar != null);
764 } 755 }
765 756
@@ -1036,8 +1027,9 @@ namespace OpenSim.Region.Framework.Scenes
1036 }); 1027 });
1037 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); 1028 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
1038 */ 1029 */
1039 // For now, perform actiona serially 1030 // For now, perform actions serially
1040 foreach (ScenePresence sp in GetScenePresences()) 1031 List<ScenePresence> presences = GetScenePresences();
1032 foreach (ScenePresence sp in presences)
1041 { 1033 {
1042 try 1034 try
1043 { 1035 {
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 46eadee..71c8018 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -104,7 +104,7 @@ namespace OpenSim.Region.Framework.Scenes
104 104
105 #endregion Enumerations 105 #endregion Enumerations
106 106
107 public class SceneObjectPart : IScriptHost 107 public class SceneObjectPart : IScriptHost, ISceneEntity
108 { 108 {
109 /// <value> 109 /// <value>
110 /// Denote all sides of the prim 110 /// Denote all sides of the prim
@@ -712,6 +712,24 @@ namespace OpenSim.Region.Framework.Scenes
712 } 712 }
713 } 713 }
714 714
715 public Vector3 RelativePosition
716 {
717 get
718 {
719 if (IsRoot)
720 {
721 if (IsAttachment)
722 return AttachedPos;
723 else
724 return AbsolutePosition;
725 }
726 else
727 {
728 return OffsetPosition;
729 }
730 }
731 }
732
715 public Quaternion RotationOffset 733 public Quaternion RotationOffset
716 { 734 {
717 get 735 get
@@ -973,7 +991,6 @@ namespace OpenSim.Region.Framework.Scenes
973 get { return AggregateScriptEvents; } 991 get { return AggregateScriptEvents; }
974 } 992 }
975 993
976
977 public Quaternion SitTargetOrientation 994 public Quaternion SitTargetOrientation
978 { 995 {
979 get { return m_sitTargetOrientation; } 996 get { return m_sitTargetOrientation; }
@@ -2925,11 +2942,7 @@ namespace OpenSim.Region.Framework.Scenes
2925 //if (LocalId != ParentGroup.RootPart.LocalId) 2942 //if (LocalId != ParentGroup.RootPart.LocalId)
2926 //isattachment = ParentGroup.RootPart.IsAttachment; 2943 //isattachment = ParentGroup.RootPart.IsAttachment;
2927 2944
2928 byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A}; 2945 remoteClient.SendPrimUpdate(this, PrimUpdateFlags.FullUpdate);
2929 remoteClient.SendPrimitiveToClient(new SendPrimitiveData(m_regionHandle, m_parentGroup.GetTimeDilation(), LocalId, m_shape,
2930 lPos, Velocity, Acceleration, RotationOffset, AngularVelocity, clientFlags, m_uuid, _ownerID,
2931 m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment,
2932 AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, ParentGroup.GetUpdatePriority(remoteClient)));
2933 } 2946 }
2934 2947
2935 /// <summary> 2948 /// <summary>
@@ -4640,11 +4653,7 @@ namespace OpenSim.Region.Framework.Scenes
4640 4653
4641 // Causes this thread to dig into the Client Thread Data. 4654 // Causes this thread to dig into the Client Thread Data.
4642 // Remember your locking here! 4655 // Remember your locking here!
4643 remoteClient.SendPrimTerseUpdate(new SendPrimitiveTerseData(m_regionHandle, 4656 remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
4644 m_parentGroup.GetTimeDilation(), LocalId, lPos,
4645 RotationOffset, Velocity, Acceleration,
4646 AngularVelocity, FromItemID,
4647 OwnerID, (int)AttachmentPoint, null, ParentGroup.GetUpdatePriority(remoteClient)));
4648 } 4657 }
4649 4658
4650 public void AddScriptLPS(int count) 4659 public void AddScriptLPS(int count)
@@ -4694,7 +4703,8 @@ namespace OpenSim.Region.Framework.Scenes
4694 4703
4695 public Color4 GetTextColor() 4704 public Color4 GetTextColor()
4696 { 4705 {
4697 return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A)); 4706 Color color = Color;
4707 return new Color4(color.R, color.G, color.B, (byte)(0xFF - color.A));
4698 } 4708 }
4699 } 4709 }
4700} 4710}
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 30eafd7..ee0eb07 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Scenes
67 67
68 public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence); 68 public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence);
69 69
70 public class ScenePresence : EntityBase 70 public class ScenePresence : EntityBase, ISceneEntity
71 { 71 {
72// ~ScenePresence() 72// ~ScenePresence()
73// { 73// {
@@ -478,6 +478,12 @@ namespace OpenSim.Region.Framework.Scenes
478 } 478 }
479 } 479 }
480 480
481 public Vector3 OffsetPosition
482 {
483 get { return m_pos; }
484 set { m_pos = value; }
485 }
486
481 /// <summary> 487 /// <summary>
482 /// Current velocity of the avatar. 488 /// Current velocity of the avatar.
483 /// </summary> 489 /// </summary>
@@ -1036,8 +1042,9 @@ namespace OpenSim.Region.Framework.Scenes
1036 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); 1042 AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f));
1037 } 1043 }
1038 1044
1039 ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 1045 ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position);
1040 AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); 1046 //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
1047 // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient)));
1041 } 1048 }
1042 1049
1043 public void AddNeighbourRegion(ulong regionHandle, string cap) 1050 public void AddNeighbourRegion(ulong regionHandle, string cap)
@@ -2360,8 +2367,7 @@ namespace OpenSim.Region.Framework.Scenes
2360 2367
2361 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity); 2368 //m_log.DebugFormat("[SCENEPRESENCE]: TerseUpdate: Pos={0} Rot={1} Vel={2}", m_pos, m_bodyRot, m_velocity);
2362 2369
2363 remoteClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, 2370 remoteClient.SendPrimUpdate(this, PrimUpdateFlags.Position | PrimUpdateFlags.Rotation | PrimUpdateFlags.Velocity | PrimUpdateFlags.Acceleration | PrimUpdateFlags.AngularVelocity);
2364 pos, velocity, Vector3.Zero, m_bodyRot, CollisionPlane, m_uuid, null, GetUpdatePriority(remoteClient)));
2365 2371
2366 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); 2372 m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS));
2367 m_scene.StatsReporter.AddAgentUpdates(1); 2373 m_scene.StatsReporter.AddAgentUpdates(1);
@@ -2457,9 +2463,7 @@ namespace OpenSim.Region.Framework.Scenes
2457 Vector3 pos = m_pos; 2463 Vector3 pos = m_pos;
2458 pos.Z += m_appearance.HipOffset; 2464 pos.Z += m_appearance.HipOffset;
2459 2465
2460 remoteAvatar.m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, 2466 remoteAvatar.m_controllingClient.SendAvatarDataImmediate(this);
2461 LocalId, pos, m_appearance.Texture.GetBytes(),
2462 m_parentID, m_bodyRot));
2463 m_scene.StatsReporter.AddAgentUpdates(1); 2467 m_scene.StatsReporter.AddAgentUpdates(1);
2464 } 2468 }
2465 2469
@@ -2527,8 +2531,7 @@ namespace OpenSim.Region.Framework.Scenes
2527 Vector3 pos = m_pos; 2531 Vector3 pos = m_pos;
2528 pos.Z += m_appearance.HipOffset; 2532 pos.Z += m_appearance.HipOffset;
2529 2533
2530 m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2534 m_controllingClient.SendAvatarDataImmediate(this);
2531 pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
2532 2535
2533 SendInitialFullUpdateToAllClients(); 2536 SendInitialFullUpdateToAllClients();
2534 SendAppearanceToAllOtherAgents(); 2537 SendAppearanceToAllOtherAgents();
@@ -2638,9 +2641,7 @@ namespace OpenSim.Region.Framework.Scenes
2638 Vector3 pos = m_pos; 2641 Vector3 pos = m_pos;
2639 pos.Z += m_appearance.HipOffset; 2642 pos.Z += m_appearance.HipOffset;
2640 2643
2641 m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2644 m_controllingClient.SendAvatarDataImmediate(this);
2642 pos, m_appearance.Texture.GetBytes(), m_parentID, m_bodyRot));
2643
2644 } 2645 }
2645 2646
2646 public void SetWearable(int wearableId, AvatarWearable wearable) 2647 public void SetWearable(int wearableId, AvatarWearable wearable)
@@ -3906,7 +3907,7 @@ namespace OpenSim.Region.Framework.Scenes
3906 3907
3907 private void Reprioritize(object sender, ElapsedEventArgs e) 3908 private void Reprioritize(object sender, ElapsedEventArgs e)
3908 { 3909 {
3909 m_controllingClient.ReprioritizeUpdates(StateUpdateTypes.All, UpdatePriority); 3910 m_controllingClient.ReprioritizeUpdates(UpdatePriority);
3910 3911
3911 lock (m_reprioritization_timer) 3912 lock (m_reprioritization_timer)
3912 { 3913 {
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index 69e78b3..84faac0 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1045,16 +1045,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1045 1045
1046 } 1046 }
1047 1047
1048 public void SendAvatarData(SendAvatarData data)
1049 {
1050
1051 }
1052
1053 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
1054 {
1055
1056 }
1057
1058 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 1048 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
1059 { 1049 {
1060 1050
@@ -1065,32 +1055,27 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1065 1055
1066 } 1056 }
1067 1057
1068 public void SetChildAgentThrottle(byte[] throttle) 1058 public void SendAvatarDataImmediate(ISceneEntity avatar)
1069 { 1059 {
1070
1071 }
1072 1060
1073 public void SendPrimitiveToClient(SendPrimitiveData data)
1074 {
1075
1076 } 1061 }
1077 1062
1078 public void SendPrimTerseUpdate(SendPrimitiveTerseData data) 1063 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
1079 { 1064 {
1080 1065
1081 } 1066 }
1082 1067
1083 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 1068 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
1084 { 1069 {
1085 1070
1086 } 1071 }
1087 1072
1088 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems) 1073 public void FlushPrimUpdates()
1089 { 1074 {
1090 1075
1091 } 1076 }
1092 1077
1093 public void FlushPrimUpdates() 1078 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, int version, bool fetchFolders, bool fetchItems)
1094 { 1079 {
1095 1080
1096 } 1081 }
@@ -1420,6 +1405,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1420 1405
1421 } 1406 }
1422 1407
1408 public virtual void SetChildAgentThrottle(byte[] throttle)
1409 {
1410
1411 }
1412
1423 public byte[] GetThrottlesPacked(float multiplier) 1413 public byte[] GetThrottlesPacked(float multiplier)
1424 { 1414 {
1425 return new byte[0]; 1415 return new byte[0];
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index 6360c99..9066691 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -618,14 +618,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC
618 { 618 {
619 } 619 }
620 620
621 public virtual void SendAvatarData(SendAvatarData data)
622 {
623 }
624
625 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
626 {
627 }
628
629 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 621 public virtual void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
630 { 622 {
631 } 623 }
@@ -638,15 +630,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC
638 { 630 {
639 } 631 }
640 632
641 public virtual void SendPrimitiveToClient(SendPrimitiveData data) 633 public void SendAvatarDataImmediate(ISceneEntity avatar)
642 { 634 {
643 } 635 }
644 636
645 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data) 637 public void SendPrimUpdate(ISceneEntity entity, PrimUpdateFlags updateFlags)
646 { 638 {
647 } 639 }
648 640
649 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler) 641 public void ReprioritizeUpdates(UpdatePriorityHandler handler)
650 { 642 {
651 } 643 }
652 644
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
index 9da818a..33ff707 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerLargeLandChannel.cs
@@ -140,6 +140,16 @@ public class RegionCombinerLargeLandChannel : ILandChannel
140 RootRegionLandChannel.UpdateLandObject(localID, data); 140 RootRegionLandChannel.UpdateLandObject(localID, data);
141 } 141 }
142 142
143 public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
144 {
145 RootRegionLandChannel.Join(start_x, start_y, end_x, end_y, attempting_user_id);
146 }
147
148 public void Subdivide(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id)
149 {
150 RootRegionLandChannel.Subdivide(start_x, start_y, end_x, end_y, attempting_user_id);
151 }
152
143 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) 153 public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient)
144 { 154 {
145 RootRegionLandChannel.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient); 155 RootRegionLandChannel.ReturnObjectsInParcel(localID, returnType, agentIDs, taskIDs, remoteClient);
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 7e68cc7..15469db 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1129,7 +1129,89 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1129 return 0.0f; 1129 return 0.0f;
1130 } 1130 }
1131 1131
1132 // Routines for creating and managing parcels programmatically
1133 public void osParcelJoin(LSL_Vector pos1, LSL_Vector pos2)
1134 {
1135 CheckThreatLevel(ThreatLevel.High, "osParcelJoin");
1136 m_host.AddScriptLPS(1);
1137
1138 int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x);
1139 int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y);
1140 int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x);
1141 int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y);
1142
1143 World.LandChannel.Join(startx,starty,endx,endy,m_host.OwnerID);
1144 }
1145
1146 public void osParcelSubdivide(LSL_Vector pos1, LSL_Vector pos2)
1147 {
1148 CheckThreatLevel(ThreatLevel.High, "osParcelSubdivide");
1149 m_host.AddScriptLPS(1);
1150
1151 int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x);
1152 int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y);
1153 int endx = (int)(pos1.x > pos2.x ? pos1.x : pos2.x);
1154 int endy = (int)(pos1.y > pos2.y ? pos1.y : pos2.y);
1132 1155
1156 World.LandChannel.Subdivide(startx,starty,endx,endy,m_host.OwnerID);
1157 }
1158
1159 public void osParcelSetDetails(LSL_Vector pos, LSL_List rules)
1160 {
1161 CheckThreatLevel(ThreatLevel.High, "osParcelSetDetails");
1162 m_host.AddScriptLPS(1);
1163
1164 // Get a reference to the land data and make sure the owner of the script
1165 // can modify it
1166
1167 ILandObject startLandObject = World.LandChannel.GetLandObject((int)pos.x, (int)pos.y);
1168 if (startLandObject == null)
1169 {
1170 OSSLShoutError("There is no land at that location");
1171 return;
1172 }
1173
1174 if (! World.Permissions.CanEditParcel(m_host.OwnerID, startLandObject))
1175 {
1176 OSSLShoutError("You do not have permission to modify the parcel");
1177 return;
1178 }
1179
1180 // Create a new land data object we can modify
1181 LandData newLand = startLandObject.LandData.Copy();
1182 UUID uuid;
1183
1184 // Process the rules, not sure what the impact would be of changing owner or group
1185 for (int idx = 0; idx < rules.Length; )
1186 {
1187 int code = rules.GetLSLIntegerItem(idx++);
1188 string arg = rules.GetLSLStringItem(idx++);
1189 switch (code)
1190 {
1191 case 0:
1192 newLand.Name = arg;
1193 break;
1194
1195 case 1:
1196 newLand.Description = arg;
1197 break;
1198
1199 case 2:
1200 CheckThreatLevel(ThreatLevel.VeryHigh, "osParcelSetDetails");
1201 if (UUID.TryParse(arg , out uuid))
1202 newLand.OwnerID = uuid;
1203 break;
1204
1205 case 3:
1206 CheckThreatLevel(ThreatLevel.VeryHigh, "osParcelSetDetails");
1207 if (UUID.TryParse(arg , out uuid))
1208 newLand.GroupID = uuid;
1209 break;
1210 }
1211 }
1212
1213 World.LandChannel.UpdateLandObject(newLand.LocalID,newLand);
1214 }
1133 1215
1134 public double osList2Double(LSL_Types.list src, int index) 1216 public double osList2Double(LSL_Types.list src, int index)
1135 { 1217 {
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
index 60b8050..7a8f469 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs
@@ -123,6 +123,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces
123 void osWindParamSet(string plugin, string param, float value); 123 void osWindParamSet(string plugin, string param, float value);
124 float osWindParamGet(string plugin, string param); 124 float osWindParamGet(string plugin, string param);
125 125
126 // Parcel commands
127 void osParcelJoin(vector pos1, vector pos2);
128 void osParcelSubdivide(vector pos1, vector pos2);
129 void osParcelSetDetails(vector pos, LSL_List rules);
126 130
127 string osGetScriptEngineName(); 131 string osGetScriptEngineName();
128 string osGetSimulatorVersion(); 132 string osGetSimulatorVersion();
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
index 3870af3..fd9309a 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs
@@ -106,6 +106,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase
106// return m_OSSL_Functions.osWindParamGet(plugin, param); 106// return m_OSSL_Functions.osWindParamGet(plugin, param);
107// } 107// }
108 108
109 public void osParcelJoin(vector pos1, vector pos2)
110 {
111 m_OSSL_Functions.osParcelJoin(pos1,pos2);
112 }
113
114 public void osParcelSubdivide(vector pos1, vector pos2)
115 {
116 m_OSSL_Functions.osParcelSubdivide(pos1, pos2);
117 }
118
119 public void osParcelSetDetails(vector pos, LSL_List rules)
120 {
121 m_OSSL_Functions.osParcelSetDetails(pos,rules);
122 }
123
109 public double osList2Double(LSL_Types.list src, int index) 124 public double osList2Double(LSL_Types.list src, int index)
110 { 125 {
111 return m_OSSL_Functions.osList2Double(src, index); 126 return m_OSSL_Functions.osList2Double(src, index);