aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs12
-rw-r--r--OpenSim/Client/MXP/ClientStack/MXPClientView.cs31
-rw-r--r--OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs13
-rw-r--r--OpenSim/Data/MySQL/MySQLLegacyRegionData.cs25
-rw-r--r--OpenSim/Framework/IClientAPI.cs254
-rwxr-xr-xOpenSim/Framework/MinHeap.cs375
-rw-r--r--OpenSim/Framework/Util.cs23
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs785
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs83
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs39
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs2
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs8
-rw-r--r--OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs28
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISceneViewer.cs1
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs73
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs18
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs74
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs65
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs23
-rw-r--r--OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs4
-rw-r--r--OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs4
-rw-r--r--OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs13
-rw-r--r--OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs2
-rw-r--r--OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs4
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs27
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs18
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs4
-rw-r--r--OpenSim/Tests/Common/Mock/TestClient.cs28
31 files changed, 1473 insertions, 600 deletions
diff --git a/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs b/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
index f30a18b..a868bd0 100644
--- a/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
+++ b/OpenSim/ApplicationPlugins/RegionModulesController/RegionModulesControllerPlugin.cs
@@ -268,7 +268,7 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
268 deferredlist.Add(module); 268 deferredlist.Add(module);
269 } 269 }
270 270
271 foreach (INonSharedRegionModule module in deferredlist) 271 foreach (IRegionModuleBase module in deferredlist)
272 { 272 {
273 module.AddRegion(scene); 273 module.AddRegion(scene);
274 scene.AddRegionModule(module.Name, module); 274 scene.AddRegionModule(module.Name, module);
@@ -284,14 +284,16 @@ namespace OpenSim.ApplicationPlugins.RegionModulesController
284 // and unneccessary caching logic repeated in all modules. 284 // and unneccessary caching logic repeated in all modules.
285 // The extra function stub is just that much cleaner 285 // The extra function stub is just that much cleaner
286 // 286 //
287 foreach (ISharedRegionModule module in sharedlist) 287 foreach (IRegionModuleBase module in sharedlist)
288 { 288 {
289 module.RegionLoaded(scene); 289 try { module.RegionLoaded(scene); }
290 catch (Exception ex) { m_log.Error("[REGIONMODULE]: Exception while loading shared region module " + module + ": " + ex.Message, ex); }
290 } 291 }
291 292
292 foreach (INonSharedRegionModule module in list) 293 foreach (IRegionModuleBase module in list)
293 { 294 {
294 module.RegionLoaded(scene); 295 try { module.RegionLoaded(scene); }
296 catch (Exception ex) { m_log.Error("[REGIONMODULE]: Exception while loading non-shared region module " + module + ": " + ex.Message, ex); }
295 } 297 }
296 } 298 }
297 299
diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
index bc02bc4..ea29c41 100644
--- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
+++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs
@@ -996,19 +996,19 @@ namespace OpenSim.Client.MXP.ClientStack
996 // Need to translate to MXP somehow 996 // Need to translate to MXP somehow
997 } 997 }
998 998
999 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, uint avatarLocalID, Vector3 position, byte[] textureEntry, uint parentID, Quaternion rotation) 999 public void SendAvatarData(SendAvatarData data)
1000 { 1000 {
1001 //ScenePresence presence=((Scene)this.Scene).GetScenePresence(avatarID); 1001 //ScenePresence presence=((Scene)this.Scene).GetScenePresence(avatarID);
1002 UUID ownerID = avatarID; 1002 UUID ownerID = data.avatarID;
1003 MXPSendAvatarData(firstName + " " + lastName, ownerID, UUID.Zero, avatarID, avatarLocalID, position, rotation); 1003 MXPSendAvatarData(data.firstName + " " + data.lastName, ownerID, UUID.Zero, data.avatarID, data.avatarLocalID, data.Pos, data.rotation);
1004 } 1004 }
1005 1005
1006 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity, Quaternion rotation, UUID uuid) 1006 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
1007 { 1007 {
1008 MovementEventMessage me = new MovementEventMessage(); 1008 MovementEventMessage me = new MovementEventMessage();
1009 me.ObjectIndex = localID; 1009 me.ObjectIndex = data.localID;
1010 me.Location =ToOmVector(position); 1010 me.Location = ToOmVector(data.position);
1011 me.Orientation = ToOmQuaternion(rotation); 1011 me.Orientation = ToOmQuaternion(data.rotation);
1012 1012
1013 Session.Send(me); 1013 Session.Send(me);
1014 } 1014 }
@@ -1028,22 +1028,17 @@ namespace OpenSim.Client.MXP.ClientStack
1028 // Need to translate to MXP somehow 1028 // Need to translate to MXP somehow
1029 } 1029 }
1030 1030
1031 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius) 1031 public void SendPrimitiveToClient(SendPrimitiveData data)
1032 { 1032 {
1033 MXPSendPrimitive(localID, ownerID, acc, rvel, primShape, pos, objectID, vel, rotation, flags,text,color,parentID,particleSystem,clickAction,material,textureanim); 1033 MXPSendPrimitive(data.localID, data.ownerID, data.acc, data.rvel, data.primShape, data.pos, data.objectID, data.vel, data.rotation, data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction, data.material, data.textureanim);
1034 } 1034 }
1035 1035
1036 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte material) 1036 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
1037 {
1038 MXPSendPrimitive(localID, ownerID, acc, rvel, primShape, pos, objectID, vel, rotation, flags, text, color, parentID, particleSystem, clickAction, material, new byte[0]);
1039 }
1040
1041 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID owner, int attachPoint)
1042 { 1037 {
1043 MovementEventMessage me = new MovementEventMessage(); 1038 MovementEventMessage me = new MovementEventMessage();
1044 me.ObjectIndex = localID; 1039 me.ObjectIndex = data.localID;
1045 me.Location = ToOmVector(position); 1040 me.Location = ToOmVector(data.position);
1046 me.Orientation = ToOmQuaternion(rotation); 1041 me.Orientation = ToOmQuaternion(data.rotation);
1047 Session.Send(me); 1042 Session.Send(me);
1048 } 1043 }
1049 1044
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
index e3abcf5..3a48a03 100644
--- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
+++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
@@ -560,12 +560,12 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
560 throw new System.NotImplementedException(); 560 throw new System.NotImplementedException();
561 } 561 }
562 562
563 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) 563 public void SendAvatarData(SendAvatarData data)
564 { 564 {
565 throw new System.NotImplementedException(); 565 throw new System.NotImplementedException();
566 } 566 }
567 567
568 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity, Quaternion rotation, UUID uuid) 568 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
569 { 569 {
570 throw new System.NotImplementedException(); 570 throw new System.NotImplementedException();
571 } 571 }
@@ -585,17 +585,12 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
585 throw new System.NotImplementedException(); 585 throw new System.NotImplementedException();
586 } 586 }
587 587
588 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius) 588 public void SendPrimitiveToClient(SendPrimitiveData data)
589 { 589 {
590 throw new System.NotImplementedException(); 590 throw new System.NotImplementedException();
591 } 591 }
592 592
593 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte material) 593 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
594 {
595 throw new System.NotImplementedException();
596 }
597
598 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID owner, int attachPoint)
599 { 594 {
600 throw new System.NotImplementedException(); 595 throw new System.NotImplementedException();
601 } 596 }
diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs
index fe0914b..6bc8bec 100644
--- a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs
+++ b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs
@@ -68,12 +68,20 @@ namespace OpenSim.Data.MySQL
68 68
69 // Clean dropped attachments 69 // Clean dropped attachments
70 // 70 //
71 MySqlCommand cmd = m_Connection.CreateCommand(); 71 try
72 cmd.CommandText = "delete from prims, primshapes using prims " + 72 {
73 "left join primshapes on prims.uuid = primshapes.uuid " + 73 using (MySqlCommand cmd = m_Connection.CreateCommand())
74 "where PCode = 9 and State <> 0"; 74 {
75 ExecuteNonQuery(cmd); 75 cmd.CommandText = "delete from prims, primshapes using prims " +
76 cmd.Dispose(); 76 "left join primshapes on prims.uuid = primshapes.uuid " +
77 "where PCode = 9 and State <> 0";
78 ExecuteNonQuery(cmd);
79 }
80 }
81 catch (MySqlException ex)
82 {
83 m_log.Error("[REGION DB]: Error cleaning up dropped attachments: " + ex.Message);
84 }
77 } 85 }
78 86
79 private IDataReader ExecuteReader(MySqlCommand c) 87 private IDataReader ExecuteReader(MySqlCommand c)
@@ -401,6 +409,7 @@ namespace OpenSim.Data.MySQL
401 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>(); 409 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
402 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(); 410 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>();
403 SceneObjectGroup grp = null; 411 SceneObjectGroup grp = null;
412 int count = 0;
404 413
405 lock (m_Connection) 414 lock (m_Connection)
406 { 415 {
@@ -463,6 +472,10 @@ namespace OpenSim.Data.MySQL
463 if (link != 0) 472 if (link != 0)
464 prim.LinkNum = link; 473 prim.LinkNum = link;
465 } 474 }
475
476 ++count;
477 if (count % 5000 == 0)
478 m_log.Debug("[REGION DB]: Loaded " + count + " prims...");
466 } 479 }
467 } 480 }
468 481
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 29846f5..4b51e15 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -517,6 +517,233 @@ namespace OpenSim.Framework
517 public float dwell; 517 public float dwell;
518 } 518 }
519 519
520 public struct SendAvatarData
521 {
522 private ulong m_regionHandle;
523 private string m_firstName;
524 private string m_lastName;
525 private string m_grouptitle;
526 private UUID m_avatarID;
527 private uint m_avatarLocalID;
528 private Vector3 m_Pos;
529 private byte[] m_textureEntry;
530 private uint m_parentID;
531 private Quaternion m_rotation;
532
533 public SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID,
534 uint avatarLocalID,
535 Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
536 {
537 this.m_regionHandle = regionHandle;
538 this.m_firstName = firstName;
539 this.m_lastName = lastName;
540 this.m_grouptitle = grouptitle;
541 this.m_avatarID = avatarID;
542 this.m_avatarLocalID = avatarLocalID;
543 this.m_Pos = Pos;
544 this.m_textureEntry = textureEntry;
545 this.m_parentID = parentID;
546 this.m_rotation = rotation;
547 }
548
549 public ulong regionHandle { get { return this.m_regionHandle; } }
550 public string firstName { get { return this.m_firstName; } }
551 public string lastName { get { return this.m_lastName; } }
552 public string grouptitle { get { return this.m_grouptitle; } }
553 public UUID avatarID { get { return this.m_avatarID; } }
554 public uint avatarLocalID { get { return this.m_avatarLocalID; } }
555 public Vector3 Pos { get { return this.m_Pos; } }
556 public byte[] textureEntry { get { return this.m_textureEntry; } }
557 public uint parentID { get { return this.m_parentID; } }
558 public Quaternion rotation { get { return this.m_rotation; } }
559 }
560
561 public struct SendAvatarTerseData
562 {
563 private ulong m_regionHandle;
564 private ushort m_timeDilation;
565 private uint m_localID;
566 private Vector3 m_position;
567 private Vector3 m_velocity;
568 private Quaternion m_rotation;
569 private UUID m_agentid;
570 private double m_priority;
571
572 public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
573 Vector3 velocity, Quaternion rotation, UUID agentid, double priority)
574 {
575 this.m_regionHandle = regionHandle;
576 this.m_timeDilation = timeDilation;
577 this.m_localID = localID;
578 this.m_position = position;
579 this.m_velocity = velocity;
580 this.m_rotation = rotation;
581 this.m_agentid = agentid;
582 this.m_priority = priority;
583 }
584
585 public ulong regionHandle { get { return this.m_regionHandle; } }
586 public ushort timeDilation { get { return this.m_timeDilation; } }
587 public uint localID { get { return this.m_localID; } }
588 public Vector3 position { get { return this.m_position; } }
589 public Vector3 velocity { get { return this.m_velocity; } }
590 public Quaternion rotation { get { return this.m_rotation; } }
591 public UUID agentid { get { return this.m_agentid; } }
592 public double priority { get { return this.m_priority; } }
593 }
594
595 public struct SendPrimitiveTerseData
596 {
597 private ulong m_regionHandle;
598 private ushort m_timeDilation;
599 private uint m_localID;
600 private Vector3 m_position;
601 private Quaternion m_rotation;
602 private Vector3 m_velocity;
603 private Vector3 m_rotationalvelocity;
604 private byte m_state;
605 private UUID m_AssetId;
606 private UUID m_owner;
607 private int m_attachPoint;
608 private double m_priority;
609
610 public SendPrimitiveTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
611 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state,
612 UUID AssetId, UUID owner, int attachPoint, double priority)
613 {
614 this.m_regionHandle = regionHandle;
615 this.m_timeDilation = timeDilation;
616 this.m_localID = localID;
617 this.m_position = position;
618 this.m_rotation = rotation;
619 this.m_velocity = velocity;
620 this.m_rotationalvelocity = rotationalvelocity;
621 this.m_state = state;
622 this.m_AssetId = AssetId;
623 this.m_owner = owner;
624 this.m_attachPoint = attachPoint;
625 this.m_priority = priority;
626 }
627
628 public ulong regionHandle { get { return this.m_regionHandle; } }
629 public ushort timeDilation { get { return this.m_timeDilation; } }
630 public uint localID { get { return this.m_localID; } }
631 public Vector3 position { get { return this.m_position; } }
632 public Quaternion rotation { get { return this.m_rotation; } }
633 public Vector3 velocity { get { return this.m_velocity; } }
634 public Vector3 rotationalvelocity { get { return this.m_rotationalvelocity; } }
635 public byte state { get { return this.m_state; } }
636 public UUID AssetId { get { return this.m_AssetId; } }
637 public UUID owner { get { return this.m_owner; } }
638 public int attachPoint { get { return this.m_attachPoint; } }
639 public double priority { get { return this.m_priority; } }
640 }
641
642 public struct SendPrimitiveData
643 {
644 private ulong m_regionHandle;
645 private ushort m_timeDilation;
646 private uint m_localID;
647 private PrimitiveBaseShape m_primShape;
648 private Vector3 m_pos;
649 private Vector3 m_vel;
650 private Vector3 m_acc;
651 private Quaternion m_rotation;
652 private Vector3 m_rvel;
653 private uint m_flags;
654 private UUID m_objectID;
655 private UUID m_ownerID;
656 private string m_text;
657 private byte[] m_color;
658 private uint m_parentID;
659 private byte[] m_particleSystem;
660 private byte m_clickAction;
661 private byte m_material;
662 private byte[] m_textureanim;
663 private bool m_attachment;
664 private uint m_AttachPoint;
665 private UUID m_AssetId;
666 private UUID m_SoundId;
667 private double m_SoundVolume;
668 private byte m_SoundFlags;
669 private double m_SoundRadius;
670 private double m_priority;
671
672 public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
673 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
674 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
675 uint parentID, byte[] particleSystem, byte clickAction, byte material, double priority) :
676 this(regionHandle, timeDilation, localID, primShape, pos, vel, acc, rotation, rvel, flags, objectID,
677 ownerID, text, color, parentID, particleSystem, clickAction, material, new byte[0], false, 0, UUID.Zero,
678 UUID.Zero, 0, 0, 0, priority) { }
679
680 public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
681 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
682 uint flags,
683 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID,
684 byte[] particleSystem,
685 byte clickAction, byte material, byte[] textureanim, bool attachment,
686 uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags,
687 double SoundRadius, double priority)
688 {
689 this.m_regionHandle = regionHandle;
690 this.m_timeDilation = timeDilation;
691 this.m_localID = localID;
692 this.m_primShape = primShape;
693 this.m_pos = pos;
694 this.m_vel = vel;
695 this.m_acc = acc;
696 this.m_rotation = rotation;
697 this.m_rvel = rvel;
698 this.m_flags = flags;
699 this.m_objectID = objectID;
700 this.m_ownerID = ownerID;
701 this.m_text = text;
702 this.m_color = color;
703 this.m_parentID = parentID;
704 this.m_particleSystem = particleSystem;
705 this.m_clickAction = clickAction;
706 this.m_material = material;
707 this.m_textureanim = textureanim;
708 this.m_attachment = attachment;
709 this.m_AttachPoint = AttachPoint;
710 this.m_AssetId = AssetId;
711 this.m_SoundId = SoundId;
712 this.m_SoundVolume = SoundVolume;
713 this.m_SoundFlags = SoundFlags;
714 this.m_SoundRadius = SoundRadius;
715 this.m_priority = priority;
716 }
717
718 public ulong regionHandle { get { return this.m_regionHandle; } }
719 public ushort timeDilation { get { return this.m_timeDilation; } }
720 public uint localID { get { return this.m_localID; } }
721 public PrimitiveBaseShape primShape { get { return this.m_primShape; } }
722 public Vector3 pos { get { return this.m_pos; } }
723 public Vector3 vel { get { return this.m_vel; } }
724 public Vector3 acc { get { return this.m_acc; } }
725 public Quaternion rotation { get { return this.m_rotation; } }
726 public Vector3 rvel { get { return this.m_rvel; } }
727 public uint flags { get { return this.m_flags; } }
728 public UUID objectID { get { return this.m_objectID; } }
729 public UUID ownerID { get { return this.m_ownerID; } }
730 public string text { get { return this.m_text; } }
731 public byte[] color { get { return this.m_color; } }
732 public uint parentID { get { return this.m_parentID; } }
733 public byte[] particleSystem { get { return this.m_particleSystem; } }
734 public byte clickAction { get { return this.m_clickAction; } }
735 public byte material { get { return this.m_material; } }
736 public byte[] textureanim { get { return this.m_textureanim; } }
737 public bool attachment { get { return this.m_attachment; } }
738 public uint AttachPoint { get { return this.m_AttachPoint; } }
739 public UUID AssetId { get { return this.m_AssetId; } }
740 public UUID SoundId { get { return this.m_SoundId; } }
741 public double SoundVolume { get { return this.m_SoundVolume; } }
742 public byte SoundFlags { get { return this.m_SoundFlags; } }
743 public double SoundRadius { get { return this.m_SoundRadius; } }
744 public double priority { get { return this.m_priority; } }
745 }
746
520 public interface IClientAPI 747 public interface IClientAPI
521 { 748 {
522 Vector3 StartPos { get; set; } 749 Vector3 StartPos { get; set; }
@@ -877,37 +1104,18 @@ namespace OpenSim.Framework
877 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); 1104 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
878 void SendPayPrice(UUID objectID, int[] payPrice); 1105 void SendPayPrice(UUID objectID, int[] payPrice);
879 1106
880 void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, 1107 void SendAvatarData(SendAvatarData data);
881 uint avatarLocalID,
882 Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation);
883 1108
884 void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 1109 void SendAvatarTerseUpdate(SendAvatarTerseData data);
885 Vector3 velocity, Quaternion rotation, UUID agentid);
886 1110
887 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); 1111 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
888 1112
889 void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID); 1113 void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID);
890 void SetChildAgentThrottle(byte[] throttle); 1114 void SetChildAgentThrottle(byte[] throttle);
891 1115
892 void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, 1116 void SendPrimitiveToClient(SendPrimitiveData data);
893 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
894 uint flags,
895 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID,
896 byte[] particleSystem,
897 byte clickAction, byte material, byte[] textureanim, bool attachment,
898 uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags,
899 double SoundRadius);
900
901 1117
902 void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, 1118 void SendPrimTerseUpdate(SendPrimitiveTerseData data);
903 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
904 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
905 uint parentID, byte[] particleSystem, byte clickAction, byte material);
906
907
908 void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
909 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state,
910 UUID AssetId, UUID owner, int attachPoint);
911 1119
912 void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, 1120 void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
913 List<InventoryFolderBase> folders, bool fetchFolders, 1121 List<InventoryFolderBase> folders, bool fetchFolders,
diff --git a/OpenSim/Framework/MinHeap.cs b/OpenSim/Framework/MinHeap.cs
new file mode 100755
index 0000000..ad39bbc
--- /dev/null
+++ b/OpenSim/Framework/MinHeap.cs
@@ -0,0 +1,375 @@
1using System;
2using System.Threading;
3using System.Collections;
4using System.Collections.Generic;
5using System.Runtime.InteropServices;
6
7namespace OpenSim.Framework
8{
9 public interface IHandle { }
10
11 [Serializable, ComVisible(false)]
12 public class MinHeap<T> : ICollection<T>, ICollection
13 {
14 private class Handle : IHandle
15 {
16 internal int index = -1;
17 internal MinHeap<T> heap = null;
18
19 internal void Clear()
20 {
21 this.index = -1;
22 this.heap = null;
23 }
24 }
25
26 private struct HeapItem
27 {
28 internal T value;
29 internal Handle handle;
30
31 internal HeapItem(T value, Handle handle)
32 {
33 this.value = value;
34 this.handle = handle;
35 }
36
37 internal void Clear()
38 {
39 this.value = default(T);
40 if (this.handle != null)
41 {
42 this.handle.Clear();
43 this.handle = null;
44 }
45 }
46 }
47
48 public const int DEFAULT_CAPACITY = 4;
49
50 private HeapItem[] items;
51 private int size;
52 private object sync_root;
53 private int version;
54
55 private Comparison<T> comparison;
56
57 public MinHeap() : this(DEFAULT_CAPACITY, Comparer<T>.Default) { }
58 public MinHeap(int capacity) : this(capacity, Comparer<T>.Default) { }
59 public MinHeap(IComparer<T> comparer) : this(DEFAULT_CAPACITY, comparer) { }
60 public MinHeap(int capacity, IComparer<T> comparer) :
61 this(capacity, new Comparison<T>(comparer.Compare)) { }
62 public MinHeap(Comparison<T> comparison) : this(DEFAULT_CAPACITY, comparison) { }
63 public MinHeap(int capacity, Comparison<T> comparison)
64 {
65 this.items = new HeapItem[capacity];
66 this.comparison = comparison;
67 this.size = this.version = 0;
68 }
69
70 public int Count { get { return this.size; } }
71
72 public bool IsReadOnly { get { return false; } }
73
74 public bool IsSynchronized { get { return false; } }
75
76 public T this[IHandle key]
77 {
78 get
79 {
80 Handle handle = ValidateThisHandle(key);
81 return this.items[handle.index].value;
82 }
83
84 set
85 {
86 Handle handle = ValidateThisHandle(key);
87 this.items[handle.index].value = value;
88 if (!BubbleUp(handle.index))
89 BubbleDown(handle.index);
90 }
91 }
92
93 public object SyncRoot
94 {
95 get
96 {
97 if (this.sync_root == null)
98 Interlocked.CompareExchange<object>(ref this.sync_root, new object(), null);
99 return this.sync_root;
100 }
101 }
102
103 private Handle ValidateHandle(IHandle ihandle)
104 {
105 if (ihandle == null)
106 throw new ArgumentNullException("handle");
107 Handle handle = ihandle as Handle;
108 if (handle == null)
109 throw new InvalidOperationException("handle is not valid");
110 return handle;
111 }
112
113 private Handle ValidateThisHandle(IHandle ihandle)
114 {
115 Handle handle = ValidateHandle(ihandle);
116 if (!object.ReferenceEquals(handle.heap, this))
117 throw new InvalidOperationException("handle is not valid for this heap");
118 if (handle.index < 0)
119 throw new InvalidOperationException("handle is not associated to a value");
120 return handle;
121 }
122
123 private void Set(HeapItem item, int index)
124 {
125 this.items[index] = item;
126 if (item.handle != null)
127 item.handle.index = index;
128 }
129
130 private bool BubbleUp(int index)
131 {
132 HeapItem item = this.items[index];
133 int current, parent;
134
135 for (current = index, parent = (current - 1) / 2;
136 (current > 0) && (this.comparison(this.items[parent].value, item.value)) > 0;
137 current = parent, parent = (current - 1) / 2)
138 {
139 Set(this.items[parent], current);
140 }
141
142 if (current != index)
143 {
144 Set(item, current);
145 ++this.version;
146 return true;
147 }
148 return false;
149 }
150
151 private void BubbleDown(int index)
152 {
153 HeapItem item = this.items[index];
154 int current, child;
155
156 for (current = index, child = (2 * current) + 1;
157 current < this.size / 2;
158 current = child, child = (2 * current) + 1)
159 {
160 if ((child < this.size - 1) && this.comparison(this.items[child].value, this.items[child + 1].value) > 0)
161 ++child;
162 if (this.comparison(this.items[child].value, item.value) >= 0)
163 break;
164 Set(this.items[child], current);
165 }
166
167 if (current != index)
168 {
169 Set(item, current);
170 ++this.version;
171 }
172 }
173
174 public bool TryGetValue(IHandle key, out T value)
175 {
176 Handle handle = ValidateHandle(key);
177 if (handle.index > -1)
178 {
179 value = this.items[handle.index].value;
180 return true;
181 }
182 value = default(T);
183 return false;
184 }
185
186 public bool ContainsHandle(IHandle ihandle)
187 {
188 Handle handle = ValidateHandle(ihandle);
189 return object.ReferenceEquals(handle.heap, this) && handle.index > -1;
190 }
191
192 public void Add(T value, ref IHandle handle)
193 {
194 if (handle == null)
195 handle = new Handle();
196 Add(value, handle);
197 }
198
199 public void Add(T value, IHandle ihandle)
200 {
201 if (this.size == this.items.Length)
202 {
203 int capacity = (int)((this.items.Length * 200L) / 100L);
204 if (capacity < (this.items.Length + DEFAULT_CAPACITY))
205 capacity = this.items.Length + DEFAULT_CAPACITY;
206 Array.Resize<HeapItem>(ref this.items, capacity);
207 }
208
209 Handle handle = null;
210 if (ihandle != null)
211 {
212 handle = ValidateHandle(ihandle);
213 handle.heap = this;
214 }
215
216 HeapItem item = new MinHeap<T>.HeapItem(value, handle);
217
218 Set(item, this.size);
219 BubbleUp(this.size++);
220 }
221
222 public void Add(T value)
223 {
224 Add(value, null);
225 }
226
227 public T Min()
228 {
229 if (this.size == 0)
230 throw new InvalidOperationException("Heap is empty");
231
232 return this.items[0].value;
233 }
234
235 public void Clear()
236 {
237 for (int index = 0; index < this.size; ++index)
238 this.items[index].Clear();
239 this.size = 0;
240 ++this.version;
241 }
242
243 public void TrimExcess()
244 {
245 int length = (int)(this.items.Length * 0.9);
246 if (this.size < length)
247 Array.Resize<HeapItem>(ref this.items, Math.Min(this.size, DEFAULT_CAPACITY));
248 }
249
250 private void RemoveAt(int index)
251 {
252 if (this.size == 0)
253 throw new InvalidOperationException("Heap is empty");
254 if (index >= this.size)
255 throw new ArgumentOutOfRangeException("index");
256
257 this.items[index].Clear();
258 if (--this.size > 0 && index != this.size)
259 {
260 Set(this.items[this.size], index);
261 if (!BubbleUp(index))
262 BubbleDown(index);
263 }
264 }
265
266 public T RemoveMin()
267 {
268 if (this.size == 0)
269 throw new InvalidOperationException("Heap is empty");
270
271 HeapItem item = this.items[0];
272 RemoveAt(0);
273 return item.value;
274 }
275
276 public T Remove(IHandle ihandle)
277 {
278 Handle handle = ValidateThisHandle(ihandle);
279 HeapItem item = this.items[handle.index];
280 RemoveAt(handle.index);
281 return item.value;
282 }
283
284 private int GetIndex(T value)
285 {
286 EqualityComparer<T> comparer = EqualityComparer<T>.Default;
287 int index;
288
289 for (index = 0; index < this.size; ++index)
290 {
291 if (comparer.Equals(this.items[index].value, value))
292 return index;
293 }
294 return -1;
295 }
296
297 public bool Contains(T value)
298 {
299 return GetIndex(value) != -1;
300 }
301
302 public bool Remove(T value)
303 {
304 int index = GetIndex(value);
305 if (index != -1)
306 {
307 RemoveAt(index);
308 return true;
309 }
310 return false;
311 }
312
313 public void CopyTo(T[] array, int index)
314 {
315 if (array == null)
316 throw new ArgumentNullException("array");
317 if (array.Rank != 1)
318 throw new ArgumentException("Multidimensional array not supported");
319 if (array.GetLowerBound(0) != 0)
320 throw new ArgumentException("Non-zero lower bound array not supported");
321
322 int length = array.Length;
323 if ((index < 0) || (index > length))
324 throw new ArgumentOutOfRangeException("index");
325 if ((length - index) < this.size)
326 throw new ArgumentException("Not enough space available in array starting at index");
327
328 for (int i = 0; i < this.size; ++i)
329 array[index + i] = this.items[i].value;
330 }
331
332 public void CopyTo(Array array, int index)
333 {
334 if (array == null)
335 throw new ArgumentNullException("array");
336 if (array.Rank != 1)
337 throw new ArgumentException("Multidimensional array not supported");
338 if (array.GetLowerBound(0) != 0)
339 throw new ArgumentException("Non-zero lower bound array not supported");
340
341 int length = array.Length;
342 if ((index < 0) || (index > length))
343 throw new ArgumentOutOfRangeException("index");
344 if ((length - index) < this.size)
345 throw new ArgumentException("Not enough space available in array starting at index");
346
347 try
348 {
349 for (int i = 0; i < this.size; ++i)
350 array.SetValue(this.items[i].value, index + i);
351 }
352 catch (ArrayTypeMismatchException)
353 {
354 throw new ArgumentException("Invalid array type");
355 }
356 }
357
358 public IEnumerator<T> GetEnumerator()
359 {
360 int version = this.version;
361
362 for (int index = 0; index < this.size; ++index)
363 {
364 if (version != this.version)
365 throw new InvalidOperationException("Heap was modified while enumerating");
366 yield return this.items[index].value;
367 }
368 }
369
370 IEnumerator IEnumerable.GetEnumerator()
371 {
372 return GetEnumerator();
373 }
374 }
375}
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 38729c6..3203fc1 100644
--- a/OpenSim/Framework/Util.cs
+++ b/OpenSim/Framework/Util.cs
@@ -44,6 +44,7 @@ using System.Xml;
44using log4net; 44using log4net;
45using Nini.Config; 45using Nini.Config;
46using Nwc.XmlRpc; 46using Nwc.XmlRpc;
47using BclExtras;
47using OpenMetaverse; 48using OpenMetaverse;
48using OpenMetaverse.StructuredData; 49using OpenMetaverse.StructuredData;
49 50
@@ -1269,14 +1270,32 @@ namespace OpenSim.Framework
1269 1270
1270 #region FireAndForget Threading Pattern 1271 #region FireAndForget Threading Pattern
1271 1272
1273 /// <summary>
1274 /// Created to work around a limitation in Mono with nested delegates
1275 /// </summary>
1276 private class FireAndForgetWrapper
1277 {
1278 public void FireAndForget(System.Threading.WaitCallback callback)
1279 {
1280 callback.BeginInvoke(null, EndFireAndForget, callback);
1281 }
1282
1283 public void FireAndForget(System.Threading.WaitCallback callback, object obj)
1284 {
1285 callback.BeginInvoke(obj, EndFireAndForget, callback);
1286 }
1287 }
1288
1272 public static void FireAndForget(System.Threading.WaitCallback callback) 1289 public static void FireAndForget(System.Threading.WaitCallback callback)
1273 { 1290 {
1274 callback.BeginInvoke(null, EndFireAndForget, callback); 1291 FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
1292 wrapper.FireAndForget(callback);
1275 } 1293 }
1276 1294
1277 public static void FireAndForget(System.Threading.WaitCallback callback, object obj) 1295 public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
1278 { 1296 {
1279 callback.BeginInvoke(obj, EndFireAndForget, callback); 1297 FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
1298 wrapper.FireAndForget(callback, obj);
1280 } 1299 }
1281 1300
1282 private static void EndFireAndForget(IAsyncResult ar) 1301 private static void EndFireAndForget(IAsyncResult ar)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 05a2a63..43c3c7c 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -51,6 +51,44 @@ using Nini.Config;
51 51
52namespace OpenSim.Region.ClientStack.LindenUDP 52namespace OpenSim.Region.ClientStack.LindenUDP
53{ 53{
54 #region Enums
55
56 /// <summary>
57 /// Specifies the fields that have been changed when sending a prim or
58 /// avatar update
59 /// </summary>
60 [Flags]
61 public enum PrimUpdateFlags : uint
62 {
63 None = 0,
64 AttachmentPoint = 1 << 0,
65 Material = 1 << 1,
66 ClickAction = 1 << 2,
67 Scale = 1 << 3,
68 ParentID = 1 << 4,
69 PrimFlags = 1 << 5,
70 PrimData = 1 << 6,
71 MediaURL = 1 << 7,
72 ScratchPad = 1 << 8,
73 Textures = 1 << 9,
74 TextureAnim = 1 << 10,
75 NameValue = 1 << 11,
76 Position = 1 << 12,
77 Rotation = 1 << 13,
78 Velocity = 1 << 14,
79 Acceleration = 1 << 15,
80 AngularVelocity = 1 << 16,
81 CollisionPlane = 1 << 17,
82 Text = 1 << 18,
83 Particles = 1 << 19,
84 ExtraData = 1 << 20,
85 Sound = 1 << 21,
86 Joint = 1 << 22,
87 FullUpdate = UInt32.MaxValue
88 }
89
90 #endregion Enums
91
54 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 92 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
55 93
56 /// <summary> 94 /// <summary>
@@ -282,12 +320,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
282 private readonly IGroupsModule m_GroupsModule; 320 private readonly IGroupsModule m_GroupsModule;
283 321
284 private int m_cachedTextureSerial; 322 private int m_cachedTextureSerial;
285 private Timer m_avatarTerseUpdateTimer; 323 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates =
286 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 324 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
287 private Timer m_primTerseUpdateTimer; 325 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates =
288 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 326 new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
289 private Timer m_primFullUpdateTimer; 327 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates =
290 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = new List<ObjectUpdatePacket.ObjectDataBlock>(); 328 new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>();
291 private int m_moneyBalance; 329 private int m_moneyBalance;
292 private int m_animationSequenceNumber = 1; 330 private int m_animationSequenceNumber = 1;
293 private bool m_SendLogoutPacketWhenClosing = true; 331 private bool m_SendLogoutPacketWhenClosing = true;
@@ -309,13 +347,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
309 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); 347 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>();
310 protected int m_terrainCheckerCount; 348 protected int m_terrainCheckerCount;
311 349
312 // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet 350 // These numbers are guesses at a decent tradeoff between responsiveness
313 protected int m_primTerseUpdatesPerPacket = 10; 351 // of the interest list and throughput. Lower is more responsive, higher
314 protected int m_primFullUpdatesPerPacket = 14; 352 // is better throughput
315 protected int m_primTerseUpdateRate = 10; 353 protected int m_primTerseUpdatesPerPacket = 25;
316 protected int m_primFullUpdateRate = 14; 354 protected int m_primFullUpdatesPerPacket = 100;
317 protected int m_avatarTerseUpdateRate = 50; 355 protected int m_avatarTerseUpdatesPerPacket = 10;
318 protected int m_avatarTerseUpdatesPerPacket = 5;
319 /// <summary>Number of texture packets to put on the queue each time the 356 /// <summary>Number of texture packets to put on the queue each time the
320 /// OnQueueEmpty event is triggered for the texture category</summary> 357 /// OnQueueEmpty event is triggered for the texture category</summary>
321 protected int m_textureSendLimit = 20; 358 protected int m_textureSendLimit = 20;
@@ -438,25 +475,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
438 // Remove ourselves from the scene 475 // Remove ourselves from the scene
439 m_scene.RemoveClient(AgentId); 476 m_scene.RemoveClient(AgentId);
440 477
441 // Shut down timers. Thread Context of this method is murky. Lock all timers
442 if (m_avatarTerseUpdateTimer.Enabled)
443 lock (m_avatarTerseUpdateTimer)
444 m_avatarTerseUpdateTimer.Stop();
445 if (m_primTerseUpdateTimer.Enabled)
446 lock (m_primTerseUpdateTimer)
447 m_primTerseUpdateTimer.Stop();
448 if (m_primFullUpdateTimer.Enabled)
449 lock (m_primFullUpdateTimer)
450 m_primFullUpdateTimer.Stop();
451
452 // We can't reach into other scenes and close the connection 478 // We can't reach into other scenes and close the connection
453 // We need to do this over grid communications 479 // We need to do this over grid communications
454 //m_scene.CloseAllAgents(CircuitCode); 480 //m_scene.CloseAllAgents(CircuitCode);
455 481
456 m_avatarTerseUpdateTimer.Dispose();
457 m_primTerseUpdateTimer.Dispose();
458 m_primFullUpdateTimer.Dispose();
459
460 // Disable UDP handling for this client 482 // Disable UDP handling for this client
461 m_udpClient.Shutdown(); 483 m_udpClient.Shutdown();
462 484
@@ -483,18 +505,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 505
484 public void Stop() 506 public void Stop()
485 { 507 {
486 // Shut down timers. Thread Context is Murky, lock all timers!
487 if (m_avatarTerseUpdateTimer.Enabled)
488 lock (m_avatarTerseUpdateTimer)
489 m_avatarTerseUpdateTimer.Stop();
490
491 if (m_primTerseUpdateTimer.Enabled)
492 lock (m_primTerseUpdateTimer)
493 m_primTerseUpdateTimer.Stop();
494 508
495 if (m_primFullUpdateTimer.Enabled)
496 lock (m_primFullUpdateTimer)
497 m_primFullUpdateTimer.Stop();
498 } 509 }
499 510
500 #endregion Client Methods 511 #endregion Client Methods
@@ -590,18 +601,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
590 601
591 public virtual void Start() 602 public virtual void Start()
592 { 603 {
593 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
594 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
595 m_avatarTerseUpdateTimer.AutoReset = false;
596
597 m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
598 m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
599 m_primTerseUpdateTimer.AutoReset = false;
600
601 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
602 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
603 m_primFullUpdateTimer.AutoReset = false;
604
605 m_scene.AddNewClient(this); 604 m_scene.AddNewClient(this);
606 605
607 RefreshGroupMembership(); 606 RefreshGroupMembership();
@@ -3127,7 +3126,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3127 3126
3128 avp.Sender.IsTrial = false; 3127 avp.Sender.IsTrial = false;
3129 avp.Sender.ID = agentID; 3128 avp.Sender.ID = agentID;
3130 OutPacket(avp, ThrottleOutPacketType.State); 3129 OutPacket(avp, ThrottleOutPacketType.Task);
3131 } 3130 }
3132 3131
3133 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3132 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3159,33 +3158,221 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3159 3158
3160 #endregion 3159 #endregion
3161 3160
3161 #region Prim/Avatar Updates
3162
3163 /*void SendObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3164 {
3165 bool canUseCompressed, canUseImproved;
3166 UpdateFlagsToPacketType(creatorFlags, updateFlags, out canUseCompressed, out canUseImproved);
3167
3168 if (!canUseImproved && !canUseCompressed)
3169 SendFullObjectUpdate(obj, creatorFlags, updateFlags);
3170 else if (!canUseImproved)
3171 SendObjectUpdateCompressed(obj, creatorFlags, updateFlags);
3172 else
3173 SendImprovedTerseObjectUpdate(obj, creatorFlags, updateFlags);
3174 }
3175
3176 void SendFullObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3177 {
3178 IClientAPI owner;
3179 if (m_scene.ClientManager.TryGetValue(obj.OwnerID, out owner) && owner is LLClientView)
3180 {
3181 LLClientView llOwner = (LLClientView)owner;
3182
3183 // Send an update out to the owner
3184 ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket();
3185 updateToOwner.RegionData.RegionHandle = obj.RegionHandle;
3186 //updateToOwner.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3187 updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3188 updateToOwner.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags | creatorFlags | PrimFlags.ObjectYouOwner, 0);
3189
3190 m_udpServer.SendPacket(llOwner.UDPClient, updateToOwner, ThrottleOutPacketType.State, true);
3191 }
3192
3193 // Send an update out to everyone else
3194 ObjectUpdatePacket updateToOthers = new ObjectUpdatePacket();
3195 updateToOthers.RegionData.RegionHandle = obj.RegionHandle;
3196 //updateToOthers.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3197 updateToOthers.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3198 updateToOthers.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags, 0);
3199
3200 m_scene.ClientManager.ForEach(
3201 delegate(IClientAPI client)
3202 {
3203 if (client.AgentId != obj.OwnerID && client is LLClientView)
3204 {
3205 LLClientView llClient = (LLClientView)client;
3206 m_udpServer.SendPacket(llClient.UDPClient, updateToOthers, ThrottleOutPacketType.State, true);
3207 }
3208 }
3209 );
3210 }
3211
3212 void SendObjectUpdateCompressed(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3213 {
3214 }
3215
3216 void SendImprovedTerseObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3217 {
3218 }
3219
3220 void UpdateFlagsToPacketType(PrimFlags creatorFlags, PrimUpdateFlags updateFlags, out bool canUseCompressed, out bool canUseImproved)
3221 {
3222 canUseCompressed = true;
3223 canUseImproved = true;
3224
3225 if ((updateFlags & PrimUpdateFlags.FullUpdate) == PrimUpdateFlags.FullUpdate || creatorFlags != PrimFlags.None)
3226 {
3227 canUseCompressed = false;
3228 canUseImproved = false;
3229 }
3230 else
3231 {
3232 if ((updateFlags & PrimUpdateFlags.Velocity) != 0 ||
3233 (updateFlags & PrimUpdateFlags.Acceleration) != 0 ||
3234 (updateFlags & PrimUpdateFlags.CollisionPlane) != 0 ||
3235 (updateFlags & PrimUpdateFlags.Joint) != 0)
3236 {
3237 canUseCompressed = false;
3238 }
3239
3240 if ((updateFlags & PrimUpdateFlags.PrimFlags) != 0 ||
3241 (updateFlags & PrimUpdateFlags.ParentID) != 0 ||
3242 (updateFlags & PrimUpdateFlags.Scale) != 0 ||
3243 (updateFlags & PrimUpdateFlags.PrimData) != 0 ||
3244 (updateFlags & PrimUpdateFlags.Text) != 0 ||
3245 (updateFlags & PrimUpdateFlags.NameValue) != 0 ||
3246 (updateFlags & PrimUpdateFlags.ExtraData) != 0 ||
3247 (updateFlags & PrimUpdateFlags.TextureAnim) != 0 ||
3248 (updateFlags & PrimUpdateFlags.Sound) != 0 ||
3249 (updateFlags & PrimUpdateFlags.Particles) != 0 ||
3250 (updateFlags & PrimUpdateFlags.Material) != 0 ||
3251 (updateFlags & PrimUpdateFlags.ClickAction) != 0 ||
3252 (updateFlags & PrimUpdateFlags.MediaURL) != 0 ||
3253 (updateFlags & PrimUpdateFlags.Joint) != 0)
3254 {
3255 canUseImproved = false;
3256 }
3257 }
3258 }
3259
3260 static ObjectUpdatePacket.ObjectDataBlock BuildUpdateBlockFromPrim(SceneObjectPart prim, UUID assetID, PrimFlags flags, uint crc)
3261 {
3262 byte[] objectData = new byte[60];
3263 prim.OffsetPosition.ToBytes(objectData, 0);
3264 prim.Velocity.ToBytes(objectData, 12);
3265 prim.Acceleration.ToBytes(objectData, 24);
3266 prim.RotationOffset.ToBytes(objectData, 36);
3267 prim.AngularVelocity.ToBytes(objectData, 48);
3268
3269 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
3270 update.ClickAction = (byte)prim.ClickAction;
3271 update.CRC = crc;
3272 update.ExtraParams = prim.Shape.ExtraParams ?? Utils.EmptyBytes;
3273 update.Flags = (byte)flags;
3274 update.FullID = prim.UUID;
3275 update.ID = prim.LocalId;
3276 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
3277 //update.JointPivot = Vector3.Zero;
3278 //update.JointType = 0;
3279 update.Material = prim.Material;
3280 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
3281 if (prim.IsAttachment)
3282 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + assetID);
3283 else
3284 update.NameValue = Utils.EmptyBytes;
3285 update.ObjectData = objectData;
3286 update.ParentID = prim.ParentID;
3287 update.PathBegin = prim.Shape.PathBegin;
3288 update.PathCurve = prim.Shape.PathCurve;
3289 update.PathEnd = prim.Shape.PathEnd;
3290 update.PathRadiusOffset = prim.Shape.PathRadiusOffset;
3291 update.PathRevolutions = prim.Shape.PathRevolutions;
3292 update.PathScaleX = prim.Shape.PathScaleX;
3293 update.PathScaleY = prim.Shape.PathScaleY;
3294 update.PathShearX = prim.Shape.PathShearX;
3295 update.PathShearY = prim.Shape.PathShearY;
3296 update.PathSkew = prim.Shape.PathSkew;
3297 update.PathTaperX = prim.Shape.PathTaperX;
3298 update.PathTaperY = prim.Shape.PathTaperY;
3299 update.PathTwist = prim.Shape.PathTwist;
3300 update.PathTwistBegin = prim.Shape.PathTwistBegin;
3301 update.PCode = prim.Shape.PCode;
3302 update.ProfileBegin = prim.Shape.ProfileBegin;
3303 update.ProfileCurve = prim.Shape.ProfileCurve;
3304 update.ProfileEnd = prim.Shape.ProfileEnd;
3305 update.ProfileHollow = prim.Shape.ProfileHollow;
3306 update.PSBlock = prim.ParticleSystem ?? Utils.EmptyBytes;
3307 update.TextColor = new Color4(prim.Color).GetBytes(true);
3308 update.TextureAnim = prim.TextureAnimation ?? Utils.EmptyBytes;
3309 update.TextureEntry = prim.Shape.TextureEntry ?? Utils.EmptyBytes;
3310 update.Scale = prim.Scale;
3311 update.State = prim.Shape.State;
3312 update.Text = Util.StringToBytes256(prim.Text);
3313 update.UpdateFlags = (uint)flags;
3314
3315 if (prim.Sound != UUID.Zero)
3316 {
3317 update.Sound = prim.Sound;
3318 update.OwnerID = prim.OwnerID;
3319 update.Gain = (float)prim.SoundGain;
3320 update.Radius = (float)prim.SoundRadius;
3321 }
3322
3323 switch ((PCode)prim.Shape.PCode)
3324 {
3325 case PCode.Grass:
3326 case PCode.Tree:
3327 case PCode.NewTree:
3328 update.Data = new byte[] { prim.Shape.State };
3329 break;
3330 default:
3331 // TODO: Support ScratchPad
3332 //if (prim.ScratchPad != null)
3333 //{
3334 // update.Data = new byte[prim.ScratchPad.Length];
3335 // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length);
3336 //}
3337 //else
3338 //{
3339 // update.Data = Utils.EmptyBytes;
3340 //}
3341 update.Data = Utils.EmptyBytes;
3342 break;
3343 }
3344
3345 return update;
3346 }*/
3347
3348 #endregion Prim/Avatar Updates
3349
3162 #region Avatar Packet/data sending Methods 3350 #region Avatar Packet/data sending Methods
3163 3351
3164 /// <summary> 3352 /// <summary>
3165 /// send a objectupdate packet with information about the clients avatar 3353 /// send a objectupdate packet with information about the clients avatar
3166 /// </summary> 3354 /// </summary>
3167 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, 3355 public void SendAvatarData(SendAvatarData data)
3168 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
3169 { 3356 {
3170 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3357 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3171 // TODO: don't create new blocks if recycling an old packet 3358 // TODO: don't create new blocks if recycling an old packet
3172 objupdate.RegionData.RegionHandle = regionHandle; 3359 objupdate.RegionData.RegionHandle = data.regionHandle;
3173 objupdate.RegionData.TimeDilation = ushort.MaxValue; 3360 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3174 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; 3361 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3175 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry); 3362 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(data.textureEntry);
3176 3363
3177 //give this avatar object a local id and assign the user a name 3364 //give this avatar object a local id and assign the user a name
3178 objupdate.ObjectData[0].ID = avatarLocalID; 3365 objupdate.ObjectData[0].ID = data.avatarLocalID;
3179 objupdate.ObjectData[0].FullID = avatarID; 3366 objupdate.ObjectData[0].FullID = data.avatarID;
3180 objupdate.ObjectData[0].ParentID = parentID; 3367 objupdate.ObjectData[0].ParentID = data.parentID;
3181 objupdate.ObjectData[0].NameValue = 3368 objupdate.ObjectData[0].NameValue =
3182 Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); 3369 Utils.StringToBytes("FirstName STRING RW SV " + data.firstName + "\nLastName STRING RW SV " + data.lastName + "\nTitle STRING RW SV " + data.grouptitle);
3183 3370
3184 Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); 3371 Vector3 pos2 = new Vector3(data.Pos.X, data.Pos.Y, data.Pos.Z);
3185 byte[] pb = pos2.GetBytes(); 3372 byte[] pb = pos2.GetBytes();
3186 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); 3373 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length);
3187 3374
3188 byte[] rot = rotation.GetBytes(); 3375 byte[] rot = data.rotation.GetBytes();
3189 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); 3376 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length);
3190 3377
3191 objupdate.Header.Zerocoded = true; 3378 objupdate.Header.Zerocoded = true;
@@ -3196,38 +3383,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3196 /// Send a terse positional/rotation/velocity update about an avatar 3383 /// Send a terse positional/rotation/velocity update about an avatar
3197 /// to the client. This avatar can be that of the client itself. 3384 /// to the client. This avatar can be that of the client itself.
3198 /// </summary> 3385 /// </summary>
3199 public virtual void SendAvatarTerseUpdate(ulong regionHandle, 3386 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
3200 ushort timeDilation, uint localID, Vector3 position,
3201 Vector3 velocity, Quaternion rotation, UUID agentid)
3202 { 3387 {
3388 if (data.priority == double.NaN)
3389 {
3390 m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
3391 return;
3392 }
3393
3394 Quaternion rotation = data.rotation;
3395
3203 if (rotation.X == rotation.Y && 3396 if (rotation.X == rotation.Y &&
3204 rotation.Y == rotation.Z && 3397 rotation.Y == rotation.Z &&
3205 rotation.Z == rotation.W && rotation.W == 0) 3398 rotation.Z == rotation.W && rotation.W == 0)
3206 rotation = Quaternion.Identity; 3399 rotation = Quaternion.Identity;
3207 3400
3208 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = 3401 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock =
3209 CreateAvatarImprovedBlock(localID, position, velocity,rotation); 3402 CreateAvatarImprovedBlock(data.localID, data.position, data.velocity, rotation);
3210 3403
3211 lock (m_avatarTerseUpdates) 3404 lock (m_avatarTerseUpdates.SyncRoot)
3212 { 3405 m_avatarTerseUpdates.Enqueue(data.priority, terseBlock, data.localID);
3213 m_avatarTerseUpdates.Add(terseBlock);
3214
3215 // If packet is full or own movement packet, send it.
3216 if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket)
3217 {
3218 ProcessAvatarTerseUpdates(this, null);
3219 }
3220 else if (m_avatarTerseUpdates.Count == 1)
3221 {
3222 lock (m_avatarTerseUpdateTimer)
3223 m_avatarTerseUpdateTimer.Start();
3224 }
3225 }
3226 } 3406 }
3227 3407
3228 private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) 3408 private void ProcessAvatarTerseUpdates()
3229 { 3409 {
3230 lock (m_avatarTerseUpdates) 3410 lock (m_avatarTerseUpdates.SyncRoot)
3231 { 3411 {
3232 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); 3412 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3233 3413
@@ -3237,44 +3417,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3237 terse.RegionData.TimeDilation = 3417 terse.RegionData.TimeDilation =
3238 (ushort)(Scene.TimeDilation * ushort.MaxValue); 3418 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3239 3419
3240 int max = m_avatarTerseUpdatesPerPacket; 3420 int count = Math.Min(m_avatarTerseUpdates.Count, m_avatarTerseUpdatesPerPacket);
3241 if (max > m_avatarTerseUpdates.Count)
3242 max = m_avatarTerseUpdates.Count;
3243
3244 int count = 0;
3245 int size = 0;
3246
3247 byte[] zerobuffer = new byte[1024];
3248 byte[] blockbuffer = new byte[1024];
3249
3250 for (count = 0 ; count < max ; count++)
3251 {
3252 int length = 0;
3253 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length);
3254 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3255 if (size + length > Packet.MTU)
3256 break;
3257 size += length;
3258 }
3259 3421
3260 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; 3422 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3261 3423 for (int i = 0; i < count; i++)
3262 for (int i = 0 ; i < count ; i++) 3424 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
3263 {
3264 terse.ObjectData[i] = m_avatarTerseUpdates[0];
3265 m_avatarTerseUpdates.RemoveAt(0);
3266 }
3267 3425
3268 terse.Header.Reliable = false; 3426 terse.Header.Reliable = false;
3269 terse.Header.Zerocoded = true; 3427 terse.Header.Zerocoded = true;
3270 // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed
3271 OutPacket(terse, ThrottleOutPacketType.Task);
3272 3428
3273 if (m_avatarTerseUpdates.Count == 0) 3429 OutPacket(terse, ThrottleOutPacketType.Task);
3274 {
3275 lock (m_avatarTerseUpdateTimer)
3276 m_avatarTerseUpdateTimer.Stop();
3277 }
3278 } 3430 }
3279 } 3431 }
3280 3432
@@ -3342,54 +3494,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3342 OutPacket(attach, ThrottleOutPacketType.Task); 3494 OutPacket(attach, ThrottleOutPacketType.Task);
3343 } 3495 }
3344 3496
3345 public void SendPrimitiveToClient( 3497 public void SendPrimitiveToClient(SendPrimitiveData data)
3346 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3347 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
3348 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
3349 uint parentID, byte[] particleSystem, byte clickAction, byte material)
3350 { 3498 {
3351 byte[] textureanim = new byte[0]; 3499 if (data.priority == double.NaN)
3352 3500 {
3353 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel, 3501 m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
3354 acc, rotation, rvel, flags, 3502 return;
3355 objectID, ownerID, text, color, parentID, particleSystem, 3503 }
3356 clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0);
3357 }
3358 3504
3359 public void SendPrimitiveToClient( 3505 Quaternion rotation = data.rotation;
3360 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3361 Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity,
3362 uint flags,
3363 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
3364 byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius)
3365 {
3366 3506
3367 if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3507 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
3368 return; 3508 return;
3369 if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) 3509 if (data.primShape.PCode == 9 && data.primShape.State != 0 && data.parentID == 0)
3370 return; 3510 return;
3371 3511
3372 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3512 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0.0f)
3373 rotation = Quaternion.Identity; 3513 rotation = Quaternion.Identity;
3374 3514
3375 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); 3515 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data.primShape, data.flags);
3376 3516
3377 objectData.ID = localID; 3517 objectData.ID = data.localID;
3378 objectData.FullID = objectID; 3518 objectData.FullID = data.objectID;
3379 objectData.OwnerID = ownerID; 3519 objectData.OwnerID = data.ownerID;
3380 3520
3381 objectData.Text = Util.StringToBytes256(text); 3521 objectData.Text = Util.StringToBytes256(data.text);
3382 objectData.TextColor[0] = color[0]; 3522 objectData.TextColor[0] = data.color[0];
3383 objectData.TextColor[1] = color[1]; 3523 objectData.TextColor[1] = data.color[1];
3384 objectData.TextColor[2] = color[2]; 3524 objectData.TextColor[2] = data.color[2];
3385 objectData.TextColor[3] = color[3]; 3525 objectData.TextColor[3] = data.color[3];
3386 objectData.ParentID = parentID; 3526 objectData.ParentID = data.parentID;
3387 objectData.PSBlock = particleSystem; 3527 objectData.PSBlock = data.particleSystem;
3388 objectData.ClickAction = clickAction; 3528 objectData.ClickAction = data.clickAction;
3389 objectData.Material = material; 3529 objectData.Material = data.material;
3390 objectData.Flags = 0; 3530 objectData.Flags = 0;
3391 3531
3392 if (attachment) 3532 if (data.attachment)
3393 { 3533 {
3394 // Necessary??? 3534 // Necessary???
3395 objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); 3535 objectData.JointAxisOrAnchor = new Vector3(0, 0, 2);
@@ -3397,14 +3537,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3397 3537
3398 // Item from inventory??? 3538 // Item from inventory???
3399 objectData.NameValue = 3539 objectData.NameValue =
3400 Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid); 3540 Utils.StringToBytes("AttachItemID STRING RW SV " + data.AssetId.Guid);
3401 objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16)); 3541 objectData.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16));
3402 } 3542 }
3403 3543
3404 // Xantor 20080528: Send sound info as well 3544 // Xantor 20080528: Send sound info as well
3405 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again 3545 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again
3406 objectData.Sound = SoundId; 3546 objectData.Sound = data.SoundId;
3407 if (SoundId == UUID.Zero) 3547 if (data.SoundId == UUID.Zero)
3408 { 3548 {
3409 objectData.OwnerID = UUID.Zero; 3549 objectData.OwnerID = UUID.Zero;
3410 objectData.Gain = 0.0f; 3550 objectData.Gain = 0.0f;
@@ -3413,48 +3553,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3413 } 3553 }
3414 else 3554 else
3415 { 3555 {
3416 objectData.OwnerID = ownerID; 3556 objectData.OwnerID = data.ownerID;
3417 objectData.Gain = (float)SoundGain; 3557 objectData.Gain = (float)data.SoundVolume;
3418 objectData.Radius = (float)SoundRadius; 3558 objectData.Radius = (float)data.SoundRadius;
3419 objectData.Flags = SoundFlags; 3559 objectData.Flags = data.SoundFlags;
3420 } 3560 }
3421 3561
3422 byte[] pb = pos.GetBytes(); 3562 byte[] pb = data.pos.GetBytes();
3423 Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length); 3563 Buffer.BlockCopy(pb, 0, objectData.ObjectData, 0, pb.Length);
3424 3564
3425 byte[] vel = velocity.GetBytes(); 3565 byte[] vel = data.vel.GetBytes();
3426 Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length); 3566 Buffer.BlockCopy(vel, 0, objectData.ObjectData, pb.Length, vel.Length);
3427 3567
3428 byte[] rot = rotation.GetBytes(); 3568 byte[] rot = rotation.GetBytes();
3429 Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); 3569 Buffer.BlockCopy(rot, 0, objectData.ObjectData, 36, rot.Length);
3430 3570
3431 byte[] rvel = rotational_velocity.GetBytes(); 3571 byte[] rvel = data.rvel.GetBytes();
3432 Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length); 3572 Buffer.BlockCopy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length);
3433 3573
3434 if (textureanim.Length > 0) 3574 if (data.textureanim.Length > 0)
3435 { 3575 {
3436 objectData.TextureAnim = textureanim; 3576 objectData.TextureAnim = data.textureanim;
3437 } 3577 }
3438 3578
3439 lock (m_primFullUpdates) 3579 lock (m_primFullUpdates.SyncRoot)
3440 { 3580 m_primFullUpdates.Enqueue(data.priority, objectData, data.localID);
3441 if (m_primFullUpdates.Count == 0)
3442 m_primFullUpdateTimer.Start();
3443
3444 m_primFullUpdates.Add(objectData);
3445
3446 if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket)
3447 ProcessPrimFullUpdates(this, null);
3448 }
3449 } 3581 }
3450 3582
3451 void HandleQueueEmpty(ThrottleOutPacketType queue) 3583 void HandleQueueEmpty(ThrottleOutPacketType queue)
3452 { 3584 {
3585 int count = 0;
3586
3453 switch (queue) 3587 switch (queue)
3454 { 3588 {
3455 case ThrottleOutPacketType.Texture: 3589 case ThrottleOutPacketType.Texture:
3456 ProcessTextureRequests(); 3590 ProcessTextureRequests();
3457 break; 3591 break;
3592 case ThrottleOutPacketType.Task:
3593 lock (m_avatarTerseUpdates.SyncRoot)
3594 count = m_avatarTerseUpdates.Count;
3595 if (count > 0)
3596 {
3597 ProcessAvatarTerseUpdates();
3598 return;
3599 }
3600 break;
3601 case ThrottleOutPacketType.State:
3602 lock (m_primFullUpdates.SyncRoot)
3603 count = m_primFullUpdates.Count;
3604 if (count > 0)
3605 {
3606 ProcessPrimFullUpdates();
3607 return;
3608 }
3609
3610 lock (m_primTerseUpdates.SyncRoot)
3611 count = m_primTerseUpdates.Count;
3612 if (count > 0)
3613 {
3614 ProcessPrimTerseUpdates();
3615 return;
3616 }
3617 break;
3458 } 3618 }
3459 } 3619 }
3460 3620
@@ -3464,18 +3624,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3464 m_imageManager.ProcessImageQueue(m_textureSendLimit); 3624 m_imageManager.ProcessImageQueue(m_textureSendLimit);
3465 } 3625 }
3466 3626
3467 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) 3627 void ProcessPrimFullUpdates()
3468 { 3628 {
3469 lock (m_primFullUpdates) 3629 lock (m_primFullUpdates.SyncRoot)
3470 { 3630 {
3471 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3472 {
3473 lock (m_primFullUpdateTimer)
3474 m_primFullUpdateTimer.Stop();
3475
3476 return;
3477 }
3478
3479 ObjectUpdatePacket outPacket = 3631 ObjectUpdatePacket outPacket =
3480 (ObjectUpdatePacket)PacketPool.Instance.GetPacket( 3632 (ObjectUpdatePacket)PacketPool.Instance.GetPacket(
3481 PacketType.ObjectUpdate); 3633 PacketType.ObjectUpdate);
@@ -3485,84 +3637,50 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3485 outPacket.RegionData.TimeDilation = 3637 outPacket.RegionData.TimeDilation =
3486 (ushort)(Scene.TimeDilation * ushort.MaxValue); 3638 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3487 3639
3488 int max = m_primFullUpdates.Count; 3640 int count = Math.Min(m_primFullUpdates.Count, m_primFullUpdatesPerPacket);
3489 if (max > m_primFullUpdatesPerPacket)
3490 max = m_primFullUpdatesPerPacket;
3491
3492 int count = 0;
3493 int size = 0;
3494
3495 byte[] zerobuffer = new byte[1024];
3496 byte[] blockbuffer = new byte[1024];
3497 3641
3498 for (count = 0 ; count < max ; count++) 3642 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count];
3499 { 3643 for (int i = 0; i < count; i++)
3500 int length = 0; 3644 outPacket.ObjectData[i] = m_primFullUpdates.Dequeue();
3501 m_primFullUpdates[count].ToBytes(blockbuffer, ref length);
3502 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3503 if (size + length > Packet.MTU)
3504 break;
3505 size += length;
3506 }
3507
3508 outPacket.ObjectData =
3509 new ObjectUpdatePacket.ObjectDataBlock[count];
3510
3511 for (int index = 0 ; index < count ; index++)
3512 {
3513 outPacket.ObjectData[index] = m_primFullUpdates[0];
3514 m_primFullUpdates.RemoveAt(0);
3515 }
3516 3645
3517 outPacket.Header.Zerocoded = true; 3646 outPacket.Header.Zerocoded = true;
3518 OutPacket(outPacket, ThrottleOutPacketType.State); 3647 OutPacket(outPacket, ThrottleOutPacketType.State);
3519
3520 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3521 lock (m_primFullUpdateTimer)
3522 m_primFullUpdateTimer.Stop();
3523 } 3648 }
3524 } 3649 }
3525 3650
3526 /// <summary> 3651 /// <summary>
3527 /// 3652 ///
3528 /// </summary> 3653 /// </summary>
3529 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 3654 //public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
3530 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) 3655 // Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint)
3656 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
3531 { 3657 {
3532 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3658 if (data.priority == double.NaN)
3659 {
3660 m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update");
3661 return;
3662 }
3663
3664 Quaternion rotation = data.rotation;
3665
3666 if (data.attachPoint > 30 && data.owner != AgentId) // Someone else's HUD
3533 return; 3667 return;
3534 3668
3535 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3669 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0)
3536 rotation = Quaternion.Identity; 3670 rotation = Quaternion.Identity;
3537 3671
3538 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = 3672 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData =
3539 CreatePrimImprovedBlock(localID, position, rotation, 3673 CreatePrimImprovedBlock(data.localID, data.position, rotation,
3540 velocity, rotationalvelocity, state); 3674 data.velocity, data.rotationalvelocity, data.state);
3541
3542 lock (m_primTerseUpdates)
3543 {
3544 if (m_primTerseUpdates.Count == 0)
3545 m_primTerseUpdateTimer.Start();
3546
3547 m_primTerseUpdates.Add(objectData);
3548 3675
3549 if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket) 3676 lock (m_primTerseUpdates.SyncRoot)
3550 ProcessPrimTerseUpdates(this, null); 3677 m_primTerseUpdates.Enqueue(data.priority, objectData, data.localID);
3551 }
3552 } 3678 }
3553 3679
3554 void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) 3680 void ProcessPrimTerseUpdates()
3555 { 3681 {
3556 lock (m_primTerseUpdates) 3682 lock (m_primTerseUpdates.SyncRoot)
3557 { 3683 {
3558 if (m_primTerseUpdates.Count == 0)
3559 {
3560 lock (m_primTerseUpdateTimer)
3561 m_primTerseUpdateTimer.Stop();
3562
3563 return;
3564 }
3565
3566 ImprovedTerseObjectUpdatePacket outPacket = 3684 ImprovedTerseObjectUpdatePacket outPacket =
3567 (ImprovedTerseObjectUpdatePacket) 3685 (ImprovedTerseObjectUpdatePacket)
3568 PacketPool.Instance.GetPacket( 3686 PacketPool.Instance.GetPacket(
@@ -3573,43 +3691,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3573 outPacket.RegionData.TimeDilation = 3691 outPacket.RegionData.TimeDilation =
3574 (ushort)(Scene.TimeDilation * ushort.MaxValue); 3692 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3575 3693
3576 int max = m_primTerseUpdates.Count; 3694 int count = Math.Min(m_primTerseUpdates.Count, m_primTerseUpdatesPerPacket);
3577 if (max > m_primTerseUpdatesPerPacket)
3578 max = m_primTerseUpdatesPerPacket;
3579
3580 int count = 0;
3581 int size = 0;
3582 3695
3583 byte[] zerobuffer = new byte[1024]; 3696 outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3584 byte[] blockbuffer = new byte[1024]; 3697 for (int i = 0; i < count; i++)
3585 3698 outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
3586 for (count = 0 ; count < max ; count++)
3587 {
3588 int length = 0;
3589 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length);
3590 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3591 if (size + length > Packet.MTU)
3592 break;
3593 size += length;
3594 }
3595
3596 outPacket.ObjectData =
3597 new ImprovedTerseObjectUpdatePacket.
3598 ObjectDataBlock[count];
3599
3600 for (int index = 0 ; index < count ; index++)
3601 {
3602 outPacket.ObjectData[index] = m_primTerseUpdates[0];
3603 m_primTerseUpdates.RemoveAt(0);
3604 }
3605 3699
3606 outPacket.Header.Reliable = false; 3700 outPacket.Header.Reliable = false;
3607 outPacket.Header.Zerocoded = true; 3701 outPacket.Header.Zerocoded = true;
3608 OutPacket(outPacket, ThrottleOutPacketType.State); 3702 OutPacket(outPacket, ThrottleOutPacketType.State);
3609
3610 if (m_primTerseUpdates.Count == 0)
3611 lock (m_primTerseUpdateTimer)
3612 m_primTerseUpdateTimer.Stop();
3613 } 3703 }
3614 } 3704 }
3615 3705
@@ -3617,15 +3707,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3617 { 3707 {
3618 while (m_primFullUpdates.Count > 0) 3708 while (m_primFullUpdates.Count > 0)
3619 { 3709 {
3620 ProcessPrimFullUpdates(this, null); 3710 ProcessPrimFullUpdates();
3621 } 3711 }
3622 while (m_primTerseUpdates.Count > 0) 3712 while (m_primTerseUpdates.Count > 0)
3623 { 3713 {
3624 ProcessPrimTerseUpdates(this, null); 3714 ProcessPrimTerseUpdates();
3625 } 3715 }
3626 while (m_avatarTerseUpdates.Count > 0) 3716 while (m_avatarTerseUpdates.Count > 0)
3627 { 3717 {
3628 ProcessAvatarTerseUpdates(this, null); 3718 ProcessAvatarTerseUpdates();
3629 } 3719 }
3630 } 3720 }
3631 3721
@@ -10371,5 +10461,136 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10371 pack.TextureData.TextureID = textureID; 10461 pack.TextureData.TextureID = textureID;
10372 OutPacket(pack, ThrottleOutPacketType.Task); 10462 OutPacket(pack, ThrottleOutPacketType.Task);
10373 } 10463 }
10464
10465 #region PriorityQueue
10466 private class PriorityQueue<TPriority, TValue>
10467 {
10468 private MinHeap<MinHeapItem>[] heaps = new MinHeap<MinHeapItem>[1];
10469 private Dictionary<uint, LookupItem> lookup_table = new Dictionary<uint, LookupItem>();
10470 private Comparison<TPriority> comparison;
10471 private object sync_root = new object();
10472
10473 internal PriorityQueue() :
10474 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<TPriority>.Default) { }
10475 internal PriorityQueue(int capacity) :
10476 this(capacity, Comparer<TPriority>.Default) { }
10477 internal PriorityQueue(IComparer<TPriority> comparer) :
10478 this(new Comparison<TPriority>(comparer.Compare)) { }
10479 internal PriorityQueue(Comparison<TPriority> comparison) :
10480 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
10481 internal PriorityQueue(int capacity, IComparer<TPriority> comparer) :
10482 this(capacity, new Comparison<TPriority>(comparer.Compare)) { }
10483 internal PriorityQueue(int capacity, Comparison<TPriority> comparison)
10484 {
10485 for (int i = 0; i < heaps.Length; ++i)
10486 heaps[i] = new MinHeap<MinHeapItem>(capacity);
10487 this.comparison = comparison;
10488 }
10489
10490 internal object SyncRoot { get { return this.sync_root; } }
10491 internal int Count
10492 {
10493 get
10494 {
10495 int count = 0;
10496 for (int i = 0; i < heaps.Length; ++i)
10497 count = heaps[i].Count;
10498 return count;
10499 }
10500 }
10501
10502 internal bool Enqueue(TPriority priority, TValue value, uint local_id)
10503 {
10504 LookupItem item;
10505
10506 if (lookup_table.TryGetValue(local_id, out item))
10507 {
10508 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.comparison);
10509 return false;
10510 }
10511 else
10512 {
10513 item.Heap = heaps[0];
10514 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.comparison), ref item.Handle);
10515 lookup_table.Add(local_id, item);
10516 return true;
10517 }
10518 }
10519
10520 internal TValue Peek()
10521 {
10522 for (int i = 0; i < heaps.Length; ++i)
10523 if (heaps[i].Count > 0)
10524 return heaps[i].Min().Value;
10525 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10526 }
10527
10528 internal TValue Dequeue()
10529 {
10530 for (int i = 0; i < heaps.Length; ++i)
10531 {
10532 if (heaps[i].Count > 0)
10533 {
10534 MinHeapItem item = heaps[i].RemoveMin();
10535 lookup_table.Remove(item.LocalID);
10536 return item.Value;
10537 }
10538 }
10539 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10540 }
10541
10542 #region MinHeapItem
10543 private struct MinHeapItem : IComparable<MinHeapItem>
10544 {
10545 private TPriority priority;
10546 private TValue value;
10547 private uint local_id;
10548 private Comparison<TPriority> comparison;
10549
10550 internal MinHeapItem(TPriority priority, TValue value, uint local_id) :
10551 this(priority, value, local_id, Comparer<TPriority>.Default) { }
10552 internal MinHeapItem(TPriority priority, TValue value, uint local_id, IComparer<TPriority> comparer) :
10553 this(priority, value, local_id, new Comparison<TPriority>(comparer.Compare)) { }
10554 internal MinHeapItem(TPriority priority, TValue value, uint local_id, Comparison<TPriority> comparison)
10555 {
10556 this.priority = priority;
10557 this.value = value;
10558 this.local_id = local_id;
10559 this.comparison = comparison;
10560 }
10561
10562 internal TPriority Priority { get { return this.priority; } }
10563 internal TValue Value { get { return this.value; } }
10564 internal uint LocalID { get { return this.local_id; } }
10565
10566 public override string ToString()
10567 {
10568 StringBuilder sb = new StringBuilder();
10569 sb.Append("[");
10570 if (this.priority != null)
10571 sb.Append(this.priority.ToString());
10572 sb.Append(",");
10573 if (this.value != null)
10574 sb.Append(this.value.ToString());
10575 sb.Append("]");
10576 return sb.ToString();
10577 }
10578
10579 public int CompareTo(MinHeapItem other)
10580 {
10581 return this.comparison(this.priority, other.priority);
10582 }
10583 }
10584 #endregion
10585
10586 #region LookupItem
10587 private struct LookupItem {
10588 internal MinHeap<MinHeapItem> Heap;
10589 internal IHandle Handle;
10590 }
10591 #endregion
10592 }
10593 #endregion
10594
10374 } 10595 }
10375} 10596}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 4eee6b6..9476eed 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
@@ -170,7 +170,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
170 { 170 {
171 ThrottleOutPacketType type = (ThrottleOutPacketType)i; 171 ThrottleOutPacketType type = (ThrottleOutPacketType)i;
172 172
173 // Initialize the packet outboxes, where packets sit while they are waiting for tokens
173 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>(); 174 m_packetOutboxes[i] = new OpenSim.Framework.LocklessQueue<OutgoingPacket>();
175 // Initialize the token buckets that control the throttling for each category
174 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type)); 176 m_throttleCategories[i] = new TokenBucket(m_throttle, rates.GetLimit(type), rates.GetRate(type));
175 } 177 }
176 178
@@ -293,36 +295,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP
293 int state = (int)((float)task * STATE_TASK_PERCENTAGE); 295 int state = (int)((float)task * STATE_TASK_PERCENTAGE);
294 task -= state; 296 task -= state;
295 297
296 int ceiling = Int32.MaxValue; 298 // Make sure none of the throttles are set below our packet MTU,
297 if (m_defaultThrottleRates.Total != 0) 299 // otherwise a throttle could become permanently clogged
298 { 300 resend = Math.Max(resend, LLUDPServer.MTU);
299 ceiling = m_defaultThrottleRates.Total; 301 land = Math.Max(land, LLUDPServer.MTU);
300 if (ceiling < Packet.MTU) ceiling = Packet.MTU; 302 wind = Math.Max(wind, LLUDPServer.MTU);
301 } 303 cloud = Math.Max(cloud, LLUDPServer.MTU);
302 304 task = Math.Max(task, LLUDPServer.MTU);
303 resend = Utils.Clamp(resend, Packet.MTU, ceiling); 305 texture = Math.Max(texture, LLUDPServer.MTU);
304 land = Utils.Clamp(land, Packet.MTU, ceiling); 306 asset = Math.Max(asset, LLUDPServer.MTU);
305 wind = Utils.Clamp(wind, Packet.MTU, ceiling); 307 state = Math.Max(state, LLUDPServer.MTU);
306 cloud = Utils.Clamp(cloud, Packet.MTU, ceiling);
307 task = Utils.Clamp(task, Packet.MTU, ceiling);
308 texture = Utils.Clamp(texture, Packet.MTU, ceiling);
309 asset = Utils.Clamp(asset, Packet.MTU, ceiling);
310 state = Utils.Clamp(state, Packet.MTU, ceiling);
311 308
312 int total = resend + land + wind + cloud + task + texture + asset + state; 309 int total = resend + land + wind + cloud + task + texture + asset + state;
313 int taskTotal = task + state;
314 310
315 m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}", 311 m_log.DebugFormat("[LLUDPCLIENT]: {0} is setting throttles. Resend={1}, Land={2}, Wind={3}, Cloud={4}, Task={5}, Texture={6}, Asset={7}, State={8}, Total={9}",
316 AgentID, resend, land, wind, cloud, task, texture, asset, state, total); 312 AgentID, resend, land, wind, cloud, task, texture, asset, state, total);
317 313
318 SetThrottle(ThrottleOutPacketType.Resend, resend, resend); 314 // Update the token buckets with new throttle values
319 SetThrottle(ThrottleOutPacketType.Land, land, land); 315 TokenBucket bucket;
320 SetThrottle(ThrottleOutPacketType.Wind, wind, wind); 316
321 SetThrottle(ThrottleOutPacketType.Cloud, cloud, cloud); 317 bucket = m_throttle;
322 SetThrottle(ThrottleOutPacketType.Task, task, taskTotal); 318 bucket.MaxBurst = total;
323 SetThrottle(ThrottleOutPacketType.Texture, texture, texture); 319
324 SetThrottle(ThrottleOutPacketType.Asset, asset, asset); 320 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Resend];
325 SetThrottle(ThrottleOutPacketType.State, state, taskTotal); 321 bucket.DripRate = bucket.MaxBurst = resend;
322
323 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Land];
324 bucket.DripRate = bucket.MaxBurst = land;
325
326 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Wind];
327 bucket.DripRate = bucket.MaxBurst = wind;
328
329 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Cloud];
330 bucket.DripRate = bucket.MaxBurst = cloud;
331
332 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Asset];
333 bucket.DripRate = bucket.MaxBurst = asset;
334
335 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Task];
336 bucket.DripRate = task + state + texture;
337 bucket.MaxBurst = task + state + texture;
338
339 bucket = m_throttleCategories[(int)ThrottleOutPacketType.State];
340 bucket.DripRate = state + texture;
341 bucket.MaxBurst = state + texture;
342
343 bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture];
344 bucket.DripRate = texture;
345 bucket.MaxBurst = texture;
326 } 346 }
327 347
328 public byte[] GetThrottlesPacked() 348 public byte[] GetThrottlesPacked()
@@ -342,17 +362,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
342 return data; 362 return data;
343 } 363 }
344 364
345 public void SetThrottle(ThrottleOutPacketType category, int rate, int maxBurst)
346 {
347 int i = (int)category;
348 if (i >= 0 && i < m_throttleCategories.Length)
349 {
350 TokenBucket bucket = m_throttleCategories[(int)category];
351 bucket.DripRate = rate;
352 bucket.MaxBurst = maxBurst;
353 }
354 }
355
356 public bool EnqueueOutgoing(OutgoingPacket packet) 365 public bool EnqueueOutgoing(OutgoingPacket packet)
357 { 366 {
358 int category = (int)packet.Category; 367 int category = (int)packet.Category;
@@ -395,9 +404,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
395 TokenBucket bucket; 404 TokenBucket bucket;
396 bool packetSent = false; 405 bool packetSent = false;
397 406
407 //string queueDebugOutput = String.Empty; // Serious debug business
408
398 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++) 409 for (int i = 0; i < THROTTLE_CATEGORY_COUNT; i++)
399 { 410 {
400 bucket = m_throttleCategories[i]; 411 bucket = m_throttleCategories[i];
412 //queueDebugOutput += m_packetOutboxes[i].Count + " "; // Serious debug business
401 413
402 if (m_nextPackets[i] != null) 414 if (m_nextPackets[i] != null)
403 { 415 {
@@ -449,6 +461,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
449 } 461 }
450 } 462 }
451 463
464 //m_log.Info("[LLUDPCLIENT]: Queues: " + queueDebugOutput); // Serious debug business
452 return packetSent; 465 return packetSent;
453 } 466 }
454 467
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 545a0bc..8bfab6a 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
@@ -89,6 +89,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
89 /// </summary> 89 /// </summary>
90 public class LLUDPServer : OpenSimUDPBase 90 public class LLUDPServer : OpenSimUDPBase
91 { 91 {
92 /// <summary>Maximum transmission unit, or UDP packet size, for the LLUDP protocol</summary>
93 public const int MTU = 1400;
94
92 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 95 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
93 96
94 /// <summary>Handlers for incoming packets</summary> 97 /// <summary>Handlers for incoming packets</summary>
@@ -267,38 +270,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP
267 { 270 {
268 int dataLength = data.Length; 271 int dataLength = data.Length;
269 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; 272 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
273 bool doCopy = true;
270 274
271 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. 275 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum.
272 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting 276 // The vast majority of packets are less than 200 bytes, although due to asset transfers and packet splitting
273 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here 277 // there are a decent number of packets in the 1000-1140 byte range. We allocate one of two sizes of data here
274 // to accomodate for both common scenarios and provide ample room for ACK appending in both 278 // to accomodate for both common scenarios and provide ample room for ACK appending in both
275 int bufferSize = (dataLength > 180) ? Packet.MTU : 200; 279 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
276 280
277 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 281 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
278 282
279 // Zerocode if needed 283 // Zerocode if needed
280 if (doZerocode) 284 if (doZerocode)
281 { 285 {
282 try { dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data); } 286 try
287 {
288 dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
289 doCopy = false;
290 }
283 catch (IndexOutOfRangeException) 291 catch (IndexOutOfRangeException)
284 { 292 {
285 // The packet grew larger than the bufferSize while zerocoding. 293 // The packet grew larger than the bufferSize while zerocoding.
286 // Remove the MSG_ZEROCODED flag and send the unencoded data 294 // Remove the MSG_ZEROCODED flag and send the unencoded data
287 // instead 295 // instead
288 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". Removing MSG_ZEROCODED flag"); 296 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
297 " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
289 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); 298 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
290 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
291 } 299 }
292 } 300 }
293 else 301
302 // If the packet data wasn't already copied during zerocoding, copy it now
303 if (doCopy)
294 { 304 {
295 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 305 if (dataLength <= buffer.Data.Length)
306 {
307 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
308 }
309 else
310 {
311 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
312 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
313 return;
314 }
296 } 315 }
316
297 buffer.DataLength = dataLength; 317 buffer.DataLength = dataLength;
298 318
299 #region Queue or Send 319 #region Queue or Send
300 320
301 // Look up the UDPClient this is going to
302 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); 321 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
303 322
304 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 323 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
@@ -513,7 +532,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 IClientAPI client; 532 IClientAPI client;
514 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView)) 533 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView))
515 { 534 {
516 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + 535 m_log.Debug("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address +
517 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients"); 536 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
518 return; 537 return;
519 } 538 }
@@ -568,9 +587,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
568 // client.BytesSinceLastACK. Lockless thread safety 587 // client.BytesSinceLastACK. Lockless thread safety
569 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); 588 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
570 bytesSinceLastACK += buffer.DataLength; 589 bytesSinceLastACK += buffer.DataLength;
571 if (bytesSinceLastACK > Packet.MTU * 2) 590 if (bytesSinceLastACK > LLUDPServer.MTU * 2)
572 { 591 {
573 bytesSinceLastACK -= Packet.MTU * 2; 592 bytesSinceLastACK -= LLUDPServer.MTU * 2;
574 SendAcks(udpClient); 593 SendAcks(udpClient);
575 } 594 }
576 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK); 595 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
index 66a9b5a..cd59bdb 100644
--- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs
@@ -224,11 +224,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat
224 224
225 foreach (Scene s in m_scenes) 225 foreach (Scene s in m_scenes)
226 { 226 {
227 s.ForEachScenePresence(delegate(ScenePresence presence) 227 s.ForEachScenePresence(
228 { 228 delegate(ScenePresence presence)
229 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, 229 {
230 c.Type, message, sourceType); 230 TrySendChatMessage(presence, fromPos, regionPos, fromID, fromName, c.Type, message, sourceType);
231 }); 231 }
232 );
232 } 233 }
233 } 234 }
234 235
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
index 4896edf..3bb162e 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -756,7 +756,7 @@ namespace OpenSim.Region.CoreModules.World.Estate
756 756
757 public void sendRegionHandshakeToAll() 757 public void sendRegionHandshakeToAll()
758 { 758 {
759 m_scene.Broadcast(sendRegionHandshake); 759 m_scene.ForEachClient(sendRegionHandshake);
760 } 760 }
761 761
762 public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2) 762 public void handleEstateChangeInfo(IClientAPI remoteClient, UUID invoice, UUID senderID, UInt32 parms1, UInt32 parms2)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index d2b5cb1..332d3ce 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -1061,7 +1061,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1061 { 1061 {
1062 land.LandData.OwnerID = ownerID; 1062 land.LandData.OwnerID = ownerID;
1063 1063
1064 m_scene.Broadcast(SendParcelOverlay); 1064 m_scene.ForEachClient(SendParcelOverlay);
1065 land.SendLandUpdateToClient(remote_client); 1065 land.SendLandUpdateToClient(remote_client);
1066 } 1066 }
1067 } 1067 }
@@ -1083,7 +1083,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1083 land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 1083 land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
1084 else 1084 else
1085 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; 1085 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1086 m_scene.Broadcast(SendParcelOverlay); 1086 m_scene.ForEachClient(SendParcelOverlay);
1087 land.SendLandUpdateToClient(remote_client); 1087 land.SendLandUpdateToClient(remote_client);
1088 } 1088 }
1089 } 1089 }
@@ -1107,7 +1107,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1107 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; 1107 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1108 land.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 1108 land.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
1109 land.LandData.IsGroupOwned = false; 1109 land.LandData.IsGroupOwned = false;
1110 m_scene.Broadcast(SendParcelOverlay); 1110 m_scene.ForEachClient(SendParcelOverlay);
1111 land.SendLandUpdateToClient(remote_client); 1111 land.SendLandUpdateToClient(remote_client);
1112 } 1112 }
1113 } 1113 }
diff --git a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs
index 6499915..d8c5ed9 100644
--- a/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/RegionCombinerModule.cs
@@ -81,8 +81,12 @@ namespace OpenSim.Region.CoreModules.World.Land
81 81
82 public void RegionLoaded(Scene scene) 82 public void RegionLoaded(Scene scene)
83 { 83 {
84 if (!enabledYN) 84 if (enabledYN)
85 return; 85 RegionLoadedDoWork(scene);
86 }
87
88 private void RegionLoadedDoWork(Scene scene)
89 {
86/* 90/*
87 // For testing on a single instance 91 // For testing on a single instance
88 if (scene.RegionInfo.RegionLocX == 1004 && scene.RegionInfo.RegionLocY == 1000) 92 if (scene.RegionInfo.RegionLocX == 1004 && scene.RegionInfo.RegionLocY == 1000)
diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
index d651fd4..3799a02 100644
--- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
+++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs
@@ -499,13 +499,11 @@ namespace OpenSim.Region.Examples.SimpleModule
499 { 499 {
500 } 500 }
501 501
502 public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, 502 public virtual void SendAvatarData(SendAvatarData data)
503 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
504 { 503 {
505 } 504 }
506 505
507 public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, 506 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
508 Vector3 position, Vector3 velocity, Quaternion rotation, UUID agentid)
509 { 507 {
510 } 508 }
511 509
@@ -521,27 +519,11 @@ namespace OpenSim.Region.Examples.SimpleModule
521 { 519 {
522 } 520 }
523 521
524 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, 522 public virtual void SendPrimitiveToClient(SendPrimitiveData data)
525 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel,
526 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
527 UUID objectID, UUID ownerID, string text, byte[] color,
528 uint parentID,
529 byte[] particleSystem, byte clickAction, byte material)
530 { 523 {
531 } 524 }
532 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, 525
533 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, 526 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
534 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
535 UUID objectID, UUID ownerID, string text, byte[] color,
536 uint parentID,
537 byte[] particleSystem, byte clickAction, byte material, byte[] textureanimation,
538 bool attachment, uint AttachmentPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius)
539 {
540 }
541 public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID,
542 Vector3 position, Quaternion rotation, Vector3 velocity,
543 Vector3 rotationalvelocity, byte state, UUID AssetId,
544 UUID ownerID, int attachPoint)
545 { 527 {
546 } 528 }
547 529
diff --git a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs b/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
index 8e3f4a0..7251d57 100644
--- a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
@@ -34,7 +34,6 @@ namespace OpenSim.Region.Framework.Interfaces
34 { 34 {
35 void Reset(); 35 void Reset();
36 void Close(); 36 void Close();
37 int MaxPrimsPerFrame { get; set; }
38 void QueuePartForUpdate(SceneObjectPart part); 37 void QueuePartForUpdate(SceneObjectPart part);
39 void SendPrimUpdates(); 38 void SendPrimUpdates();
40 } 39 }
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 29d2a84..49c1ebf 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -57,6 +57,12 @@ namespace OpenSim.Region.Framework.Scenes
57 57
58 public partial class Scene : SceneBase 58 public partial class Scene : SceneBase
59 { 59 {
60 public enum UpdatePrioritizationSchemes {
61 Time = 0,
62 Distance = 1,
63 SimpleAngularDistance = 2,
64 }
65
60 public delegate void SynchronizeSceneHandler(Scene scene); 66 public delegate void SynchronizeSceneHandler(Scene scene);
61 public SynchronizeSceneHandler SynchronizeScene = null; 67 public SynchronizeSceneHandler SynchronizeScene = null;
62 68
@@ -269,9 +275,10 @@ namespace OpenSim.Region.Framework.Scenes
269 private volatile bool shuttingdown = false; 275 private volatile bool shuttingdown = false;
270 276
271 private int m_lastUpdate = Environment.TickCount; 277 private int m_lastUpdate = Environment.TickCount;
272 private int m_maxPrimsPerFrame = 200;
273 private bool m_firstHeartbeat = true; 278 private bool m_firstHeartbeat = true;
274 279
280 private UpdatePrioritizationSchemes m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
281
275 private object m_deleting_scene_object = new object(); 282 private object m_deleting_scene_object = new object();
276 283
277 // the minimum time that must elapse before a changed object will be considered for persisted 284 // the minimum time that must elapse before a changed object will be considered for persisted
@@ -283,6 +290,8 @@ namespace OpenSim.Region.Framework.Scenes
283 290
284 #region Properties 291 #region Properties
285 292
293 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return this.m_update_prioritization_scheme; } }
294
286 public AgentCircuitManager AuthenticateHandler 295 public AgentCircuitManager AuthenticateHandler
287 { 296 {
288 get { return m_authenticateHandler; } 297 get { return m_authenticateHandler; }
@@ -327,12 +336,6 @@ namespace OpenSim.Region.Framework.Scenes
327 get { return m_sceneGraph.m_syncRoot; } 336 get { return m_sceneGraph.m_syncRoot; }
328 } 337 }
329 338
330 public int MaxPrimsPerFrame
331 {
332 get { return m_maxPrimsPerFrame; }
333 set { m_maxPrimsPerFrame = value; }
334 }
335
336 /// <summary> 339 /// <summary>
337 /// This is for llGetRegionFPS 340 /// This is for llGetRegionFPS
338 /// </summary> 341 /// </summary>
@@ -510,7 +513,6 @@ namespace OpenSim.Region.Framework.Scenes
510 513
511 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "DotNetEngine"); 514 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "DotNetEngine");
512 515
513 m_maxPrimsPerFrame = startupConfig.GetInt("MaxPrimsPerFrame", 200);
514 IConfig packetConfig = m_config.Configs["PacketPool"]; 516 IConfig packetConfig = m_config.Configs["PacketPool"];
515 if (packetConfig != null) 517 if (packetConfig != null)
516 { 518 {
@@ -519,6 +521,30 @@ namespace OpenSim.Region.Framework.Scenes
519 } 521 }
520 522
521 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 523 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
524
525 IConfig interest_management_config = m_config.Configs["InterestManagement"];
526 if (interest_management_config != null)
527 {
528 string update_prioritization_scheme = interest_management_config.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower();
529 switch (update_prioritization_scheme)
530 {
531 case "time":
532 m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
533 break;
534 case "distance":
535 m_update_prioritization_scheme = UpdatePrioritizationSchemes.Distance;
536 break;
537 case "simpleangulardistance":
538 m_update_prioritization_scheme = UpdatePrioritizationSchemes.SimpleAngularDistance;
539 break;
540 default:
541 m_log.Warn("[SCENE]: UpdatePrioritizationScheme was not recognized, setting to default settomg of Time");
542 m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
543 break;
544 }
545 }
546
547 m_log.Info("[SCENE]: Using the " + m_update_prioritization_scheme + " prioritization scheme");
522 } 548 }
523 catch 549 catch
524 { 550 {
@@ -1200,15 +1226,6 @@ namespace OpenSim.Region.Framework.Scenes
1200 } 1226 }
1201 1227
1202 /// <summary> 1228 /// <summary>
1203 /// Perform delegate action on all clients subscribing to updates from this region.
1204 /// </summary>
1205 /// <returns></returns>
1206 public void Broadcast(Action<IClientAPI> whatToDo)
1207 {
1208 ForEachScenePresence(delegate(ScenePresence presence) { whatToDo(presence.ControllingClient); });
1209 }
1210
1211 /// <summary>
1212 /// Backup the scene. This acts as the main method of the backup thread. 1229 /// Backup the scene. This acts as the main method of the backup thread.
1213 /// </summary> 1230 /// </summary>
1214 /// <returns></returns> 1231 /// <returns></returns>
@@ -3054,17 +3071,13 @@ namespace OpenSim.Region.Framework.Scenes
3054 } 3071 }
3055 3072
3056 m_eventManager.TriggerOnRemovePresence(agentID); 3073 m_eventManager.TriggerOnRemovePresence(agentID);
3057 Broadcast(delegate(IClientAPI client) 3074 ForEachClient(
3058 { 3075 delegate(IClientAPI client)
3059 try 3076 {
3060 { 3077 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3061 client.SendKillObject(avatar.RegionHandle, avatar.LocalId); 3078 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); }
3062 } 3079 catch (NullReferenceException) { }
3063 catch (NullReferenceException) 3080 });
3064 {
3065 //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway.
3066 }
3067 });
3068 3081
3069 ForEachScenePresence( 3082 ForEachScenePresence(
3070 delegate(ScenePresence presence) { presence.CoarseLocationChange(); }); 3083 delegate(ScenePresence presence) { presence.CoarseLocationChange(); });
@@ -3149,7 +3162,7 @@ namespace OpenSim.Region.Framework.Scenes
3149 return; 3162 return;
3150 } 3163 }
3151 } 3164 }
3152 Broadcast(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3165 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
3153 } 3166 }
3154 3167
3155 #endregion 3168 #endregion
@@ -4222,7 +4235,7 @@ namespace OpenSim.Region.Framework.Scenes
4222 4235
4223 public void ForEachClient(Action<IClientAPI> action) 4236 public void ForEachClient(Action<IClientAPI> action)
4224 { 4237 {
4225 m_sceneGraph.ForEachClient(action); 4238 ClientManager.ForEach(action);
4226 } 4239 }
4227 4240
4228 public void ForEachSOG(Action<SceneObjectGroup> action) 4241 public void ForEachSOG(Action<SceneObjectGroup> action)
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 9cd2247..b9872ca 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -613,7 +613,6 @@ namespace OpenSim.Region.Framework.Scenes
613 613
614 newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance); 614 newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance);
615 newAvatar.IsChildAgent = true; 615 newAvatar.IsChildAgent = true;
616 newAvatar.MaxPrimsPerFrame = m_parentScene.MaxPrimsPerFrame;
617 616
618 AddScenePresence(newAvatar); 617 AddScenePresence(newAvatar);
619 618
@@ -1107,23 +1106,6 @@ namespace OpenSim.Region.Framework.Scenes
1107 return UUID.Zero; 1106 return UUID.Zero;
1108 } 1107 }
1109 1108
1110 protected internal void ForEachClient(Action<IClientAPI> action)
1111 {
1112 List<ScenePresence> splist = GetScenePresences();
1113 foreach (ScenePresence presence in splist)
1114 {
1115 try
1116 {
1117 action(presence.ControllingClient);
1118 }
1119 catch (Exception e)
1120 {
1121 // Catch it and move on. This includes situations where splist has inconsistent info
1122 m_log.WarnFormat("[SCENE]: Problem processing action in ForEachClient: ", e.Message);
1123 }
1124 }
1125 }
1126
1127 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1109 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1128 { 1110 {
1129 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1111 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
index d4cef7d..2153b9b 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -1817,7 +1817,7 @@ namespace OpenSim.Region.Framework.Scenes
1817 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags) 1817 public void ServiceObjectPropertiesFamilyRequest(IClientAPI remoteClient, UUID AgentID, uint RequestFlags)
1818 { 1818 {
1819 1819
1820 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.ObjectOwner, RootPart.GroupID, RootPart.BaseMask, 1820 remoteClient.SendObjectPropertiesFamilyData(RequestFlags, RootPart.UUID, RootPart.OwnerID, RootPart.GroupID, RootPart.BaseMask,
1821 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask, 1821 RootPart.OwnerMask, RootPart.GroupMask, RootPart.EveryoneMask, RootPart.NextOwnerMask,
1822 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category, 1822 RootPart.OwnershipCost, RootPart.ObjectSaleType, RootPart.SalePrice, RootPart.Category,
1823 RootPart.CreatorID, RootPart.Name, RootPart.Description); 1823 RootPart.CreatorID, RootPart.Name, RootPart.Description);
@@ -3343,5 +3343,77 @@ namespace OpenSim.Region.Framework.Scenes
3343 3343
3344 return true; 3344 return true;
3345 } 3345 }
3346
3347 public double GetUpdatePriority(IClientAPI client)
3348 {
3349 switch (Scene.UpdatePrioritizationScheme)
3350 {
3351 case Scene.UpdatePrioritizationSchemes.Time:
3352 return GetPriorityByTime();
3353 case Scene.UpdatePrioritizationSchemes.Distance:
3354 return GetPriorityByDistance(client);
3355 case Scene.UpdatePrioritizationSchemes.SimpleAngularDistance:
3356 return GetPriorityBySimpleAngularDistance(client);
3357 default:
3358 throw new InvalidOperationException("UpdatePrioritizationScheme not defined");
3359 }
3360 }
3361
3362 private double GetPriorityByTime()
3363 {
3364 return DateTime.Now.ToOADate();
3365 }
3366
3367 private double GetPriorityByDistance(IClientAPI client)
3368 {
3369 ScenePresence presence = Scene.GetScenePresence(client.AgentId);
3370 if (presence != null)
3371 {
3372 return GetPriorityByDistance((presence.IsChildAgent) ?
3373 presence.AbsolutePosition : presence.CameraPosition);
3374 }
3375 return double.NaN;
3376 }
3377
3378 private double GetPriorityBySimpleAngularDistance(IClientAPI client)
3379 {
3380 ScenePresence presence = Scene.GetScenePresence(client.AgentId);
3381 if (presence != null)
3382 {
3383 return GetPriorityBySimpleAngularDistance((presence.IsChildAgent) ?
3384 presence.AbsolutePosition : presence.CameraPosition);
3385 }
3386 return double.NaN;
3387 }
3388
3389 public double GetPriorityByDistance(Vector3 position)
3390 {
3391 return Vector3.Distance(AbsolutePosition, position);
3392 }
3393
3394 public double GetPriorityBySimpleAngularDistance(Vector3 position)
3395 {
3396 double distance = Vector3.Distance(position, AbsolutePosition);
3397 if (distance >= double.Epsilon)
3398 {
3399 float height;
3400 Vector3 box = GetAxisAlignedBoundingBox(out height);
3401
3402 double angle = box.X / distance;
3403 double max = angle;
3404
3405 angle = box.Y / distance;
3406 if (max < angle)
3407 max = angle;
3408
3409 angle = box.Z / distance;
3410 if (max < angle)
3411 max = angle;
3412
3413 return -max;
3414 }
3415 else
3416 return double.MinValue;
3417 }
3346 } 3418 }
3347} 3419}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 801a7db..79f6366 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -853,16 +853,6 @@ if (m_shape != null) {
853 return m_offsetPosition + m_groupPosition; } 853 return m_offsetPosition + m_groupPosition; }
854 } 854 }
855 855
856 public UUID ObjectCreator
857 {
858 get { return _creatorID; }
859 }
860
861 public UUID ObjectOwner
862 {
863 get { return _ownerID; }
864 }
865
866 public SceneObjectGroup ParentGroup 856 public SceneObjectGroup ParentGroup
867 { 857 {
868 get { return m_parentGroup; } 858 get { return m_parentGroup; }
@@ -1440,7 +1430,7 @@ if (m_shape != null) {
1440 // Move afterwards ResetIDs as it clears the localID 1430 // Move afterwards ResetIDs as it clears the localID
1441 dupe.LocalId = localID; 1431 dupe.LocalId = localID;
1442 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. 1432 // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated.
1443 dupe._lastOwnerID = ObjectOwner; 1433 dupe._lastOwnerID = OwnerID;
1444 1434
1445 byte[] extraP = new byte[Shape.ExtraParams.Length]; 1435 byte[] extraP = new byte[Shape.ExtraParams.Length];
1446 Array.Copy(Shape.ExtraParams, extraP, extraP.Length); 1436 Array.Copy(Shape.ExtraParams, extraP, extraP.Length);
@@ -2410,10 +2400,10 @@ if (m_shape != null) {
2410 //isattachment = ParentGroup.RootPart.IsAttachment; 2400 //isattachment = ParentGroup.RootPart.IsAttachment;
2411 2401
2412 byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A}; 2402 byte[] color = new byte[] {m_color.R, m_color.G, m_color.B, m_color.A};
2413 remoteClient.SendPrimitiveToClient(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape, 2403 remoteClient.SendPrimitiveToClient(new SendPrimitiveData(m_regionHandle, (ushort)(m_parentGroup.GetTimeDilation() * (float)ushort.MaxValue), LocalId, m_shape,
2414 lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, _ownerID, 2404 lPos, Velocity, Acceleration, RotationOffset, RotationalVelocity, clientFlags, m_uuid, _ownerID,
2415 m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment, 2405 m_text, color, _parentID, m_particleSystem, m_clickAction, (byte)m_material, m_TextureAnimation, IsAttachment,
2416 AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius); 2406 AttachmentPoint,FromItemID, Sound, SoundGain, SoundFlags, SoundRadius, ParentGroup.GetUpdatePriority(remoteClient)));
2417 } 2407 }
2418 2408
2419 /// <summary> 2409 /// <summary>
@@ -3804,12 +3794,12 @@ if (m_shape != null) {
3804 3794
3805 // Causes this thread to dig into the Client Thread Data. 3795 // Causes this thread to dig into the Client Thread Data.
3806 // Remember your locking here! 3796 // Remember your locking here!
3807 remoteClient.SendPrimTerseUpdate(m_regionHandle, 3797 remoteClient.SendPrimTerseUpdate(new SendPrimitiveTerseData(m_regionHandle,
3808 (ushort)(m_parentGroup.GetTimeDilation() * 3798 (ushort)(m_parentGroup.GetTimeDilation() *
3809 (float)ushort.MaxValue), LocalId, lPos, 3799 (float)ushort.MaxValue), LocalId, lPos,
3810 RotationOffset, Velocity, 3800 RotationOffset, Velocity,
3811 RotationalVelocity, state, FromItemID, 3801 RotationalVelocity, state, FromItemID,
3812 OwnerID, (int)AttachmentPoint); 3802 OwnerID, (int)AttachmentPoint, ParentGroup.GetUpdatePriority(remoteClient)));
3813 } 3803 }
3814 3804
3815 public void AddScriptLPS(int count) 3805 public void AddScriptLPS(int count)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index c25fa55..9d13ad4 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -403,12 +403,6 @@ namespace OpenSim.Region.Framework.Scenes
403 set { m_parentPosition = value; } 403 set { m_parentPosition = value; }
404 } 404 }
405 405
406 public int MaxPrimsPerFrame
407 {
408 get { return m_sceneViewer.MaxPrimsPerFrame; }
409 set { m_sceneViewer.MaxPrimsPerFrame = value; }
410 }
411
412 /// <summary> 406 /// <summary>
413 /// Absolute position of this avatar in 'region cordinates' 407 /// Absolute position of this avatar in 'region cordinates'
414 /// </summary> 408 /// </summary>
@@ -2456,11 +2450,10 @@ namespace OpenSim.Region.Framework.Scenes
2456 m_perfMonMS = Environment.TickCount; 2450 m_perfMonMS = Environment.TickCount;
2457 2451
2458 Vector3 pos = m_pos; 2452 Vector3 pos = m_pos;
2459 Vector3 vel = Velocity;
2460 Quaternion rot = m_bodyRot;
2461 pos.Z -= m_appearance.HipOffset; 2453 pos.Z -= m_appearance.HipOffset;
2462 remoteClient.SendAvatarTerseUpdate(m_regionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, new Vector3(pos.X, pos.Y, pos.Z), 2454
2463 new Vector3(vel.X, vel.Y, vel.Z), rot, m_uuid); 2455 remoteClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_regionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
2456 pos, m_velocity, m_rotation, m_uuid, GetUpdatePriority(remoteClient)));
2464 2457
2465 m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS); 2458 m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
2466 m_scene.StatsReporter.AddAgentUpdates(1); 2459 m_scene.StatsReporter.AddAgentUpdates(1);
@@ -2474,7 +2467,7 @@ namespace OpenSim.Region.Framework.Scenes
2474 { 2467 {
2475 m_perfMonMS = Environment.TickCount; 2468 m_perfMonMS = Environment.TickCount;
2476 2469
2477 m_scene.Broadcast(SendTerseUpdateToClient); 2470 m_scene.ForEachClient(SendTerseUpdateToClient);
2478 2471
2479 m_lastVelocity = m_velocity; 2472 m_lastVelocity = m_velocity;
2480 lastPhysPos = AbsolutePosition; 2473 lastPhysPos = AbsolutePosition;
@@ -2566,9 +2559,9 @@ namespace OpenSim.Region.Framework.Scenes
2566 Vector3 pos = m_pos; 2559 Vector3 pos = m_pos;
2567 pos.Z -= m_appearance.HipOffset; 2560 pos.Z -= m_appearance.HipOffset;
2568 2561
2569 remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, 2562 remoteAvatar.m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid,
2570 LocalId, m_pos, m_appearance.Texture.GetBytes(), 2563 LocalId, m_pos, m_appearance.Texture.GetBytes(),
2571 m_parentID, rot); 2564 m_parentID, rot));
2572 m_scene.StatsReporter.AddAgentUpdates(1); 2565 m_scene.StatsReporter.AddAgentUpdates(1);
2573 } 2566 }
2574 2567
@@ -2637,8 +2630,8 @@ namespace OpenSim.Region.Framework.Scenes
2637 Vector3 pos = m_pos; 2630 Vector3 pos = m_pos;
2638 pos.Z -= m_appearance.HipOffset; 2631 pos.Z -= m_appearance.HipOffset;
2639 2632
2640 m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2633 m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
2641 m_pos, m_appearance.Texture.GetBytes(), m_parentID, rot); 2634 m_pos, m_appearance.Texture.GetBytes(), m_parentID, rot));
2642 2635
2643 if (!m_isChildAgent) 2636 if (!m_isChildAgent)
2644 { 2637 {
@@ -2744,8 +2737,8 @@ namespace OpenSim.Region.Framework.Scenes
2744 } 2737 }
2745 2738
2746 Quaternion rot = m_bodyRot; 2739 Quaternion rot = m_bodyRot;
2747 m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2740 m_controllingClient.SendAvatarData(new SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId,
2748 m_pos, m_appearance.Texture.GetBytes(), m_parentID, rot); 2741 m_pos, m_appearance.Texture.GetBytes(), m_parentID, rot));
2749 2742
2750 } 2743 }
2751 2744
@@ -2776,7 +2769,7 @@ namespace OpenSim.Region.Framework.Scenes
2776 if (m_isChildAgent) 2769 if (m_isChildAgent)
2777 return; 2770 return;
2778 2771
2779 m_scene.Broadcast( 2772 m_scene.ForEachClient(
2780 delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId, objectIDs); }); 2773 delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId, objectIDs); });
2781 } 2774 }
2782 2775
@@ -3884,5 +3877,41 @@ namespace OpenSim.Region.Framework.Scenes
3884 } 3877 }
3885 } 3878 }
3886 } 3879 }
3880
3881 public double GetUpdatePriority(IClientAPI client)
3882 {
3883 switch (Scene.UpdatePrioritizationScheme)
3884 {
3885 case Scene.UpdatePrioritizationSchemes.Time:
3886 return GetPriorityByTime();
3887 case Scene.UpdatePrioritizationSchemes.Distance:
3888 return GetPriorityByDistance(client);
3889 case Scene.UpdatePrioritizationSchemes.SimpleAngularDistance:
3890 return GetPriorityByDistance(client);
3891 default:
3892 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
3893 }
3894 }
3895
3896 private double GetPriorityByTime()
3897 {
3898 return DateTime.Now.ToOADate();
3899 }
3900
3901 private double GetPriorityByDistance(IClientAPI client)
3902 {
3903 ScenePresence presence = Scene.GetScenePresence(client.AgentId);
3904 if (presence != null)
3905 {
3906 return GetPriorityByDistance((presence.IsChildAgent) ?
3907 presence.AbsolutePosition : presence.CameraPosition);
3908 }
3909 return double.NaN;
3910 }
3911
3912 private double GetPriorityByDistance(Vector3 position)
3913 {
3914 return Vector3.Distance(AbsolutePosition, position);
3915 }
3887 } 3916 }
3888} 3917}
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index 8ab0552..e4296ef 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -45,14 +45,6 @@ namespace OpenSim.Region.Framework.Scenes
45 45
46 protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>(); 46 protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
47 47
48 protected int m_maxPrimsPerFrame = 200;
49
50 public int MaxPrimsPerFrame
51 {
52 get { return m_maxPrimsPerFrame; }
53 set { m_maxPrimsPerFrame = value; }
54 }
55
56 public SceneViewer() 48 public SceneViewer()
57 { 49 {
58 } 50 }
@@ -82,16 +74,7 @@ namespace OpenSim.Region.Framework.Scenes
82 { 74 {
83 m_pendingObjects = new Queue<SceneObjectGroup>(); 75 m_pendingObjects = new Queue<SceneObjectGroup>();
84 76
85 List<EntityBase> ents = new List<EntityBase>(m_presence.Scene.Entities); 77 foreach (EntityBase e in m_presence.Scene.Entities)
86 if (!m_presence.IsChildAgent) // Proximity sort makes no sense for
87 { // Child agents
88 ents.Sort(delegate(EntityBase a, EntityBase b)
89 {
90 return Vector3.Distance(m_presence.AbsolutePosition, a.AbsolutePosition).CompareTo(Vector3.Distance(m_presence.AbsolutePosition, b.AbsolutePosition));
91 });
92 }
93
94 foreach (EntityBase e in ents)
95 { 78 {
96 if (e is SceneObjectGroup) 79 if (e is SceneObjectGroup)
97 m_pendingObjects.Enqueue((SceneObjectGroup)e); 80 m_pendingObjects.Enqueue((SceneObjectGroup)e);
@@ -99,7 +82,7 @@ namespace OpenSim.Region.Framework.Scenes
99 } 82 }
100 } 83 }
101 84
102 while (m_pendingObjects != null && m_pendingObjects.Count > 0 && m_partsUpdateQueue.Count < m_maxPrimsPerFrame) 85 while (m_pendingObjects != null && m_pendingObjects.Count > 0)
103 { 86 {
104 SceneObjectGroup g = m_pendingObjects.Dequeue(); 87 SceneObjectGroup g = m_pendingObjects.Dequeue();
105 88
@@ -183,8 +166,6 @@ namespace OpenSim.Region.Framework.Scenes
183 m_presence.GenerateClientFlags(part.UUID)); 166 m_presence.GenerateClientFlags(part.UUID));
184 } 167 }
185 } 168 }
186
187 m_presence.ControllingClient.FlushPrimUpdates();
188 } 169 }
189 170
190 public void Reset() 171 public void Reset()
diff --git a/OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs b/OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs
index 29c4672..f3be028 100644
--- a/OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs
+++ b/OpenSim/Region/Framework/Scenes/Scripting/IScriptHost.cs
@@ -35,8 +35,8 @@ namespace OpenSim.Region.Framework.Scenes.Scripting
35 string Description { get; set; } 35 string Description { get; set; }
36 36
37 UUID UUID { get; } 37 UUID UUID { get; }
38 UUID ObjectOwner { get; } 38 UUID OwnerID { get; }
39 UUID ObjectCreator { get; } 39 UUID CreatorID { get; }
40 Vector3 AbsolutePosition { get; } 40 Vector3 AbsolutePosition { get; }
41 41
42 string SitName { get; set; } 42 string SitName { get; set; }
diff --git a/OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs b/OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs
index af18a98..d7198f0 100644
--- a/OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs
+++ b/OpenSim/Region/Framework/Scenes/Scripting/NullScriptHost.cs
@@ -68,12 +68,12 @@ namespace OpenSim.Region.Framework.Scenes.Scripting
68 get { return UUID.Zero; } 68 get { return UUID.Zero; }
69 } 69 }
70 70
71 public UUID ObjectOwner 71 public UUID OwnerID
72 { 72 {
73 get { return UUID.Zero; } 73 get { return UUID.Zero; }
74 } 74 }
75 75
76 public UUID ObjectCreator 76 public UUID CreatorID
77 { 77 {
78 get { return UUID.Zero; } 78 get { return UUID.Zero; }
79 } 79 }
diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
index a8acf0d..8ad9327 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1011,12 +1011,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1011 1011
1012 } 1012 }
1013 1013
1014 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) 1014 public void SendAvatarData(SendAvatarData data)
1015 { 1015 {
1016 1016
1017 } 1017 }
1018 1018
1019 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity, Quaternion rotation, UUID agentid) 1019 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
1020 { 1020 {
1021 1021
1022 } 1022 }
@@ -1036,17 +1036,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1036 1036
1037 } 1037 }
1038 1038
1039 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius) 1039 public void SendPrimitiveToClient(SendPrimitiveData data)
1040 { 1040 {
1041 1041
1042 } 1042 }
1043 1043
1044 public void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags, UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem, byte clickAction, byte material) 1044 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
1045 {
1046
1047 }
1048
1049 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID owner, int attachPoint)
1050 { 1045 {
1051 1046
1052 } 1047 }
diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs
index 0379180..e185351 100644
--- a/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs
+++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/SceneObjectGroupDiff.cs
@@ -188,7 +188,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement
188 // MISC COMPARISONS (UUID, Byte) 188 // MISC COMPARISONS (UUID, Byte)
189 if (first.ClickAction != second.ClickAction) 189 if (first.ClickAction != second.ClickAction)
190 result |= Diff.CLICKACTION; 190 result |= Diff.CLICKACTION;
191 if (first.ObjectOwner != second.ObjectOwner) 191 if (first.OwnerID != second.OwnerID)
192 result |= Diff.OBJECTOWNER; 192 result |= Diff.OBJECTOWNER;
193 193
194 194
diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
index ce50f9e..4521f8e 100644
--- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/MRMModule.cs
@@ -259,7 +259,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
259 if (e.InnerException != null) 259 if (e.InnerException != null)
260 m_log.Error("[MRM] " + e.InnerException); 260 m_log.Error("[MRM] " + e.InnerException);
261 261
262 m_scene.Broadcast(delegate(IClientAPI user) 262 m_scene.ForEachClient(delegate(IClientAPI user)
263 { 263 {
264 user.SendAlertMessage( 264 user.SendAlertMessage(
265 "MRM UnAuthorizedAccess: " + e); 265 "MRM UnAuthorizedAccess: " + e);
@@ -268,7 +268,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule
268 catch (Exception e) 268 catch (Exception e)
269 { 269 {
270 m_log.Info("[MRM] Error: " + e); 270 m_log.Info("[MRM] Error: " + e);
271 m_scene.Broadcast(delegate(IClientAPI user) 271 m_scene.ForEachClient(delegate(IClientAPI user)
272 { 272 {
273 user.SendAlertMessage( 273 user.SendAlertMessage(
274 "Compile error while building MRM script, check OpenSim console for more information."); 274 "Compile error while building MRM script, check OpenSim console for more information.");
diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
index f7c63ac..6c58f2d 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs
@@ -588,13 +588,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
588 { 588 {
589 } 589 }
590 590
591 public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, 591 public virtual void SendAvatarData(SendAvatarData data)
592 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
593 { 592 {
594 } 593 }
595 594
596 public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, 595 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
597 Vector3 position, Vector3 velocity, Quaternion rotation, UUID agentId)
598 { 596 {
599 } 597 }
600 598
@@ -610,26 +608,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC
610 { 608 {
611 } 609 }
612 610
613 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, 611 public virtual void SendPrimitiveToClient(SendPrimitiveData data)
614 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel,
615 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
616 UUID objectID, UUID ownerID, string text, byte[] color,
617 uint parentID,
618 byte[] particleSystem, byte clickAction, byte material)
619 { 612 {
620 } 613 }
621 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, 614
622 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, 615 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
623 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
624 UUID objectID, UUID ownerID, string text, byte[] color,
625 uint parentID,
626 byte[] particleSystem, byte clickAction, byte material, byte[] textureanimation,
627 bool attachment, uint AttachmentPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius)
628 {
629 }
630 public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID,
631 Vector3 position, Quaternion rotation, Vector3 velocity,
632 Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint)
633 { 616 {
634 } 617 }
635 618
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index e10e612..57b14f7 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -2875,7 +2875,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
2875 { 2875 {
2876 m_host.AddScriptLPS(1); 2876 m_host.AddScriptLPS(1);
2877 2877
2878 return m_host.ObjectOwner.ToString(); 2878 return m_host.OwnerID.ToString();
2879 } 2879 }
2880 2880
2881 public void llInstantMessage(string user, string message) 2881 public void llInstantMessage(string user, string message)
@@ -5634,7 +5634,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
5634 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y); 5634 ILandObject parcel = World.LandChannel.GetLandObject(av.AbsolutePosition.X, av.AbsolutePosition.Y);
5635 if (parcel != null) 5635 if (parcel != null)
5636 { 5636 {
5637 if (m_host.ObjectOwner == parcel.LandData.OwnerID || 5637 if (m_host.OwnerID == parcel.LandData.OwnerID ||
5638 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID 5638 (m_host.OwnerID == m_host.GroupID && m_host.GroupID == parcel.LandData.GroupID
5639 && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID)) 5639 && parcel.LandData.IsGroupOwned) || World.Permissions.IsGod(m_host.OwnerID))
5640 { 5640 {
@@ -7157,7 +7157,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7157 7157
7158 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 7158 ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
7159 7159
7160 if (land.LandData.OwnerID != m_host.ObjectOwner) 7160 if (land.LandData.OwnerID != m_host.OwnerID)
7161 return; 7161 return;
7162 7162
7163 land.SetMusicUrl(url); 7163 land.SetMusicUrl(url);
@@ -7215,7 +7215,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7215 public LSL_String llGetCreator() 7215 public LSL_String llGetCreator()
7216 { 7216 {
7217 m_host.AddScriptLPS(1); 7217 m_host.AddScriptLPS(1);
7218 return m_host.ObjectCreator.ToString(); 7218 return m_host.CreatorID.ToString();
7219 } 7219 }
7220 7220
7221 public LSL_String llGetTimestamp() 7221 public LSL_String llGetTimestamp()
@@ -8396,7 +8396,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8396 IDialogModule dm = World.RequestModuleInterface<IDialogModule>(); 8396 IDialogModule dm = World.RequestModuleInterface<IDialogModule>();
8397 if (null != dm) 8397 if (null != dm)
8398 dm.SendUrlToUser( 8398 dm.SendUrlToUser(
8399 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.ObjectOwner, false, message, url); 8399 new UUID(avatar_id), m_host.Name, m_host.UUID, m_host.OwnerID, false, message, url);
8400 8400
8401 ConditionalScriptSleep(10000); 8401 ConditionalScriptSleep(10000);
8402 } 8402 }
@@ -8411,7 +8411,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8411 // according to the docs, this command only works if script owner and land owner are the same 8411 // according to the docs, this command only works if script owner and land owner are the same
8412 // lets add estate owners and gods, too, and use the generic permission check. 8412 // lets add estate owners and gods, too, and use the generic permission check.
8413 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 8413 ILandObject landObject = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
8414 if (!World.Permissions.CanEditParcel(m_host.ObjectOwner, landObject)) return; 8414 if (!World.Permissions.CanEditParcel(m_host.OwnerID, landObject)) return;
8415 8415
8416 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)? 8416 bool update = false; // send a ParcelMediaUpdate (and possibly change the land's media URL)?
8417 byte loop = 0; 8417 byte loop = 0;
@@ -9081,9 +9081,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9081 Vector3 velocity = m_host.Velocity; 9081 Vector3 velocity = m_host.Velocity;
9082 Quaternion rotation = m_host.RotationOffset; 9082 Quaternion rotation = m_host.RotationOffset;
9083 string ownerName = String.Empty; 9083 string ownerName = String.Empty;
9084 ScenePresence scenePresence = World.GetScenePresence(m_host.ObjectOwner); 9084 ScenePresence scenePresence = World.GetScenePresence(m_host.OwnerID);
9085 if (scenePresence == null) 9085 if (scenePresence == null)
9086 ownerName = resolveName(m_host.ObjectOwner); 9086 ownerName = resolveName(m_host.OwnerID);
9087 else 9087 else
9088 ownerName = scenePresence.Name; 9088 ownerName = scenePresence.Name;
9089 9089
@@ -9108,7 +9108,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
9108 httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z); 9108 httpHeaders["X-SecondLife-Local-Velocity"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000})", velocity.X, velocity.Y, velocity.Z);
9109 httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W); 9109 httpHeaders["X-SecondLife-Local-Rotation"] = string.Format("({0:0.000000}, {1:0.000000}, {2:0.000000}, {3:0.000000})", rotation.X, rotation.Y, rotation.Z, rotation.W);
9110 httpHeaders["X-SecondLife-Owner-Name"] = ownerName; 9110 httpHeaders["X-SecondLife-Owner-Name"] = ownerName;
9111 httpHeaders["X-SecondLife-Owner-Key"] = m_host.ObjectOwner.ToString(); 9111 httpHeaders["X-SecondLife-Owner-Key"] = m_host.OwnerID.ToString();
9112 string userAgent = config.Configs["Network"].GetString("user_agent", null); 9112 string userAgent = config.Configs["Network"].GetString("user_agent", null);
9113 if (userAgent != null) 9113 if (userAgent != null)
9114 httpHeaders["User-Agent"] = userAgent; 9114 httpHeaders["User-Agent"] = userAgent;
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 4cb4b61..52396b6 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -1164,7 +1164,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1164 ILandObject land 1164 ILandObject land
1165 = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 1165 = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
1166 1166
1167 if (land.LandData.OwnerID != m_host.ObjectOwner) 1167 if (land.LandData.OwnerID != m_host.OwnerID)
1168 return; 1168 return;
1169 1169
1170 land.SetMediaUrl(url); 1170 land.SetMediaUrl(url);
@@ -1182,7 +1182,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
1182 ILandObject land 1182 ILandObject land
1183 = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); 1183 = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y);
1184 1184
1185 if (land.LandData.OwnerID != m_host.ObjectOwner) 1185 if (land.LandData.OwnerID != m_host.OwnerID)
1186 { 1186 {
1187 OSSLError("osSetParcelSIPAddress: Sorry, you need to own the land to use this function"); 1187 OSSLError("osSetParcelSIPAddress: Sorry, you need to own the land to use this function");
1188 return; 1188 return;
diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs
index 5c838c5..21606e2 100644
--- a/OpenSim/Tests/Common/Mock/TestClient.cs
+++ b/OpenSim/Tests/Common/Mock/TestClient.cs
@@ -592,13 +592,11 @@ namespace OpenSim.Tests.Common.Mock
592 { 592 {
593 } 593 }
594 594
595 public virtual void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, 595 public virtual void SendAvatarData(SendAvatarData data)
596 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
597 { 596 {
598 } 597 }
599 598
600 public virtual void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, 599 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
601 Vector3 position, Vector3 velocity, Quaternion rotation, UUID agentid)
602 { 600 {
603 } 601 }
604 602
@@ -614,27 +612,11 @@ namespace OpenSim.Tests.Common.Mock
614 { 612 {
615 } 613 }
616 614
617 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, 615 public virtual void SendPrimitiveToClient(SendPrimitiveData data)
618 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel,
619 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
620 UUID objectID, UUID ownerID, string text, byte[] color,
621 uint parentID,
622 byte[] particleSystem, byte clickAction, byte material)
623 { 616 {
624 } 617 }
625 public virtual void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, 618
626 PrimitiveBaseShape primShape, Vector3 pos, Vector3 vel, 619 public virtual void SendPrimTerseUpdate(SendPrimitiveTerseData data)
627 Vector3 acc, Quaternion rotation, Vector3 rvel, uint flags,
628 UUID objectID, UUID ownerID, string text, byte[] color,
629 uint parentID,
630 byte[] particleSystem, byte clickAction, byte material, byte[] textureanimation,
631 bool attachment, uint AttachmentPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags, double SoundRadius)
632 {
633 }
634 public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID,
635 Vector3 position, Quaternion rotation, Vector3 velocity,
636 Vector3 rotationalvelocity, byte state, UUID AssetId,
637 UUID ownerID, int attachPoint)
638 { 620 {
639 } 621 }
640 622