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.cs35
-rw-r--r--OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs10
-rw-r--r--OpenSim/Data/MySQL/MySQLLegacyRegionData.cs288
-rw-r--r--OpenSim/Framework/IClientAPI.cs257
-rwxr-xr-xOpenSim/Framework/MinHeap.cs375
-rw-r--r--OpenSim/Framework/Parallel.cs8
-rw-r--r--OpenSim/Framework/RegionInfo.cs2
-rw-r--r--OpenSim/Framework/Util.cs29
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs1576
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs2
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs92
-rw-r--r--OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs120
-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.cs11
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.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/EntityManager.cs69
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs21
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs125
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs32
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs76
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs197
-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.cs12
-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/Physics/Meshing/Meshmerizer.cs3
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs9
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdePlugin.cs6
-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
40 files changed, 2213 insertions, 1348 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..204603d 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.Position, 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,23 +1028,24 @@ 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,
1034 data.rotation, (uint)data.flags, data.text, data.color, data.parentID, data.particleSystem, data.clickAction,
1035 data.material, data.textureanim);
1034 } 1036 }
1035 1037
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) 1038 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
1037 { 1039 {
1038 MXPSendPrimitive(localID, ownerID, acc, rvel, primShape, pos, objectID, vel, rotation, flags, text, color, parentID, particleSystem, clickAction, material, new byte[0]); 1040 MovementEventMessage me = new MovementEventMessage();
1041 me.ObjectIndex = data.LocalID;
1042 me.Location = ToOmVector(data.Position);
1043 me.Orientation = ToOmQuaternion(data.Rotation);
1044 Session.Send(me);
1039 } 1045 }
1040 1046
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) 1047 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
1042 { 1048 {
1043 MovementEventMessage me = new MovementEventMessage();
1044 me.ObjectIndex = localID;
1045 me.Location = ToOmVector(position);
1046 me.Orientation = ToOmQuaternion(rotation);
1047 Session.Send(me);
1048 } 1049 }
1049 1050
1050 public void FlushPrimUpdates() 1051 public void FlushPrimUpdates()
diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
index bd061e7..4a54c67 100644
--- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
+++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs
@@ -561,12 +561,12 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
561 throw new System.NotImplementedException(); 561 throw new System.NotImplementedException();
562 } 562 }
563 563
564 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) 564 public void SendAvatarData(SendAvatarData data)
565 { 565 {
566 throw new System.NotImplementedException(); 566 throw new System.NotImplementedException();
567 } 567 }
568 568
569 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity, Quaternion rotation, UUID uuid) 569 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
570 { 570 {
571 throw new System.NotImplementedException(); 571 throw new System.NotImplementedException();
572 } 572 }
@@ -586,17 +586,17 @@ namespace OpenSim.Client.VWoHTTP.ClientStack
586 throw new System.NotImplementedException(); 586 throw new System.NotImplementedException();
587 } 587 }
588 588
589 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) 589 public void SendPrimitiveToClient(SendPrimitiveData data)
590 { 590 {
591 throw new System.NotImplementedException(); 591 throw new System.NotImplementedException();
592 } 592 }
593 593
594 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) 594 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
595 { 595 {
596 throw new System.NotImplementedException(); 596 throw new System.NotImplementedException();
597 } 597 }
598 598
599 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 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
600 { 600 {
601 throw new System.NotImplementedException(); 601 throw new System.NotImplementedException();
602 } 602 }
diff --git a/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs b/OpenSim/Data/MySQL/MySQLLegacyRegionData.cs
index fe0914b..801d6b9 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)
@@ -395,25 +403,23 @@ namespace OpenSim.Data.MySQL
395 } 403 }
396 } 404 }
397 405
398 public List<SceneObjectGroup> LoadObjects(UUID regionUUID) 406 public List<SceneObjectGroup> LoadObjects(UUID regionID)
399 { 407 {
400 UUID lastGroupID = UUID.Zero; 408 const int ROWS_PER_QUERY = 5000;
409
410 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(ROWS_PER_QUERY);
401 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>(); 411 Dictionary<UUID, SceneObjectGroup> objects = new Dictionary<UUID, SceneObjectGroup>();
402 Dictionary<UUID, SceneObjectPart> prims = new Dictionary<UUID, SceneObjectPart>(); 412 int count = 0;
403 SceneObjectGroup grp = null; 413
414 #region Prim Loading
404 415
405 lock (m_Connection) 416 lock (m_Connection)
406 { 417 {
407 using (MySqlCommand cmd = m_Connection.CreateCommand()) 418 using (MySqlCommand cmd = m_Connection.CreateCommand())
408 { 419 {
409 cmd.CommandText = "select *, " + 420 cmd.CommandText =
410 "case when prims.UUID = SceneGroupID " + 421 "SELECT * FROM prims LEFT JOIN primshapes ON prims.UUID = primshapes.UUID WHERE RegionUUID = ?RegionUUID";
411 "then 0 else 1 end as sort from prims " + 422 cmd.Parameters.AddWithValue("RegionUUID", regionID.ToString());
412 "left join primshapes on prims.UUID = primshapes.UUID " +
413 "where RegionUUID = ?RegionUUID " +
414 "order by SceneGroupID asc, sort asc, LinkNumber asc";
415
416 cmd.Parameters.AddWithValue("RegionUUID", regionUUID.ToString());
417 423
418 using (IDataReader reader = ExecuteReader(cmd)) 424 using (IDataReader reader = ExecuteReader(cmd))
419 { 425 {
@@ -425,52 +431,61 @@ namespace OpenSim.Data.MySQL
425 else 431 else
426 prim.Shape = BuildShape(reader); 432 prim.Shape = BuildShape(reader);
427 433
428 prims[prim.UUID] = prim; 434 UUID parentID = new UUID(reader["SceneGroupID"].ToString());
435 if (parentID != prim.UUID)
436 prim.ParentUUID = parentID;
429 437
430 UUID groupID = new UUID(reader["SceneGroupID"].ToString()); 438 prims[prim.UUID] = prim;
431 439
432 if (groupID != lastGroupID) // New SOG 440 ++count;
433 { 441 if (count % ROWS_PER_QUERY == 0)
434 if (grp != null) 442 m_log.Debug("[REGION DB]: Loaded " + count + " prims...");
435 objects[grp.UUID] = grp; 443 }
444 }
445 }
446 }
436 447
437 lastGroupID = groupID; 448 #endregion Prim Loading
438 449
439 // There sometimes exist OpenSim bugs that 'orphan groups' so that none of the prims are 450 #region SceneObjectGroup Creation
440 // recorded as the root prim (for which the UUID must equal the persisted group UUID). In
441 // this case, force the UUID to be the same as the group UUID so that at least these can be
442 // deleted (we need to change the UUID so that any other prims in the linkset can also be
443 // deleted).
444 if (prim.UUID != groupID && groupID != UUID.Zero)
445 {
446 m_log.WarnFormat(
447 "[REGION DB]: Found root prim {0} {1} at {2} where group was actually {3}. Forcing UUID to group UUID",
448 prim.Name, prim.UUID, prim.GroupPosition, groupID);
449 451
450 prim.UUID = groupID; 452 // Create all of the SOGs from the root prims first
451 } 453 foreach (SceneObjectPart prim in prims.Values)
454 {
455 if (prim.ParentUUID == UUID.Zero)
456 objects[prim.UUID] = new SceneObjectGroup(prim);
457 }
452 458
453 grp = new SceneObjectGroup(prim); 459 // Add all of the children objects to the SOGs
454 } 460 foreach (SceneObjectPart prim in prims.Values)
455 else 461 {
456 { 462 SceneObjectGroup sog;
457 // Black magic to preserve link numbers 463 if (prim.UUID != prim.ParentUUID)
458 // 464 {
459 int link = prim.LinkNum; 465 if (objects.TryGetValue(prim.ParentUUID, out sog))
466 {
467 int originalLinkNum = prim.LinkNum;
460 468
461 grp.AddPart(prim); 469 sog.AddPart(prim);
462 470
463 if (link != 0) 471 // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum.
464 prim.LinkNum = link; 472 // We override that here
465 } 473 if (originalLinkNum != 0)
466 } 474 prim.LinkNum = originalLinkNum;
475 }
476 else
477 {
478 m_log.Warn("[REGION DB]: Database contains an orphan child prim " + prim.UUID + " pointing to missing parent " + prim.ParentUUID);
467 } 479 }
468
469 if (grp != null)
470 objects[grp.UUID] = grp;
471 } 480 }
472 } 481 }
473 482
483 #endregion SceneObjectGroup Creation
484
485 m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
486
487 #region Prim Inventory Loading
488
474 // Instead of attempting to LoadItems on every prim, 489 // Instead of attempting to LoadItems on every prim,
475 // most of which probably have no items... get a 490 // most of which probably have no items... get a
476 // list from DB of all prims which have items and 491 // list from DB of all prims which have items and
@@ -480,7 +495,7 @@ namespace OpenSim.Data.MySQL
480 { 495 {
481 using (MySqlCommand itemCmd = m_Connection.CreateCommand()) 496 using (MySqlCommand itemCmd = m_Connection.CreateCommand())
482 { 497 {
483 itemCmd.CommandText = "select distinct primID from primitems"; 498 itemCmd.CommandText = "SELECT DISTINCT primID FROM primitems";
484 using (IDataReader itemReader = ExecuteReader(itemCmd)) 499 using (IDataReader itemReader = ExecuteReader(itemCmd))
485 { 500 {
486 while (itemReader.Read()) 501 while (itemReader.Read())
@@ -489,9 +504,7 @@ namespace OpenSim.Data.MySQL
489 { 504 {
490 UUID primID = new UUID(itemReader["primID"].ToString()); 505 UUID primID = new UUID(itemReader["primID"].ToString());
491 if (prims.ContainsKey(primID)) 506 if (prims.ContainsKey(primID))
492 {
493 primsWithInventory.Add(prims[primID]); 507 primsWithInventory.Add(prims[primID]);
494 }
495 } 508 }
496 } 509 }
497 } 510 }
@@ -499,9 +512,14 @@ namespace OpenSim.Data.MySQL
499 } 512 }
500 513
501 foreach (SceneObjectPart prim in primsWithInventory) 514 foreach (SceneObjectPart prim in primsWithInventory)
515 {
502 LoadItems(prim); 516 LoadItems(prim);
517 }
518
519 #endregion Prim Inventory Loading
520
521 m_log.DebugFormat("[REGION DB]: Loaded inventory from {0} objects", primsWithInventory.Count);
503 522
504 m_log.DebugFormat("[REGION DB]: Loaded {0} objects using {1} prims", objects.Count, prims.Count);
505 return new List<SceneObjectGroup>(objects.Values); 523 return new List<SceneObjectGroup>(objects.Values);
506 } 524 }
507 525
@@ -798,137 +816,137 @@ namespace OpenSim.Data.MySQL
798 private SceneObjectPart BuildPrim(IDataReader row) 816 private SceneObjectPart BuildPrim(IDataReader row)
799 { 817 {
800 SceneObjectPart prim = new SceneObjectPart(); 818 SceneObjectPart prim = new SceneObjectPart();
801 prim.UUID = new UUID((String) row["UUID"]); 819 prim.UUID = new UUID((string)row["UUID"]);
802 // explicit conversion of integers is required, which sort 820 // explicit conversion of integers is required, which sort
803 // of sucks. No idea if there is a shortcut here or not. 821 // of sucks. No idea if there is a shortcut here or not.
804 prim.CreationDate = Convert.ToInt32(row["CreationDate"]); 822 prim.CreationDate = (int)row["CreationDate"];
805 if (row["Name"] != DBNull.Value) 823 if (row["Name"] != DBNull.Value)
806 prim.Name = (String)row["Name"]; 824 prim.Name = (string)row["Name"];
807 else 825 else
808 prim.Name = string.Empty; 826 prim.Name = String.Empty;
809 // various text fields 827 // Various text fields
810 prim.Text = (String) row["Text"]; 828 prim.Text = (string)row["Text"];
811 prim.Color = Color.FromArgb(Convert.ToInt32(row["ColorA"]), 829 prim.Color = Color.FromArgb((int)row["ColorA"],
812 Convert.ToInt32(row["ColorR"]), 830 (int)row["ColorR"],
813 Convert.ToInt32(row["ColorG"]), 831 (int)row["ColorG"],
814 Convert.ToInt32(row["ColorB"])); 832 (int)row["ColorB"]);
815 prim.Description = (String) row["Description"]; 833 prim.Description = (string)row["Description"];
816 prim.SitName = (String) row["SitName"]; 834 prim.SitName = (string)row["SitName"];
817 prim.TouchName = (String) row["TouchName"]; 835 prim.TouchName = (string)row["TouchName"];
818 // permissions 836 // Permissions
819 prim.ObjectFlags = Convert.ToUInt32(row["ObjectFlags"]); 837 prim.ObjectFlags = (uint)(int)row["ObjectFlags"];
820 prim.CreatorID = new UUID((String) row["CreatorID"]); 838 prim.CreatorID = new UUID((string)row["CreatorID"]);
821 prim.OwnerID = new UUID((String) row["OwnerID"]); 839 prim.OwnerID = new UUID((string)row["OwnerID"]);
822 prim.GroupID = new UUID((String) row["GroupID"]); 840 prim.GroupID = new UUID((string)row["GroupID"]);
823 prim.LastOwnerID = new UUID((String) row["LastOwnerID"]); 841 prim.LastOwnerID = new UUID((string)row["LastOwnerID"]);
824 prim.OwnerMask = Convert.ToUInt32(row["OwnerMask"]); 842 prim.OwnerMask = (uint)(int)row["OwnerMask"];
825 prim.NextOwnerMask = Convert.ToUInt32(row["NextOwnerMask"]); 843 prim.NextOwnerMask = (uint)(int)row["NextOwnerMask"];
826 prim.GroupMask = Convert.ToUInt32(row["GroupMask"]); 844 prim.GroupMask = (uint)(int)row["GroupMask"];
827 prim.EveryoneMask = Convert.ToUInt32(row["EveryoneMask"]); 845 prim.EveryoneMask = (uint)(int)row["EveryoneMask"];
828 prim.BaseMask = Convert.ToUInt32(row["BaseMask"]); 846 prim.BaseMask = (uint)(int)row["BaseMask"];
829 // vectors 847 // Vectors
830 prim.OffsetPosition = new Vector3( 848 prim.OffsetPosition = new Vector3(
831 Convert.ToSingle(row["PositionX"]), 849 (float)(double)row["PositionX"],
832 Convert.ToSingle(row["PositionY"]), 850 (float)(double)row["PositionY"],
833 Convert.ToSingle(row["PositionZ"]) 851 (float)(double)row["PositionZ"]
834 ); 852 );
835 prim.GroupPosition = new Vector3( 853 prim.GroupPosition = new Vector3(
836 Convert.ToSingle(row["GroupPositionX"]), 854 (float)(double)row["GroupPositionX"],
837 Convert.ToSingle(row["GroupPositionY"]), 855 (float)(double)row["GroupPositionY"],
838 Convert.ToSingle(row["GroupPositionZ"]) 856 (float)(double)row["GroupPositionZ"]
839 ); 857 );
840 prim.Velocity = new Vector3( 858 prim.Velocity = new Vector3(
841 Convert.ToSingle(row["VelocityX"]), 859 (float)(double)row["VelocityX"],
842 Convert.ToSingle(row["VelocityY"]), 860 (float)(double)row["VelocityY"],
843 Convert.ToSingle(row["VelocityZ"]) 861 (float)(double)row["VelocityZ"]
844 ); 862 );
845 prim.AngularVelocity = new Vector3( 863 prim.AngularVelocity = new Vector3(
846 Convert.ToSingle(row["AngularVelocityX"]), 864 (float)(double)row["AngularVelocityX"],
847 Convert.ToSingle(row["AngularVelocityY"]), 865 (float)(double)row["AngularVelocityY"],
848 Convert.ToSingle(row["AngularVelocityZ"]) 866 (float)(double)row["AngularVelocityZ"]
849 ); 867 );
850 prim.Acceleration = new Vector3( 868 prim.Acceleration = new Vector3(
851 Convert.ToSingle(row["AccelerationX"]), 869 (float)(double)row["AccelerationX"],
852 Convert.ToSingle(row["AccelerationY"]), 870 (float)(double)row["AccelerationY"],
853 Convert.ToSingle(row["AccelerationZ"]) 871 (float)(double)row["AccelerationZ"]
854 ); 872 );
855 // quaternions 873 // quaternions
856 prim.RotationOffset = new Quaternion( 874 prim.RotationOffset = new Quaternion(
857 Convert.ToSingle(row["RotationX"]), 875 (float)(double)row["RotationX"],
858 Convert.ToSingle(row["RotationY"]), 876 (float)(double)row["RotationY"],
859 Convert.ToSingle(row["RotationZ"]), 877 (float)(double)row["RotationZ"],
860 Convert.ToSingle(row["RotationW"]) 878 (float)(double)row["RotationW"]
861 ); 879 );
862 prim.SitTargetPositionLL = new Vector3( 880 prim.SitTargetPositionLL = new Vector3(
863 Convert.ToSingle(row["SitTargetOffsetX"]), 881 (float)(double)row["SitTargetOffsetX"],
864 Convert.ToSingle(row["SitTargetOffsetY"]), 882 (float)(double)row["SitTargetOffsetY"],
865 Convert.ToSingle(row["SitTargetOffsetZ"]) 883 (float)(double)row["SitTargetOffsetZ"]
866 ); 884 );
867 prim.SitTargetOrientationLL = new Quaternion( 885 prim.SitTargetOrientationLL = new Quaternion(
868 Convert.ToSingle(row["SitTargetOrientX"]), 886 (float)(double)row["SitTargetOrientX"],
869 Convert.ToSingle(row["SitTargetOrientY"]), 887 (float)(double)row["SitTargetOrientY"],
870 Convert.ToSingle(row["SitTargetOrientZ"]), 888 (float)(double)row["SitTargetOrientZ"],
871 Convert.ToSingle(row["SitTargetOrientW"]) 889 (float)(double)row["SitTargetOrientW"]
872 ); 890 );
873 891
874 prim.PayPrice[0] = Convert.ToInt32(row["PayPrice"]); 892 prim.PayPrice[0] = (int)row["PayPrice"];
875 prim.PayPrice[1] = Convert.ToInt32(row["PayButton1"]); 893 prim.PayPrice[1] = (int)row["PayButton1"];
876 prim.PayPrice[2] = Convert.ToInt32(row["PayButton2"]); 894 prim.PayPrice[2] = (int)row["PayButton2"];
877 prim.PayPrice[3] = Convert.ToInt32(row["PayButton3"]); 895 prim.PayPrice[3] = (int)row["PayButton3"];
878 prim.PayPrice[4] = Convert.ToInt32(row["PayButton4"]); 896 prim.PayPrice[4] = (int)row["PayButton4"];
879 897
880 prim.Sound = new UUID(row["LoopedSound"].ToString()); 898 prim.Sound = new UUID(row["LoopedSound"].ToString());
881 prim.SoundGain = Convert.ToSingle(row["LoopedSoundGain"]); 899 prim.SoundGain = (float)(double)row["LoopedSoundGain"];
882 prim.SoundFlags = 1; // If it's persisted at all, it's looped 900 prim.SoundFlags = 1; // If it's persisted at all, it's looped
883 901
884 if (!(row["TextureAnimation"] is DBNull)) 902 if (!(row["TextureAnimation"] is DBNull))
885 prim.TextureAnimation = (Byte[])row["TextureAnimation"]; 903 prim.TextureAnimation = (byte[])row["TextureAnimation"];
886 if (!(row["ParticleSystem"] is DBNull)) 904 if (!(row["ParticleSystem"] is DBNull))
887 prim.ParticleSystem = (Byte[])row["ParticleSystem"]; 905 prim.ParticleSystem = (byte[])row["ParticleSystem"];
888 906
889 prim.RotationalVelocity = new Vector3( 907 prim.RotationalVelocity = new Vector3(
890 Convert.ToSingle(row["OmegaX"]), 908 (float)(double)row["OmegaX"],
891 Convert.ToSingle(row["OmegaY"]), 909 (float)(double)row["OmegaY"],
892 Convert.ToSingle(row["OmegaZ"]) 910 (float)(double)row["OmegaZ"]
893 ); 911 );
894 912
895 prim.SetCameraEyeOffset(new Vector3( 913 prim.SetCameraEyeOffset(new Vector3(
896 Convert.ToSingle(row["CameraEyeOffsetX"]), 914 (float)(double)row["CameraEyeOffsetX"],
897 Convert.ToSingle(row["CameraEyeOffsetY"]), 915 (float)(double)row["CameraEyeOffsetY"],
898 Convert.ToSingle(row["CameraEyeOffsetZ"]) 916 (float)(double)row["CameraEyeOffsetZ"]
899 )); 917 ));
900 918
901 prim.SetCameraAtOffset(new Vector3( 919 prim.SetCameraAtOffset(new Vector3(
902 Convert.ToSingle(row["CameraAtOffsetX"]), 920 (float)(double)row["CameraAtOffsetX"],
903 Convert.ToSingle(row["CameraAtOffsetY"]), 921 (float)(double)row["CameraAtOffsetY"],
904 Convert.ToSingle(row["CameraAtOffsetZ"]) 922 (float)(double)row["CameraAtOffsetZ"]
905 )); 923 ));
906 924
907 if (Convert.ToInt16(row["ForceMouselook"]) != 0) 925 if ((sbyte)row["ForceMouselook"] != 0)
908 prim.SetForceMouselook(true); 926 prim.SetForceMouselook(true);
909 927
910 prim.ScriptAccessPin = Convert.ToInt32(row["ScriptAccessPin"]); 928 prim.ScriptAccessPin = (int)row["ScriptAccessPin"];
911 929
912 if (Convert.ToInt16(row["AllowedDrop"]) != 0) 930 if ((sbyte)row["AllowedDrop"] != 0)
913 prim.AllowedDrop = true; 931 prim.AllowedDrop = true;
914 932
915 if (Convert.ToInt16(row["DieAtEdge"]) != 0) 933 if ((sbyte)row["DieAtEdge"] != 0)
916 prim.DIE_AT_EDGE = true; 934 prim.DIE_AT_EDGE = true;
917 935
918 prim.SalePrice = Convert.ToInt32(row["SalePrice"]); 936 prim.SalePrice = (int)row["SalePrice"];
919 prim.ObjectSaleType = unchecked((byte)Convert.ToSByte(row["SaleType"])); 937 prim.ObjectSaleType = unchecked((byte)(sbyte)row["SaleType"]);
920 938
921 prim.Material = unchecked((byte)Convert.ToSByte(row["Material"])); 939 prim.Material = unchecked((byte)(sbyte)row["Material"]);
922 940
923 if (!(row["ClickAction"] is DBNull)) 941 if (!(row["ClickAction"] is DBNull))
924 prim.ClickAction = unchecked((byte)Convert.ToSByte(row["ClickAction"])); 942 prim.ClickAction = unchecked((byte)(sbyte)row["ClickAction"]);
925 943
926 prim.CollisionSound = new UUID(row["CollisionSound"].ToString()); 944 prim.CollisionSound = new UUID(row["CollisionSound"].ToString());
927 prim.CollisionSoundVolume = Convert.ToSingle(row["CollisionSoundVolume"]); 945 prim.CollisionSoundVolume = (float)(double)row["CollisionSoundVolume"];
928 946
929 if (Convert.ToInt16(row["PassTouches"]) != 0) 947 if ((sbyte)row["PassTouches"] != 0)
930 prim.PassTouches = true; 948 prim.PassTouches = true;
931 prim.LinkNum = Convert.ToInt32(row["LinkNumber"]); 949 prim.LinkNum = (int)row["LinkNumber"];
932 950
933 return prim; 951 return prim;
934 } 952 }
diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs
index 9fd043c..d304345 100644
--- a/OpenSim/Framework/IClientAPI.cs
+++ b/OpenSim/Framework/IClientAPI.cs
@@ -448,6 +448,10 @@ namespace OpenSim.Framework
448 public delegate void AvatarInterestUpdate(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages); 448 public delegate void AvatarInterestUpdate(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages);
449 public delegate void PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client); 449 public delegate void PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client);
450 450
451 public delegate void AgentFOV(IClientAPI client, float verticalAngle);
452
453 public delegate double UpdatePriorityHandler(UpdatePriorityData data);
454
451 #endregion 455 #endregion
452 456
453 public struct DirPlacesReplyData 457 public struct DirPlacesReplyData
@@ -517,6 +521,232 @@ namespace OpenSim.Framework
517 public float dwell; 521 public float dwell;
518 } 522 }
519 523
524 public struct SendAvatarData
525 {
526 public readonly ulong RegionHandle;
527 public readonly string FirstName;
528 public readonly string LastName;
529 public readonly string GroupTitle;
530 public readonly UUID AvatarID;
531 public readonly uint AvatarLocalID;
532 public readonly Vector3 Position;
533 public readonly byte[] TextureEntry;
534 public readonly uint ParentID;
535 public readonly Quaternion Rotation;
536
537 public SendAvatarData(ulong regionHandle, string firstName, string lastName, string groupTitle, UUID avatarID,
538 uint avatarLocalID, Vector3 position, byte[] textureEntry, uint parentID, Quaternion rotation)
539 {
540 RegionHandle = regionHandle;
541 FirstName = firstName;
542 LastName = lastName;
543 GroupTitle = groupTitle;
544 AvatarID = avatarID;
545 AvatarLocalID = avatarLocalID;
546 Position = position;
547 TextureEntry = textureEntry;
548 ParentID = parentID;
549 Rotation = rotation;
550 }
551 }
552
553 public struct SendAvatarTerseData
554 {
555 public readonly ulong RegionHandle;
556 public readonly ushort TimeDilation;
557 public readonly uint LocalID;
558 public readonly Vector3 Position;
559 public readonly Vector3 Velocity;
560 public readonly Vector3 Acceleration;
561 public readonly Quaternion Rotation;
562 public readonly Vector4 CollisionPlane;
563 public readonly UUID AgentID;
564 public readonly byte[] TextureEntry;
565 public readonly double Priority;
566
567 public SendAvatarTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity,
568 Vector3 acceleration, Quaternion rotation, Vector4 collisionPlane, UUID agentid, byte[] textureEntry, double priority)
569 {
570 RegionHandle = regionHandle;
571 TimeDilation = timeDilation;
572 LocalID = localID;
573 Position = position;
574 Velocity = velocity;
575 Acceleration = acceleration;
576 Rotation = rotation;
577 CollisionPlane = collisionPlane;
578 AgentID = agentid;
579 TextureEntry = textureEntry;
580 Priority = priority;
581 }
582 }
583
584 public struct SendPrimitiveTerseData
585 {
586 public readonly ulong RegionHandle;
587 public readonly ushort TimeDilation;
588 public readonly uint LocalID;
589 public readonly Vector3 Position;
590 public readonly Quaternion Rotation;
591 public readonly Vector3 Velocity;
592 public readonly Vector3 Acceleration;
593 public readonly Vector3 AngularVelocity;
594 public readonly byte State;
595 public readonly UUID AssetID;
596 public readonly UUID OwnerID;
597 public readonly int AttachPoint;
598 public readonly byte[] TextureEntry;
599 public readonly double Priority;
600
601 public SendPrimitiveTerseData(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position,
602 Quaternion rotation, Vector3 velocity, Vector3 acceleration, Vector3 rotationalvelocity, byte state,
603 UUID assetID, UUID ownerID, int attachPoint, byte[] textureEntry, double priority)
604 {
605 RegionHandle = regionHandle;
606 TimeDilation = timeDilation;
607 LocalID = localID;
608 Position = position;
609 Rotation = rotation;
610 Velocity = velocity;
611 Acceleration = acceleration;
612 AngularVelocity = rotationalvelocity;
613 State = state;
614 AssetID = assetID;
615 OwnerID = ownerID;
616 AttachPoint = attachPoint;
617 TextureEntry = textureEntry;
618 Priority = priority;
619 }
620 }
621
622 public struct SendPrimitiveData
623 {
624 private ulong m_regionHandle;
625 private ushort m_timeDilation;
626 private uint m_localID;
627 private PrimitiveBaseShape m_primShape;
628 private Vector3 m_pos;
629 private Vector3 m_vel;
630 private Vector3 m_acc;
631 private Quaternion m_rotation;
632 private Vector3 m_rvel;
633 private PrimFlags m_flags;
634 private UUID m_objectID;
635 private UUID m_ownerID;
636 private string m_text;
637 private byte[] m_color;
638 private uint m_parentID;
639 private byte[] m_particleSystem;
640 private byte m_clickAction;
641 private byte m_material;
642 private byte[] m_textureanim;
643 private bool m_attachment;
644 private uint m_AttachPoint;
645 private UUID m_AssetId;
646 private UUID m_SoundId;
647 private double m_SoundVolume;
648 private byte m_SoundFlags;
649 private double m_SoundRadius;
650 private double m_priority;
651
652 public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
653 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
654 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
655 uint parentID, byte[] particleSystem, byte clickAction, byte material, double priority) :
656 this(regionHandle, timeDilation, localID, primShape, pos, vel, acc, rotation, rvel, flags, objectID,
657 ownerID, text, color, parentID, particleSystem, clickAction, material, new byte[0], false, 0, UUID.Zero,
658 UUID.Zero, 0, 0, 0, priority) { }
659
660 public SendPrimitiveData(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
661 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
662 uint flags,
663 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID,
664 byte[] particleSystem,
665 byte clickAction, byte material, byte[] textureanim, bool attachment,
666 uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags,
667 double SoundRadius, double priority)
668 {
669 this.m_regionHandle = regionHandle;
670 this.m_timeDilation = timeDilation;
671 this.m_localID = localID;
672 this.m_primShape = primShape;
673 this.m_pos = pos;
674 this.m_vel = vel;
675 this.m_acc = acc;
676 this.m_rotation = rotation;
677 this.m_rvel = rvel;
678 this.m_flags = (PrimFlags)flags;
679 this.m_objectID = objectID;
680 this.m_ownerID = ownerID;
681 this.m_text = text;
682 this.m_color = color;
683 this.m_parentID = parentID;
684 this.m_particleSystem = particleSystem;
685 this.m_clickAction = clickAction;
686 this.m_material = material;
687 this.m_textureanim = textureanim;
688 this.m_attachment = attachment;
689 this.m_AttachPoint = AttachPoint;
690 this.m_AssetId = AssetId;
691 this.m_SoundId = SoundId;
692 this.m_SoundVolume = SoundVolume;
693 this.m_SoundFlags = SoundFlags;
694 this.m_SoundRadius = SoundRadius;
695 this.m_priority = priority;
696 }
697
698 public ulong regionHandle { get { return this.m_regionHandle; } }
699 public ushort timeDilation { get { return this.m_timeDilation; } }
700 public uint localID { get { return this.m_localID; } }
701 public PrimitiveBaseShape primShape { get { return this.m_primShape; } }
702 public Vector3 pos { get { return this.m_pos; } }
703 public Vector3 vel { get { return this.m_vel; } }
704 public Vector3 acc { get { return this.m_acc; } }
705 public Quaternion rotation { get { return this.m_rotation; } }
706 public Vector3 rvel { get { return this.m_rvel; } }
707 public PrimFlags flags { get { return this.m_flags; } }
708 public UUID objectID { get { return this.m_objectID; } }
709 public UUID ownerID { get { return this.m_ownerID; } }
710 public string text { get { return this.m_text; } }
711 public byte[] color { get { return this.m_color; } }
712 public uint parentID { get { return this.m_parentID; } }
713 public byte[] particleSystem { get { return this.m_particleSystem; } }
714 public byte clickAction { get { return this.m_clickAction; } }
715 public byte material { get { return this.m_material; } }
716 public byte[] textureanim { get { return this.m_textureanim; } }
717 public bool attachment { get { return this.m_attachment; } }
718 public uint AttachPoint { get { return this.m_AttachPoint; } }
719 public UUID AssetId { get { return this.m_AssetId; } }
720 public UUID SoundId { get { return this.m_SoundId; } }
721 public double SoundVolume { get { return this.m_SoundVolume; } }
722 public byte SoundFlags { get { return this.m_SoundFlags; } }
723 public double SoundRadius { get { return this.m_SoundRadius; } }
724 public double priority { get { return this.m_priority; } }
725 }
726
727 public struct UpdatePriorityData {
728 private double m_priority;
729 private uint m_localID;
730
731 public UpdatePriorityData(double priority, uint localID) {
732 this.m_priority = priority;
733 this.m_localID = localID;
734 }
735
736 public double priority { get { return this.m_priority; } }
737 public uint localID { get { return this.m_localID; } }
738 }
739
740 [Flags]
741 public enum StateUpdateTypes
742 {
743 None = 0,
744 AvatarTerse = 1,
745 PrimitiveTerse = AvatarTerse << 1,
746 PrimitiveFull = PrimitiveTerse << 1,
747 All = AvatarTerse | PrimitiveTerse | PrimitiveFull,
748 }
749
520 public interface IClientAPI 750 public interface IClientAPI
521 { 751 {
522 Vector3 StartPos { get; set; } 752 Vector3 StartPos { get; set; }
@@ -878,37 +1108,20 @@ namespace OpenSim.Framework
878 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance); 1108 void SendMoneyBalance(UUID transaction, bool success, byte[] description, int balance);
879 void SendPayPrice(UUID objectID, int[] payPrice); 1109 void SendPayPrice(UUID objectID, int[] payPrice);
880 1110
881 void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, 1111 void SendAvatarData(SendAvatarData data);
882 uint avatarLocalID,
883 Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation);
884 1112
885 void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 1113 void SendAvatarTerseUpdate(SendAvatarTerseData data);
886 Vector3 velocity, Quaternion rotation, UUID agentid);
887 1114
888 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations); 1115 void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations);
889 1116
890 void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID); 1117 void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID);
891 void SetChildAgentThrottle(byte[] throttle); 1118 void SetChildAgentThrottle(byte[] throttle);
892 1119
893 void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape, 1120 void SendPrimitiveToClient(SendPrimitiveData data);
894 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
895 uint flags,
896 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID,
897 byte[] particleSystem,
898 byte clickAction, byte material, byte[] textureanim, bool attachment,
899 uint AttachPoint, UUID AssetId, UUID SoundId, double SoundVolume, byte SoundFlags,
900 double SoundRadius);
901
902
903 void SendPrimitiveToClient(ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
904 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
905 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
906 uint parentID, byte[] particleSystem, byte clickAction, byte material);
907 1121
1122 void SendPrimTerseUpdate(SendPrimitiveTerseData data);
908 1123
909 void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 1124 void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler);
910 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state,
911 UUID AssetId, UUID owner, int attachPoint);
912 1125
913 void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, 1126 void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items,
914 List<InventoryFolderBase> folders, bool fetchFolders, 1127 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/Parallel.cs b/OpenSim/Framework/Parallel.cs
index 6efdad0..cf4f773 100644
--- a/OpenSim/Framework/Parallel.cs
+++ b/OpenSim/Framework/Parallel.cs
@@ -36,7 +36,7 @@ namespace OpenSim.Framework
36 /// </summary> 36 /// </summary>
37 public static class Parallel 37 public static class Parallel
38 { 38 {
39 private static readonly int processorCount = System.Environment.ProcessorCount; 39 public static readonly int ProcessorCount = System.Environment.ProcessorCount;
40 40
41 /// <summary> 41 /// <summary>
42 /// Executes a for loop in which iterations may run in parallel 42 /// Executes a for loop in which iterations may run in parallel
@@ -46,7 +46,7 @@ namespace OpenSim.Framework
46 /// <param name="body">Method body to run for each iteration of the loop</param> 46 /// <param name="body">Method body to run for each iteration of the loop</param>
47 public static void For(int fromInclusive, int toExclusive, Action<int> body) 47 public static void For(int fromInclusive, int toExclusive, Action<int> body)
48 { 48 {
49 For(processorCount, fromInclusive, toExclusive, body); 49 For(ProcessorCount, fromInclusive, toExclusive, body);
50 } 50 }
51 51
52 /// <summary> 52 /// <summary>
@@ -103,7 +103,7 @@ namespace OpenSim.Framework
103 /// <param name="body">Method body to run for each object in the collection</param> 103 /// <param name="body">Method body to run for each object in the collection</param>
104 public static void ForEach<T>(IEnumerable<T> enumerable, Action<T> body) 104 public static void ForEach<T>(IEnumerable<T> enumerable, Action<T> body)
105 { 105 {
106 ForEach<T>(processorCount, enumerable, body); 106 ForEach<T>(ProcessorCount, enumerable, body);
107 } 107 }
108 108
109 /// <summary> 109 /// <summary>
@@ -161,7 +161,7 @@ namespace OpenSim.Framework
161 /// <param name="actions">A series of method bodies to execute</param> 161 /// <param name="actions">A series of method bodies to execute</param>
162 public static void Invoke(params Action[] actions) 162 public static void Invoke(params Action[] actions)
163 { 163 {
164 Invoke(processorCount, actions); 164 Invoke(ProcessorCount, actions);
165 } 165 }
166 166
167 /// <summary> 167 /// <summary>
diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs
index a7315f5..fa747c4 100644
--- a/OpenSim/Framework/RegionInfo.cs
+++ b/OpenSim/Framework/RegionInfo.cs
@@ -821,7 +821,7 @@ namespace OpenSim.Framework
821 "Scope ID for this region", ScopeID.ToString(), true); 821 "Scope ID for this region", ScopeID.ToString(), true);
822 822
823 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING, 823 configMember.addConfigurationOption("region_type", ConfigurationOption.ConfigurationTypes.TYPE_STRING,
824 "Region Type", String.Empty, true); 824 "Free form string describing the type of region", String.Empty, true);
825 } 825 }
826 826
827 public void loadConfigurationOptions() 827 public void loadConfigurationOptions()
diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs
index 38729c6..d5ae3b7 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,17 +1270,37 @@ 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);
1293 System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, null);
1275 } 1294 }
1276 1295
1277 public static void FireAndForget(System.Threading.WaitCallback callback, object obj) 1296 public static void FireAndForget(System.Threading.WaitCallback callback, object obj)
1278 { 1297 {
1279 callback.BeginInvoke(obj, EndFireAndForget, callback); 1298 //FireAndForgetWrapper wrapper = Singleton.GetInstance<FireAndForgetWrapper>();
1299 //wrapper.FireAndForget(callback, obj);
1300 System.Threading.ThreadPool.UnsafeQueueUserWorkItem(callback, obj);
1280 } 1301 }
1281 1302
1282 private static void EndFireAndForget(IAsyncResult ar) 1303 /*private static void EndFireAndForget(IAsyncResult ar)
1283 { 1304 {
1284 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState; 1305 System.Threading.WaitCallback callback = (System.Threading.WaitCallback)ar.AsyncState;
1285 1306
@@ -1287,7 +1308,7 @@ namespace OpenSim.Framework
1287 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); } 1308 catch (Exception ex) { m_log.Error("[UTIL]: Asynchronous method threw an exception: " + ex.Message, ex); }
1288 1309
1289 ar.AsyncWaitHandle.Close(); 1310 ar.AsyncWaitHandle.Close();
1290 } 1311 }*/
1291 1312
1292 #endregion FireAndForget Threading Pattern 1313 #endregion FireAndForget Threading Pattern
1293 } 1314 }
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
index 05a2a63..b027882 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs
@@ -51,6 +51,44 @@ using Nini.Config;
51 51
52namespace OpenSim.Region.ClientStack.LindenUDP 52namespace OpenSim.Region.ClientStack.LindenUDP
53{ 53{
54 #region Enums
55
56 /// <summary>
57 /// Specifies the fields that have been changed when sending a prim or
58 /// avatar update
59 /// </summary>
60 [Flags]
61 public enum PrimUpdateFlags : uint
62 {
63 None = 0,
64 AttachmentPoint = 1 << 0,
65 Material = 1 << 1,
66 ClickAction = 1 << 2,
67 Scale = 1 << 3,
68 ParentID = 1 << 4,
69 PrimFlags = 1 << 5,
70 PrimData = 1 << 6,
71 MediaURL = 1 << 7,
72 ScratchPad = 1 << 8,
73 Textures = 1 << 9,
74 TextureAnim = 1 << 10,
75 NameValue = 1 << 11,
76 Position = 1 << 12,
77 Rotation = 1 << 13,
78 Velocity = 1 << 14,
79 Acceleration = 1 << 15,
80 AngularVelocity = 1 << 16,
81 CollisionPlane = 1 << 17,
82 Text = 1 << 18,
83 Particles = 1 << 19,
84 ExtraData = 1 << 20,
85 Sound = 1 << 21,
86 Joint = 1 << 22,
87 FullUpdate = UInt32.MaxValue
88 }
89
90 #endregion Enums
91
54 public delegate bool PacketMethod(IClientAPI simClient, Packet packet); 92 public delegate bool PacketMethod(IClientAPI simClient, Packet packet);
55 93
56 /// <summary> 94 /// <summary>
@@ -257,6 +295,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
257 public event MuteListRequest OnMuteListRequest; 295 public event MuteListRequest OnMuteListRequest;
258 public event AvatarInterestUpdate OnAvatarInterestUpdate; 296 public event AvatarInterestUpdate OnAvatarInterestUpdate;
259 public event PlacesQuery OnPlacesQuery; 297 public event PlacesQuery OnPlacesQuery;
298 public event AgentFOV OnAgentFOV;
260 299
261 #endregion Events 300 #endregion Events
262 301
@@ -282,12 +321,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
282 private readonly IGroupsModule m_GroupsModule; 321 private readonly IGroupsModule m_GroupsModule;
283 322
284 private int m_cachedTextureSerial; 323 private int m_cachedTextureSerial;
285 private Timer m_avatarTerseUpdateTimer; 324 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates;
286 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_avatarTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>(); 325 private PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates;
287 private Timer m_primTerseUpdateTimer; 326 private PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates;
288 private List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock> m_primTerseUpdates = new List<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
289 private Timer m_primFullUpdateTimer;
290 private List<ObjectUpdatePacket.ObjectDataBlock> m_primFullUpdates = new List<ObjectUpdatePacket.ObjectDataBlock>();
291 private int m_moneyBalance; 327 private int m_moneyBalance;
292 private int m_animationSequenceNumber = 1; 328 private int m_animationSequenceNumber = 1;
293 private bool m_SendLogoutPacketWhenClosing = true; 329 private bool m_SendLogoutPacketWhenClosing = true;
@@ -296,26 +332,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
296 332
297 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>(); 333 protected Dictionary<PacketType, PacketMethod> m_packetHandlers = new Dictionary<PacketType, PacketMethod>();
298 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers 334 protected Dictionary<string, GenericMessage> m_genericPacketHandlers = new Dictionary<string, GenericMessage>(); //PauPaw:Local Generic Message handlers
299 protected IScene m_scene; 335 protected Scene m_scene;
300 protected LLImageManager m_imageManager; 336 protected LLImageManager m_imageManager;
301 protected string m_firstName; 337 protected string m_firstName;
302 protected string m_lastName; 338 protected string m_lastName;
303 protected Thread m_clientThread; 339 protected Thread m_clientThread;
304 protected Vector3 m_startpos; 340 protected Vector3 m_startpos;
305 protected EndPoint m_userEndPoint; 341 protected EndPoint m_userEndPoint;
306 protected UUID m_activeGroupID = UUID.Zero; 342 protected UUID m_activeGroupID;
307 protected string m_activeGroupName = String.Empty; 343 protected string m_activeGroupName = String.Empty;
308 protected ulong m_activeGroupPowers; 344 protected ulong m_activeGroupPowers;
309 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>(); 345 protected Dictionary<UUID,ulong> m_groupPowers = new Dictionary<UUID, ulong>();
310 protected int m_terrainCheckerCount; 346 protected int m_terrainCheckerCount;
311 347 protected uint m_agentFOVCounter;
312 // LL uses these limits, apparently. Compressed terse would be 23, but we don't have that yet 348
313 protected int m_primTerseUpdatesPerPacket = 10; 349 // These numbers are guesses at a decent tradeoff between responsiveness
314 protected int m_primFullUpdatesPerPacket = 14; 350 // of the interest list and throughput. Lower is more responsive, higher
315 protected int m_primTerseUpdateRate = 10; 351 // is better throughput
316 protected int m_primFullUpdateRate = 14; 352 protected int m_primTerseUpdatesPerPacket = 25;
317 protected int m_avatarTerseUpdateRate = 50; 353 protected int m_primFullUpdatesPerPacket = 100;
318 protected int m_avatarTerseUpdatesPerPacket = 5; 354 protected int m_avatarTerseUpdatesPerPacket = 10;
319 /// <summary>Number of texture packets to put on the queue each time the 355 /// <summary>Number of texture packets to put on the queue each time the
320 /// OnQueueEmpty event is triggered for the texture category</summary> 356 /// OnQueueEmpty event is triggered for the texture category</summary>
321 protected int m_textureSendLimit = 20; 357 protected int m_textureSendLimit = 20;
@@ -369,21 +405,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP
369 /// <summary> 405 /// <summary>
370 /// Constructor 406 /// Constructor
371 /// </summary> 407 /// </summary>
372 public LLClientView(EndPoint remoteEP, IScene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo, 408 public LLClientView(EndPoint remoteEP, Scene scene, LLUDPServer udpServer, LLUDPClient udpClient, AuthenticateResponse sessionInfo,
373 UUID agentId, UUID sessionId, uint circuitCode) 409 UUID agentId, UUID sessionId, uint circuitCode)
374 { 410 {
375 RegisterInterface<IClientIM>(this); 411 RegisterInterface<IClientIM>(this);
376 RegisterInterface<IClientChat>(this); 412 RegisterInterface<IClientChat>(this);
377 RegisterInterface<IClientIPEndpoint>(this); 413 RegisterInterface<IClientIPEndpoint>(this);
378 414
379 InitDefaultAnimations(); 415 InitDefaultAnimations();
380 416
381 m_scene = scene; 417 m_scene = scene;
418
419 m_avatarTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
420 m_primTerseUpdates = new PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
421 m_primFullUpdates = new PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>(m_scene.Entities.Count);
422
382 m_assetService = m_scene.RequestModuleInterface<IAssetService>(); 423 m_assetService = m_scene.RequestModuleInterface<IAssetService>();
383 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>(); 424 m_hyperAssets = m_scene.RequestModuleInterface<IHyperAssetService>();
384 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>(); 425 m_GroupsModule = scene.RequestModuleInterface<IGroupsModule>();
385 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>()); 426 m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface<IJ2KDecoder>());
386 m_channelVersion = Utils.StringToBytes(scene.GetSimulatorVersion()); 427 m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion());
387 m_agentId = agentId; 428 m_agentId = agentId;
388 m_sessionId = sessionId; 429 m_sessionId = sessionId;
389 m_secureSessionId = sessionInfo.LoginInfo.SecureSession; 430 m_secureSessionId = sessionInfo.LoginInfo.SecureSession;
@@ -438,25 +479,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
438 // Remove ourselves from the scene 479 // Remove ourselves from the scene
439 m_scene.RemoveClient(AgentId); 480 m_scene.RemoveClient(AgentId);
440 481
441 // Shut down timers. Thread Context of this method is murky. Lock all timers
442 if (m_avatarTerseUpdateTimer.Enabled)
443 lock (m_avatarTerseUpdateTimer)
444 m_avatarTerseUpdateTimer.Stop();
445 if (m_primTerseUpdateTimer.Enabled)
446 lock (m_primTerseUpdateTimer)
447 m_primTerseUpdateTimer.Stop();
448 if (m_primFullUpdateTimer.Enabled)
449 lock (m_primFullUpdateTimer)
450 m_primFullUpdateTimer.Stop();
451
452 // We can't reach into other scenes and close the connection 482 // We can't reach into other scenes and close the connection
453 // We need to do this over grid communications 483 // We need to do this over grid communications
454 //m_scene.CloseAllAgents(CircuitCode); 484 //m_scene.CloseAllAgents(CircuitCode);
455 485
456 m_avatarTerseUpdateTimer.Dispose();
457 m_primTerseUpdateTimer.Dispose();
458 m_primFullUpdateTimer.Dispose();
459
460 // Disable UDP handling for this client 486 // Disable UDP handling for this client
461 m_udpClient.Shutdown(); 487 m_udpClient.Shutdown();
462 488
@@ -474,7 +500,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
474 kupack.UserInfo.SessionID = SessionId; 500 kupack.UserInfo.SessionID = SessionId;
475 kupack.TargetBlock.TargetIP = 0; 501 kupack.TargetBlock.TargetIP = 0;
476 kupack.TargetBlock.TargetPort = 0; 502 kupack.TargetBlock.TargetPort = 0;
477 kupack.UserInfo.Reason = Utils.StringToBytes(message); 503 kupack.UserInfo.Reason = Util.StringToBytes256(message);
478 OutPacket(kupack, ThrottleOutPacketType.Task); 504 OutPacket(kupack, ThrottleOutPacketType.Task);
479 // You must sleep here or users get no message! 505 // You must sleep here or users get no message!
480 Thread.Sleep(500); 506 Thread.Sleep(500);
@@ -483,18 +509,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
483 509
484 public void Stop() 510 public void Stop()
485 { 511 {
486 // Shut down timers. Thread Context is Murky, lock all timers!
487 if (m_avatarTerseUpdateTimer.Enabled)
488 lock (m_avatarTerseUpdateTimer)
489 m_avatarTerseUpdateTimer.Stop();
490
491 if (m_primTerseUpdateTimer.Enabled)
492 lock (m_primTerseUpdateTimer)
493 m_primTerseUpdateTimer.Stop();
494 512
495 if (m_primFullUpdateTimer.Enabled)
496 lock (m_primFullUpdateTimer)
497 m_primFullUpdateTimer.Stop();
498 } 513 }
499 514
500 #endregion Client Methods 515 #endregion Client Methods
@@ -590,18 +605,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
590 605
591 public virtual void Start() 606 public virtual void Start()
592 { 607 {
593 m_avatarTerseUpdateTimer = new Timer(m_avatarTerseUpdateRate);
594 m_avatarTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessAvatarTerseUpdates);
595 m_avatarTerseUpdateTimer.AutoReset = false;
596
597 m_primTerseUpdateTimer = new Timer(m_primTerseUpdateRate);
598 m_primTerseUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimTerseUpdates);
599 m_primTerseUpdateTimer.AutoReset = false;
600
601 m_primFullUpdateTimer = new Timer(m_primFullUpdateRate);
602 m_primFullUpdateTimer.Elapsed += new ElapsedEventHandler(ProcessPrimFullUpdates);
603 m_primFullUpdateTimer.AutoReset = false;
604
605 m_scene.AddNewClient(this); 608 m_scene.AddNewClient(this);
606 609
607 RefreshGroupMembership(); 610 RefreshGroupMembership();
@@ -642,7 +645,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
642 handshake.RegionInfo.WaterHeight = args.waterHeight; 645 handshake.RegionInfo.WaterHeight = args.waterHeight;
643 646
644 handshake.RegionInfo.RegionFlags = args.regionFlags; 647 handshake.RegionInfo.RegionFlags = args.regionFlags;
645 handshake.RegionInfo.SimName = Utils.StringToBytes(args.regionName); 648 handshake.RegionInfo.SimName = Util.StringToBytes256(args.regionName);
646 handshake.RegionInfo.SimOwner = args.SimOwner; 649 handshake.RegionInfo.SimOwner = args.SimOwner;
647 handshake.RegionInfo.TerrainBase0 = args.terrainBase0; 650 handshake.RegionInfo.TerrainBase0 = args.terrainBase0;
648 handshake.RegionInfo.TerrainBase1 = args.terrainBase1; 651 handshake.RegionInfo.TerrainBase1 = args.terrainBase1;
@@ -698,11 +701,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
698 { 701 {
699 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); 702 ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator);
700 reply.ChatData.Audible = audible; 703 reply.ChatData.Audible = audible;
701 reply.ChatData.Message = Utils.StringToBytes(message); 704 reply.ChatData.Message = Util.StringToBytes1024(message);
702 reply.ChatData.ChatType = type; 705 reply.ChatData.ChatType = type;
703 reply.ChatData.SourceType = source; 706 reply.ChatData.SourceType = source;
704 reply.ChatData.Position = fromPos; 707 reply.ChatData.Position = fromPos;
705 reply.ChatData.FromName = Utils.StringToBytes(fromName); 708 reply.ChatData.FromName = Util.StringToBytes256(fromName);
706 reply.ChatData.OwnerID = fromAgentID; 709 reply.ChatData.OwnerID = fromAgentID;
707 reply.ChatData.SourceID = fromAgentID; 710 reply.ChatData.SourceID = fromAgentID;
708 711
@@ -723,7 +726,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
723 726
724 msg.AgentData.AgentID = new UUID(im.fromAgentID); 727 msg.AgentData.AgentID = new UUID(im.fromAgentID);
725 msg.AgentData.SessionID = UUID.Zero; 728 msg.AgentData.SessionID = UUID.Zero;
726 msg.MessageBlock.FromAgentName = Utils.StringToBytes(im.fromAgentName); 729 msg.MessageBlock.FromAgentName = Util.StringToBytes256(im.fromAgentName);
727 msg.MessageBlock.Dialog = im.dialog; 730 msg.MessageBlock.Dialog = im.dialog;
728 msg.MessageBlock.FromGroup = im.fromGroup; 731 msg.MessageBlock.FromGroup = im.fromGroup;
729 if (im.imSessionID == UUID.Zero.Guid) 732 if (im.imSessionID == UUID.Zero.Guid)
@@ -736,12 +739,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
736 msg.MessageBlock.RegionID = new UUID(im.RegionID); 739 msg.MessageBlock.RegionID = new UUID(im.RegionID);
737 msg.MessageBlock.Timestamp = im.timestamp; 740 msg.MessageBlock.Timestamp = im.timestamp;
738 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID); 741 msg.MessageBlock.ToAgentID = new UUID(im.toAgentID);
739 // Cap the message length at 1099. There is a limit in ImprovedInstantMessagePacket 742 msg.MessageBlock.Message = Util.StringToBytes1024(im.message);
740 // the limit is 1100 but a 0 byte gets added to mark the end of the string
741 if (im.message != null && im.message.Length > 1099)
742 msg.MessageBlock.Message = Utils.StringToBytes(im.message.Substring(0, 1099));
743 else
744 msg.MessageBlock.Message = Utils.StringToBytes(im.message);
745 msg.MessageBlock.BinaryBucket = im.binaryBucket; 743 msg.MessageBlock.BinaryBucket = im.binaryBucket;
746 744
747 if (im.message.StartsWith("[grouptest]")) 745 if (im.message.StartsWith("[grouptest]"))
@@ -759,7 +757,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
759 eq.ChatterboxInvitation( 757 eq.ChatterboxInvitation(
760 new UUID("00000000-68f9-1111-024e-222222111123"), 758 new UUID("00000000-68f9-1111-024e-222222111123"),
761 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0, 759 "OpenSimulator Testing", new UUID(im.fromAgentID), im.message, new UUID(im.toAgentID), im.fromAgentName, im.dialog, 0,
762 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Utils.StringToBytes("OpenSimulator Testing")); 760 false, 0, new Vector3(), 1, new UUID(im.imSessionID), im.fromGroup, Util.StringToBytes256("OpenSimulator Testing"));
763 761
764 eq.ChatterBoxSessionAgentListUpdates( 762 eq.ChatterBoxSessionAgentListUpdates(
765 new UUID("00000000-68f9-1111-024e-222222111123"), 763 new UUID("00000000-68f9-1111-024e-222222111123"),
@@ -776,13 +774,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
776 public void SendGenericMessage(string method, List<string> message) 774 public void SendGenericMessage(string method, List<string> message)
777 { 775 {
778 GenericMessagePacket gmp = new GenericMessagePacket(); 776 GenericMessagePacket gmp = new GenericMessagePacket();
779 gmp.MethodData.Method = Utils.StringToBytes(method); 777 gmp.MethodData.Method = Util.StringToBytes256(method);
780 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count]; 778 gmp.ParamList = new GenericMessagePacket.ParamListBlock[message.Count];
781 int i = 0; 779 int i = 0;
782 foreach (string val in message) 780 foreach (string val in message)
783 { 781 {
784 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock(); 782 gmp.ParamList[i] = new GenericMessagePacket.ParamListBlock();
785 gmp.ParamList[i++].Parameter = Utils.StringToBytes(val); 783 gmp.ParamList[i++].Parameter = Util.StringToBytes256(val);
786 } 784 }
787 OutPacket(gmp, ThrottleOutPacketType.Task); 785 OutPacket(gmp, ThrottleOutPacketType.Task);
788 } 786 }
@@ -1046,7 +1044,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1046 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8; 1044 newSimPack.RegionData.SimIP += (uint)byteIP[1] << 8;
1047 newSimPack.RegionData.SimIP += (uint)byteIP[0]; 1045 newSimPack.RegionData.SimIP += (uint)byteIP[0];
1048 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port; 1046 newSimPack.RegionData.SimPort = (ushort)externalIPEndPoint.Port;
1049 newSimPack.RegionData.SeedCapability = Utils.StringToBytes(capsURL); 1047 newSimPack.RegionData.SeedCapability = Util.StringToBytes256(capsURL);
1050 1048
1051 // Hack to get this out immediately and skip throttles 1049 // Hack to get this out immediately and skip throttles
1052 OutPacket(newSimPack, ThrottleOutPacketType.Unknown); 1050 OutPacket(newSimPack, ThrottleOutPacketType.Unknown);
@@ -1124,7 +1122,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1124 teleport.Info.RegionHandle = regionHandle; 1122 teleport.Info.RegionHandle = regionHandle;
1125 teleport.Info.SimAccess = simAccess; 1123 teleport.Info.SimAccess = simAccess;
1126 1124
1127 teleport.Info.SeedCapability = Utils.StringToBytes(capsURL); 1125 teleport.Info.SeedCapability = Util.StringToBytes256(capsURL);
1128 1126
1129 IPAddress oIP = newRegionEndPoint.Address; 1127 IPAddress oIP = newRegionEndPoint.Address;
1130 byte[] byteIP = oIP.GetAddressBytes(); 1128 byte[] byteIP = oIP.GetAddressBytes();
@@ -1149,7 +1147,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1149 { 1147 {
1150 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed); 1148 TeleportFailedPacket tpFailed = (TeleportFailedPacket)PacketPool.Instance.GetPacket(PacketType.TeleportFailed);
1151 tpFailed.Info.AgentID = AgentId; 1149 tpFailed.Info.AgentID = AgentId;
1152 tpFailed.Info.Reason = Utils.StringToBytes(reason); 1150 tpFailed.Info.Reason = Util.StringToBytes256(reason);
1153 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0]; 1151 tpFailed.AlertInfo = new TeleportFailedPacket.AlertInfoBlock[0];
1154 1152
1155 // Hack to get this out immediately and skip throttles 1153 // Hack to get this out immediately and skip throttles
@@ -1881,11 +1879,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1881 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate); 1879 AgentDataUpdatePacket sendAgentDataUpdate = (AgentDataUpdatePacket)PacketPool.Instance.GetPacket(PacketType.AgentDataUpdate);
1882 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid; 1880 sendAgentDataUpdate.AgentData.ActiveGroupID = activegroupid;
1883 sendAgentDataUpdate.AgentData.AgentID = agentid; 1881 sendAgentDataUpdate.AgentData.AgentID = agentid;
1884 sendAgentDataUpdate.AgentData.FirstName = Utils.StringToBytes(firstname); 1882 sendAgentDataUpdate.AgentData.FirstName = Util.StringToBytes256(firstname);
1885 sendAgentDataUpdate.AgentData.GroupName = Utils.StringToBytes(groupname); 1883 sendAgentDataUpdate.AgentData.GroupName = Util.StringToBytes256(groupname);
1886 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers; 1884 sendAgentDataUpdate.AgentData.GroupPowers = grouppowers;
1887 sendAgentDataUpdate.AgentData.GroupTitle = Utils.StringToBytes(grouptitle); 1885 sendAgentDataUpdate.AgentData.GroupTitle = Util.StringToBytes256(grouptitle);
1888 sendAgentDataUpdate.AgentData.LastName = Utils.StringToBytes(lastname); 1886 sendAgentDataUpdate.AgentData.LastName = Util.StringToBytes256(lastname);
1889 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task); 1887 OutPacket(sendAgentDataUpdate, ThrottleOutPacketType.Task);
1890 } 1888 }
1891 1889
@@ -1898,7 +1896,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1898 { 1896 {
1899 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage); 1897 AlertMessagePacket alertPack = (AlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AlertMessage);
1900 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock(); 1898 alertPack.AlertData = new AlertMessagePacket.AlertDataBlock();
1901 alertPack.AlertData.Message = Utils.StringToBytes(message); 1899 alertPack.AlertData.Message = Util.StringToBytes256(message);
1902 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0]; 1900 alertPack.AlertInfo = new AlertMessagePacket.AlertInfoBlock[0];
1903 OutPacket(alertPack, ThrottleOutPacketType.Task); 1901 OutPacket(alertPack, ThrottleOutPacketType.Task);
1904 } 1902 }
@@ -1925,7 +1923,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1925 { 1923 {
1926 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage); 1924 AgentAlertMessagePacket alertPack = (AgentAlertMessagePacket)PacketPool.Instance.GetPacket(PacketType.AgentAlertMessage);
1927 alertPack.AgentData.AgentID = AgentId; 1925 alertPack.AgentData.AgentID = AgentId;
1928 alertPack.AlertData.Message = Utils.StringToBytes(message); 1926 alertPack.AlertData.Message = Util.StringToBytes256(message);
1929 alertPack.AlertData.Modal = modal; 1927 alertPack.AlertData.Modal = modal;
1930 1928
1931 return alertPack; 1929 return alertPack;
@@ -1935,12 +1933,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1935 string url) 1933 string url)
1936 { 1934 {
1937 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL); 1935 LoadURLPacket loadURL = (LoadURLPacket)PacketPool.Instance.GetPacket(PacketType.LoadURL);
1938 loadURL.Data.ObjectName = Utils.StringToBytes(objectname); 1936 loadURL.Data.ObjectName = Util.StringToBytes256(objectname);
1939 loadURL.Data.ObjectID = objectID; 1937 loadURL.Data.ObjectID = objectID;
1940 loadURL.Data.OwnerID = ownerID; 1938 loadURL.Data.OwnerID = ownerID;
1941 loadURL.Data.OwnerIsGroup = groupOwned; 1939 loadURL.Data.OwnerIsGroup = groupOwned;
1942 loadURL.Data.Message = Utils.StringToBytes(message); 1940 loadURL.Data.Message = Util.StringToBytes256(message);
1943 loadURL.Data.URL = Utils.StringToBytes(url); 1941 loadURL.Data.URL = Util.StringToBytes256(url);
1944 OutPacket(loadURL, ThrottleOutPacketType.Task); 1942 OutPacket(loadURL, ThrottleOutPacketType.Task);
1945 } 1943 }
1946 1944
@@ -1948,18 +1946,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP
1948 { 1946 {
1949 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog); 1947 ScriptDialogPacket dialog = (ScriptDialogPacket)PacketPool.Instance.GetPacket(PacketType.ScriptDialog);
1950 dialog.Data.ObjectID = objectID; 1948 dialog.Data.ObjectID = objectID;
1951 dialog.Data.ObjectName = Utils.StringToBytes(objectname); 1949 dialog.Data.ObjectName = Util.StringToBytes256(objectname);
1952 // this is the username of the *owner* 1950 // this is the username of the *owner*
1953 dialog.Data.FirstName = Utils.StringToBytes(ownerFirstName); 1951 dialog.Data.FirstName = Util.StringToBytes256(ownerFirstName);
1954 dialog.Data.LastName = Utils.StringToBytes(ownerLastName); 1952 dialog.Data.LastName = Util.StringToBytes256(ownerLastName);
1955 dialog.Data.Message = Utils.StringToBytes(msg); 1953 dialog.Data.Message = Util.StringToBytes1024(msg);
1956 dialog.Data.ImageID = textureID; 1954 dialog.Data.ImageID = textureID;
1957 dialog.Data.ChatChannel = ch; 1955 dialog.Data.ChatChannel = ch;
1958 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length]; 1956 ScriptDialogPacket.ButtonsBlock[] buttons = new ScriptDialogPacket.ButtonsBlock[buttonlabels.Length];
1959 for (int i = 0; i < buttonlabels.Length; i++) 1957 for (int i = 0; i < buttonlabels.Length; i++)
1960 { 1958 {
1961 buttons[i] = new ScriptDialogPacket.ButtonsBlock(); 1959 buttons[i] = new ScriptDialogPacket.ButtonsBlock();
1962 buttons[i].ButtonLabel = Utils.StringToBytes(buttonlabels[i]); 1960 buttons[i].ButtonLabel = Util.StringToBytes256(buttonlabels[i]);
1963 } 1961 }
1964 dialog.Buttons = buttons; 1962 dialog.Buttons = buttons;
1965 OutPacket(dialog, ThrottleOutPacketType.Task); 1963 OutPacket(dialog, ThrottleOutPacketType.Task);
@@ -2115,19 +2113,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2115 avatarReply.AgentData.AgentID = AgentId; 2113 avatarReply.AgentData.AgentID = AgentId;
2116 avatarReply.AgentData.AvatarID = avatarID; 2114 avatarReply.AgentData.AvatarID = avatarID;
2117 if (aboutText != null) 2115 if (aboutText != null)
2118 avatarReply.PropertiesData.AboutText = Utils.StringToBytes(aboutText); 2116 avatarReply.PropertiesData.AboutText = Util.StringToBytes1024(aboutText);
2119 else 2117 else
2120 avatarReply.PropertiesData.AboutText = Utils.StringToBytes(""); 2118 avatarReply.PropertiesData.AboutText = Utils.EmptyBytes;
2121 avatarReply.PropertiesData.BornOn = Utils.StringToBytes(bornOn); 2119 avatarReply.PropertiesData.BornOn = Util.StringToBytes256(bornOn);
2122 avatarReply.PropertiesData.CharterMember = charterMember; 2120 avatarReply.PropertiesData.CharterMember = charterMember;
2123 if (flAbout != null) 2121 if (flAbout != null)
2124 avatarReply.PropertiesData.FLAboutText = Utils.StringToBytes(flAbout); 2122 avatarReply.PropertiesData.FLAboutText = Util.StringToBytes256(flAbout);
2125 else 2123 else
2126 avatarReply.PropertiesData.FLAboutText = Utils.StringToBytes(""); 2124 avatarReply.PropertiesData.FLAboutText = Utils.EmptyBytes;
2127 avatarReply.PropertiesData.Flags = flags; 2125 avatarReply.PropertiesData.Flags = flags;
2128 avatarReply.PropertiesData.FLImageID = flImageID; 2126 avatarReply.PropertiesData.FLImageID = flImageID;
2129 avatarReply.PropertiesData.ImageID = imageID; 2127 avatarReply.PropertiesData.ImageID = imageID;
2130 avatarReply.PropertiesData.ProfileURL = Utils.StringToBytes(profileURL); 2128 avatarReply.PropertiesData.ProfileURL = Util.StringToBytes256(profileURL);
2131 avatarReply.PropertiesData.PartnerID = partnerID; 2129 avatarReply.PropertiesData.PartnerID = partnerID;
2132 OutPacket(avatarReply, ThrottleOutPacketType.Task); 2130 OutPacket(avatarReply, ThrottleOutPacketType.Task);
2133 } 2131 }
@@ -2254,7 +2252,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2254 Group.Contribution = GroupMembership[i].Contribution; 2252 Group.Contribution = GroupMembership[i].Contribution;
2255 Group.GroupID = GroupMembership[i].GroupID; 2253 Group.GroupID = GroupMembership[i].GroupID;
2256 Group.GroupInsigniaID = GroupMembership[i].GroupPicture; 2254 Group.GroupInsigniaID = GroupMembership[i].GroupPicture;
2257 Group.GroupName = Utils.StringToBytes(GroupMembership[i].GroupName); 2255 Group.GroupName = Util.StringToBytes256(GroupMembership[i].GroupName);
2258 Group.GroupPowers = GroupMembership[i].GroupPowers; 2256 Group.GroupPowers = GroupMembership[i].GroupPowers;
2259 Groups[i] = Group; 2257 Groups[i] = Group;
2260 2258
@@ -2288,7 +2286,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2288 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1]; 2286 UUIDGroupNameReplyPacket.UUIDNameBlockBlock[] uidnameblock = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock[1];
2289 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock(); 2287 UUIDGroupNameReplyPacket.UUIDNameBlockBlock uidnamebloc = new UUIDGroupNameReplyPacket.UUIDNameBlockBlock();
2290 uidnamebloc.ID = groupLLUID; 2288 uidnamebloc.ID = groupLLUID;
2291 uidnamebloc.GroupName = Utils.StringToBytes(GroupName); 2289 uidnamebloc.GroupName = Util.StringToBytes256(GroupName);
2292 uidnameblock[0] = uidnamebloc; 2290 uidnameblock[0] = uidnamebloc;
2293 pack.UUIDNameBlock = uidnameblock; 2291 pack.UUIDNameBlock = uidnameblock;
2294 OutPacket(pack, ThrottleOutPacketType.Task); 2292 OutPacket(pack, ThrottleOutPacketType.Task);
@@ -2313,8 +2311,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
2313 lsrepdb.Score = lsrpia[i].Score; 2311 lsrepdb.Score = lsrpia[i].Score;
2314 lsrepdb.TaskID = lsrpia[i].TaskID; 2312 lsrepdb.TaskID = lsrpia[i].TaskID;
2315 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID; 2313 lsrepdb.TaskLocalID = lsrpia[i].TaskLocalID;
2316 lsrepdb.TaskName = Utils.StringToBytes(lsrpia[i].TaskName); 2314 lsrepdb.TaskName = Util.StringToBytes256(lsrpia[i].TaskName);
2317 lsrepdb.OwnerName = Utils.StringToBytes(lsrpia[i].OwnerName); 2315 lsrepdb.OwnerName = Util.StringToBytes256(lsrpia[i].OwnerName);
2318 lsrepdba[i] = lsrepdb; 2316 lsrepdba[i] = lsrepdb;
2319 } 2317 }
2320 lsrp.ReportData = lsrepdba; 2318 lsrp.ReportData = lsrepdba;
@@ -3127,7 +3125,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3127 3125
3128 avp.Sender.IsTrial = false; 3126 avp.Sender.IsTrial = false;
3129 avp.Sender.ID = agentID; 3127 avp.Sender.ID = agentID;
3130 OutPacket(avp, ThrottleOutPacketType.State); 3128 OutPacket(avp, ThrottleOutPacketType.Task);
3131 } 3129 }
3132 3130
3133 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) 3131 public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs)
@@ -3159,123 +3157,174 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3159 3157
3160 #endregion 3158 #endregion
3161 3159
3162 #region Avatar Packet/data sending Methods 3160 #region Prim/Avatar Updates
3163 3161
3164 /// <summary> 3162 /*void SendObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3165 /// send a objectupdate packet with information about the clients avatar
3166 /// </summary>
3167 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID,
3168 uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation)
3169 { 3163 {
3170 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); 3164 bool canUseCompressed, canUseImproved;
3171 // TODO: don't create new blocks if recycling an old packet 3165 UpdateFlagsToPacketType(creatorFlags, updateFlags, out canUseCompressed, out canUseImproved);
3172 objupdate.RegionData.RegionHandle = regionHandle;
3173 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3174 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3175 objupdate.ObjectData[0] = CreateDefaultAvatarPacket(textureEntry);
3176 3166
3177 //give this avatar object a local id and assign the user a name 3167 if (!canUseImproved && !canUseCompressed)
3178 objupdate.ObjectData[0].ID = avatarLocalID; 3168 SendFullObjectUpdate(obj, creatorFlags, updateFlags);
3179 objupdate.ObjectData[0].FullID = avatarID; 3169 else if (!canUseImproved)
3180 objupdate.ObjectData[0].ParentID = parentID; 3170 SendObjectUpdateCompressed(obj, creatorFlags, updateFlags);
3181 objupdate.ObjectData[0].NameValue = 3171 else
3182 Utils.StringToBytes("FirstName STRING RW SV " + firstName + "\nLastName STRING RW SV " + lastName + "\nTitle STRING RW SV " + grouptitle); 3172 SendImprovedTerseObjectUpdate(obj, creatorFlags, updateFlags);
3173 }
3183 3174
3184 Vector3 pos2 = new Vector3(Pos.X, Pos.Y, Pos.Z); 3175 void SendFullObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3185 byte[] pb = pos2.GetBytes(); 3176 {
3186 Array.Copy(pb, 0, objupdate.ObjectData[0].ObjectData, 16, pb.Length); 3177 IClientAPI owner;
3178 if (m_scene.ClientManager.TryGetValue(obj.OwnerID, out owner) && owner is LLClientView)
3179 {
3180 LLClientView llOwner = (LLClientView)owner;
3187 3181
3188 byte[] rot = rotation.GetBytes(); 3182 // Send an update out to the owner
3189 Array.Copy(rot, 0, objupdate.ObjectData[0].ObjectData, 52, rot.Length); 3183 ObjectUpdatePacket updateToOwner = new ObjectUpdatePacket();
3184 updateToOwner.RegionData.RegionHandle = obj.RegionHandle;
3185 //updateToOwner.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3186 updateToOwner.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3187 updateToOwner.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags | creatorFlags | PrimFlags.ObjectYouOwner, 0);
3190 3188
3191 objupdate.Header.Zerocoded = true; 3189 m_udpServer.SendPacket(llOwner.UDPClient, updateToOwner, ThrottleOutPacketType.State, true);
3192 OutPacket(objupdate, ThrottleOutPacketType.Task); 3190 }
3191
3192 // Send an update out to everyone else
3193 ObjectUpdatePacket updateToOthers = new ObjectUpdatePacket();
3194 updateToOthers.RegionData.RegionHandle = obj.RegionHandle;
3195 //updateToOthers.RegionData.TimeDilation = (ushort)(timeDilation * (float)UInt16.MaxValue);
3196 updateToOthers.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3197 updateToOthers.ObjectData[0] = BuildUpdateBlock(obj, obj.Flags, 0);
3198
3199 m_scene.ClientManager.ForEach(
3200 delegate(IClientAPI client)
3201 {
3202 if (client.AgentId != obj.OwnerID && client is LLClientView)
3203 {
3204 LLClientView llClient = (LLClientView)client;
3205 m_udpServer.SendPacket(llClient.UDPClient, updateToOthers, ThrottleOutPacketType.State, true);
3206 }
3207 }
3208 );
3193 } 3209 }
3194 3210
3195 /// <summary> 3211 void SendObjectUpdateCompressed(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3196 /// Send a terse positional/rotation/velocity update about an avatar
3197 /// to the client. This avatar can be that of the client itself.
3198 /// </summary>
3199 public virtual void SendAvatarTerseUpdate(ulong regionHandle,
3200 ushort timeDilation, uint localID, Vector3 position,
3201 Vector3 velocity, Quaternion rotation, UUID agentid)
3202 { 3212 {
3203 if (rotation.X == rotation.Y && 3213 }
3204 rotation.Y == rotation.Z &&
3205 rotation.Z == rotation.W && rotation.W == 0)
3206 rotation = Quaternion.Identity;
3207 3214
3208 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = 3215 void SendImprovedTerseObjectUpdate(SceneObjectPart obj, PrimFlags creatorFlags, PrimUpdateFlags updateFlags)
3209 CreateAvatarImprovedBlock(localID, position, velocity,rotation); 3216 {
3210 3217 }
3211 lock (m_avatarTerseUpdates)
3212 {
3213 m_avatarTerseUpdates.Add(terseBlock);
3214 3218
3215 // If packet is full or own movement packet, send it. 3219 void UpdateFlagsToPacketType(PrimFlags creatorFlags, PrimUpdateFlags updateFlags, out bool canUseCompressed, out bool canUseImproved)
3216 if (m_avatarTerseUpdates.Count >= m_avatarTerseUpdatesPerPacket) 3220 {
3221 canUseCompressed = true;
3222 canUseImproved = true;
3223
3224 if ((updateFlags & PrimUpdateFlags.FullUpdate) == PrimUpdateFlags.FullUpdate || creatorFlags != PrimFlags.None)
3225 {
3226 canUseCompressed = false;
3227 canUseImproved = false;
3228 }
3229 else
3230 {
3231 if ((updateFlags & PrimUpdateFlags.Velocity) != 0 ||
3232 (updateFlags & PrimUpdateFlags.Acceleration) != 0 ||
3233 (updateFlags & PrimUpdateFlags.CollisionPlane) != 0 ||
3234 (updateFlags & PrimUpdateFlags.Joint) != 0)
3217 { 3235 {
3218 ProcessAvatarTerseUpdates(this, null); 3236 canUseCompressed = false;
3219 } 3237 }
3220 else if (m_avatarTerseUpdates.Count == 1) 3238
3239 if ((updateFlags & PrimUpdateFlags.PrimFlags) != 0 ||
3240 (updateFlags & PrimUpdateFlags.ParentID) != 0 ||
3241 (updateFlags & PrimUpdateFlags.Scale) != 0 ||
3242 (updateFlags & PrimUpdateFlags.PrimData) != 0 ||
3243 (updateFlags & PrimUpdateFlags.Text) != 0 ||
3244 (updateFlags & PrimUpdateFlags.NameValue) != 0 ||
3245 (updateFlags & PrimUpdateFlags.ExtraData) != 0 ||
3246 (updateFlags & PrimUpdateFlags.TextureAnim) != 0 ||
3247 (updateFlags & PrimUpdateFlags.Sound) != 0 ||
3248 (updateFlags & PrimUpdateFlags.Particles) != 0 ||
3249 (updateFlags & PrimUpdateFlags.Material) != 0 ||
3250 (updateFlags & PrimUpdateFlags.ClickAction) != 0 ||
3251 (updateFlags & PrimUpdateFlags.MediaURL) != 0 ||
3252 (updateFlags & PrimUpdateFlags.Joint) != 0)
3221 { 3253 {
3222 lock (m_avatarTerseUpdateTimer) 3254 canUseImproved = false;
3223 m_avatarTerseUpdateTimer.Start();
3224 } 3255 }
3225 } 3256 }
3226 } 3257 }*/
3258
3259 #endregion Prim/Avatar Updates
3260
3261 #region Avatar Packet/Data Sending Methods
3227 3262
3228 private void ProcessAvatarTerseUpdates(object sender, ElapsedEventArgs e) 3263 /// <summary>
3264 /// Send an ObjectUpdate packet with information about an avatar
3265 /// </summary>
3266 public void SendAvatarData(SendAvatarData data)
3229 { 3267 {
3230 lock (m_avatarTerseUpdates) 3268 ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3231 { 3269 objupdate.Header.Zerocoded = true;
3232 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3233 3270
3234 terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock(); 3271 objupdate.RegionData.RegionHandle = data.RegionHandle;
3272 objupdate.RegionData.TimeDilation = ushort.MaxValue;
3273
3274 objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1];
3275 objupdate.ObjectData[0] = CreateAvatarUpdateBlock(data);
3235 3276
3236 terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle; 3277 OutPacket(objupdate, ThrottleOutPacketType.Task);
3237 terse.RegionData.TimeDilation = 3278 }
3238 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3239 3279
3240 int max = m_avatarTerseUpdatesPerPacket; 3280 /// <summary>
3241 if (max > m_avatarTerseUpdates.Count) 3281 /// Send a terse positional/rotation/velocity update about an avatar
3242 max = m_avatarTerseUpdates.Count; 3282 /// to the client. This avatar can be that of the client itself.
3283 /// </summary>
3284 public virtual void SendAvatarTerseUpdate(SendAvatarTerseData data)
3285 {
3286 if (data.Priority == double.NaN)
3287 {
3288 m_log.Error("[LLClientView] SendAvatarTerseUpdate received a NaN priority, dropping update");
3289 return;
3290 }
3243 3291
3244 int count = 0; 3292 Quaternion rotation = data.Rotation;
3245 int size = 0; 3293 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3294 rotation = Quaternion.Identity;
3246 3295
3247 byte[] zerobuffer = new byte[1024]; 3296 ImprovedTerseObjectUpdatePacket.ObjectDataBlock terseBlock = CreateImprovedTerseBlock(data);
3248 byte[] blockbuffer = new byte[1024];
3249 3297
3250 for (count = 0 ; count < max ; count++) 3298 lock (m_avatarTerseUpdates.SyncRoot)
3251 { 3299 m_avatarTerseUpdates.Enqueue(data.Priority, terseBlock, data.LocalID);
3252 int length = 0;
3253 m_avatarTerseUpdates[count].ToBytes(blockbuffer, ref length);
3254 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3255 if (size + length > Packet.MTU)
3256 break;
3257 size += length;
3258 }
3259 3300
3260 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count]; 3301 // If we received an update about our own avatar, process the avatar update priority queue immediately
3302 if (data.AgentID == m_agentId)
3303 ProcessAvatarTerseUpdates();
3304 }
3261 3305
3262 for (int i = 0 ; i < count ; i++) 3306 private void ProcessAvatarTerseUpdates()
3263 { 3307 {
3264 terse.ObjectData[i] = m_avatarTerseUpdates[0]; 3308 ImprovedTerseObjectUpdatePacket terse = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3265 m_avatarTerseUpdates.RemoveAt(0); 3309 terse.Header.Reliable = false;
3266 } 3310 terse.Header.Zerocoded = true;
3267 3311
3268 terse.Header.Reliable = false; 3312 //terse.RegionData = new ImprovedTerseObjectUpdatePacket.RegionDataBlock();
3269 terse.Header.Zerocoded = true; 3313 terse.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3270 // FIXME: Move this to ThrottleOutPacketType.State when the real prioritization code is committed 3314 terse.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3271 OutPacket(terse, ThrottleOutPacketType.Task);
3272 3315
3273 if (m_avatarTerseUpdates.Count == 0) 3316 lock (m_avatarTerseUpdates.SyncRoot)
3274 { 3317 {
3275 lock (m_avatarTerseUpdateTimer) 3318 int count = Math.Min(m_avatarTerseUpdates.Count, m_avatarTerseUpdatesPerPacket);
3276 m_avatarTerseUpdateTimer.Stop(); 3319 if (count == 0)
3277 } 3320 return;
3321
3322 terse.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3323 for (int i = 0; i < count; i++)
3324 terse.ObjectData[i] = m_avatarTerseUpdates.Dequeue();
3278 } 3325 }
3326
3327 OutPacket(terse, ThrottleOutPacketType.Task);
3279 } 3328 }
3280 3329
3281 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations) 3330 public void SendCoarseLocationUpdate(List<UUID> users, List<Vector3> CoarseLocations)
@@ -3314,319 +3363,231 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3314 OutPacket(loc, ThrottleOutPacketType.Task); 3363 OutPacket(loc, ThrottleOutPacketType.Task);
3315 } 3364 }
3316 3365
3317 #endregion 3366 #endregion Avatar Packet/Data Sending Methods
3318 3367
3319 #region Primitive Packet/data Sending Methods 3368 #region Primitive Packet/Data Sending Methods
3320 3369
3321 /// <summary> 3370 public void SendPrimitiveToClient(SendPrimitiveData data)
3322 ///
3323 /// </summary>
3324 /// <param name="localID"></param>
3325 /// <param name="rotation"></param>
3326 /// <param name="attachPoint"></param>
3327 public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
3328 { 3371 {
3329 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3372 if (data.priority == double.NaN)
3373 {
3374 m_log.Error("[LLClientView] SendPrimitiveToClient received a NaN priority, dropping update");
3330 return; 3375 return;
3376 }
3331 3377
3332 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); 3378 Quaternion rotation = data.rotation;
3333 // TODO: don't create new blocks if recycling an old packet 3379 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3334 attach.AgentData.AgentID = AgentId; 3380 rotation = Quaternion.Identity;
3335 attach.AgentData.SessionID = m_sessionId;
3336 attach.AgentData.AttachmentPoint = attachPoint;
3337 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
3338 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
3339 attach.ObjectData[0].ObjectLocalID = localID;
3340 attach.ObjectData[0].Rotation = rotation;
3341 attach.Header.Zerocoded = true;
3342 OutPacket(attach, ThrottleOutPacketType.Task);
3343 }
3344
3345 public void SendPrimitiveToClient(
3346 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3347 Vector3 pos, Vector3 vel, Vector3 acc, Quaternion rotation, Vector3 rvel,
3348 uint flags, UUID objectID, UUID ownerID, string text, byte[] color,
3349 uint parentID, byte[] particleSystem, byte clickAction, byte material)
3350 {
3351 byte[] textureanim = new byte[0];
3352
3353 SendPrimitiveToClient(regionHandle, timeDilation, localID, primShape, pos, vel,
3354 acc, rotation, rvel, flags,
3355 objectID, ownerID, text, color, parentID, particleSystem,
3356 clickAction, material, textureanim, false, 0, UUID.Zero, UUID.Zero, 0, 0, 0);
3357 }
3358
3359 public void SendPrimitiveToClient(
3360 ulong regionHandle, ushort timeDilation, uint localID, PrimitiveBaseShape primShape,
3361 Vector3 pos, Vector3 velocity, Vector3 acceleration, Quaternion rotation, Vector3 rotational_velocity,
3362 uint flags,
3363 UUID objectID, UUID ownerID, string text, byte[] color, uint parentID, byte[] particleSystem,
3364 byte clickAction, byte material, byte[] textureanim, bool attachment, uint AttachPoint, UUID AssetId, UUID SoundId, double SoundGain, byte SoundFlags, double SoundRadius)
3365 {
3366 3381
3367 if (AttachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3382 if (data.AttachPoint > 30 && data.ownerID != AgentId) // Someone else's HUD
3368 return; 3383 return;
3369 if (primShape.PCode == 9 && primShape.State != 0 && parentID == 0) 3384 if (data.primShape.State != 0 && data.parentID == 0 && data.primShape.PCode == 9)
3370 return; 3385 return;
3371 3386
3372 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3387 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(data);
3373 rotation = Quaternion.Identity;
3374 3388
3375 ObjectUpdatePacket.ObjectDataBlock objectData = CreatePrimUpdateBlock(primShape, flags); 3389 lock (m_primFullUpdates.SyncRoot)
3390 m_primFullUpdates.Enqueue(data.priority, objectData, data.localID);
3391 }
3376 3392
3377 objectData.ID = localID; 3393 void ProcessPrimFullUpdates()
3378 objectData.FullID = objectID; 3394 {
3379 objectData.OwnerID = ownerID; 3395 ObjectUpdatePacket outPacket = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate);
3396 outPacket.Header.Zerocoded = true;
3380 3397
3381 objectData.Text = Util.StringToBytes256(text); 3398 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3382 objectData.TextColor[0] = color[0]; 3399 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3383 objectData.TextColor[1] = color[1];
3384 objectData.TextColor[2] = color[2];
3385 objectData.TextColor[3] = color[3];
3386 objectData.ParentID = parentID;
3387 objectData.PSBlock = particleSystem;
3388 objectData.ClickAction = clickAction;
3389 objectData.Material = material;
3390 objectData.Flags = 0;
3391 3400
3392 if (attachment) 3401 lock (m_primFullUpdates.SyncRoot)
3393 { 3402 {
3394 // Necessary??? 3403 int count = Math.Min(m_primFullUpdates.Count, m_primFullUpdatesPerPacket);
3395 objectData.JointAxisOrAnchor = new Vector3(0, 0, 2); 3404 if (count == 0)
3396 objectData.JointPivot = new Vector3(0, 0, 0); 3405 return;
3397
3398 // Item from inventory???
3399 objectData.NameValue =
3400 Utils.StringToBytes("AttachItemID STRING RW SV " + AssetId.Guid);
3401 objectData.State = (byte)((AttachPoint % 16) * 16 + (AttachPoint / 16));
3402 }
3403 3406
3404 // Xantor 20080528: Send sound info as well 3407 outPacket.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[count];
3405 // Xantor 20080530: Zero out everything if there's no SoundId, so zerocompression will work again 3408 for (int i = 0; i < count; i++)
3406 objectData.Sound = SoundId; 3409 outPacket.ObjectData[i] = m_primFullUpdates.Dequeue();
3407 if (SoundId == UUID.Zero)
3408 {
3409 objectData.OwnerID = UUID.Zero;
3410 objectData.Gain = 0.0f;
3411 objectData.Radius = 0.0f;
3412 objectData.Flags = 0;
3413 } 3410 }
3414 else
3415 {
3416 objectData.OwnerID = ownerID;
3417 objectData.Gain = (float)SoundGain;
3418 objectData.Radius = (float)SoundRadius;
3419 objectData.Flags = SoundFlags;
3420 }
3421
3422 byte[] pb = pos.GetBytes();
3423 Array.Copy(pb, 0, objectData.ObjectData, 0, pb.Length);
3424
3425 byte[] vel = velocity.GetBytes();
3426 Array.Copy(vel, 0, objectData.ObjectData, pb.Length, vel.Length);
3427 3411
3428 byte[] rot = rotation.GetBytes(); 3412 OutPacket(outPacket, ThrottleOutPacketType.State);
3429 Array.Copy(rot, 0, objectData.ObjectData, 36, rot.Length); 3413 }
3430
3431 byte[] rvel = rotational_velocity.GetBytes();
3432 Array.Copy(rvel, 0, objectData.ObjectData, 36 + rot.Length, rvel.Length);
3433 3414
3434 if (textureanim.Length > 0) 3415 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
3416 {
3417 if (data.Priority == double.NaN)
3435 { 3418 {
3436 objectData.TextureAnim = textureanim; 3419 m_log.Error("[LLClientView] SendPrimTerseUpdate received a NaN priority, dropping update");
3420 return;
3437 } 3421 }
3438 3422
3439 lock (m_primFullUpdates) 3423 Quaternion rotation = data.Rotation;
3440 { 3424 if (rotation.W == 0.0f && rotation.X == 0.0f && rotation.Y == 0.0f && rotation.Z == 0.0f)
3441 if (m_primFullUpdates.Count == 0) 3425 rotation = Quaternion.Identity;
3442 m_primFullUpdateTimer.Start();
3443 3426
3444 m_primFullUpdates.Add(objectData); 3427 if (data.AttachPoint > 30 && data.OwnerID != AgentId) // Someone else's HUD
3428 return;
3445 3429
3446 if (m_primFullUpdates.Count >= m_primFullUpdatesPerPacket) 3430 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = CreateImprovedTerseBlock(data);
3447 ProcessPrimFullUpdates(this, null);
3448 }
3449 }
3450 3431
3451 void HandleQueueEmpty(ThrottleOutPacketType queue) 3432 lock (m_primTerseUpdates.SyncRoot)
3452 { 3433 m_primTerseUpdates.Enqueue(data.Priority, objectData, data.LocalID);
3453 switch (queue)
3454 {
3455 case ThrottleOutPacketType.Texture:
3456 ProcessTextureRequests();
3457 break;
3458 }
3459 } 3434 }
3460 3435
3461 void ProcessTextureRequests() 3436 void ProcessPrimTerseUpdates()
3462 { 3437 {
3463 if (m_imageManager != null) 3438 ImprovedTerseObjectUpdatePacket outPacket = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate);
3464 m_imageManager.ProcessImageQueue(m_textureSendLimit); 3439 outPacket.Header.Reliable = false;
3465 } 3440 outPacket.Header.Zerocoded = true;
3466 3441
3467 void ProcessPrimFullUpdates(object sender, ElapsedEventArgs e) 3442 outPacket.RegionData.RegionHandle = Scene.RegionInfo.RegionHandle;
3468 { 3443 outPacket.RegionData.TimeDilation = (ushort)(Scene.TimeDilation * ushort.MaxValue);
3469 lock (m_primFullUpdates)
3470 {
3471 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled)
3472 {
3473 lock (m_primFullUpdateTimer)
3474 m_primFullUpdateTimer.Stop();
3475 3444
3445 lock (m_primTerseUpdates.SyncRoot)
3446 {
3447 int count = Math.Min(m_primTerseUpdates.Count, m_primTerseUpdatesPerPacket);
3448 if (count == 0)
3476 return; 3449 return;
3477 }
3478
3479 ObjectUpdatePacket outPacket =
3480 (ObjectUpdatePacket)PacketPool.Instance.GetPacket(
3481 PacketType.ObjectUpdate);
3482
3483 outPacket.RegionData.RegionHandle =
3484 Scene.RegionInfo.RegionHandle;
3485 outPacket.RegionData.TimeDilation =
3486 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3487 3450
3488 int max = m_primFullUpdates.Count; 3451 outPacket.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[count];
3489 if (max > m_primFullUpdatesPerPacket) 3452 for (int i = 0; i < count; i++)
3490 max = m_primFullUpdatesPerPacket; 3453 outPacket.ObjectData[i] = m_primTerseUpdates.Dequeue();
3491 3454 }
3492 int count = 0;
3493 int size = 0;
3494 3455
3495 byte[] zerobuffer = new byte[1024]; 3456 OutPacket(outPacket, ThrottleOutPacketType.State);
3496 byte[] blockbuffer = new byte[1024]; 3457 }
3497 3458
3498 for (count = 0 ; count < max ; count++) 3459 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
3460 {
3461 PriorityQueue<double, ImprovedTerseObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler terse_update_priority_handler =
3462 delegate(ref double priority, uint local_id)
3499 { 3463 {
3500 int length = 0; 3464 priority = handler(new UpdatePriorityData(priority, local_id));
3501 m_primFullUpdates[count].ToBytes(blockbuffer, ref length); 3465 return priority != double.NaN;
3502 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer); 3466 };
3503 if (size + length > Packet.MTU) 3467 PriorityQueue<double, ObjectUpdatePacket.ObjectDataBlock>.UpdatePriorityHandler update_priority_handler =
3504 break; 3468 delegate(ref double priority, uint local_id)
3505 size += length; 3469 {
3506 } 3470 priority = handler(new UpdatePriorityData(priority, local_id));
3471 return priority != double.NaN;
3472 };
3507 3473
3508 outPacket.ObjectData = 3474 if ((type & StateUpdateTypes.AvatarTerse) != 0)
3509 new ObjectUpdatePacket.ObjectDataBlock[count]; 3475 {
3476 lock (m_avatarTerseUpdates.SyncRoot)
3477 m_avatarTerseUpdates.Reprioritize(terse_update_priority_handler);
3478 }
3510 3479
3511 for (int index = 0 ; index < count ; index++) 3480 if ((type & StateUpdateTypes.PrimitiveFull) != 0)
3512 { 3481 {
3513 outPacket.ObjectData[index] = m_primFullUpdates[0]; 3482 lock (m_primFullUpdates.SyncRoot)
3514 m_primFullUpdates.RemoveAt(0); 3483 m_primFullUpdates.Reprioritize(update_priority_handler);
3515 } 3484 }
3516 3485
3517 outPacket.Header.Zerocoded = true; 3486 if ((type & StateUpdateTypes.PrimitiveTerse) != 0)
3518 OutPacket(outPacket, ThrottleOutPacketType.State); 3487 {
3488 lock (m_primTerseUpdates.SyncRoot)
3489 m_primTerseUpdates.Reprioritize(terse_update_priority_handler);
3490 }
3491 }
3519 3492
3520 if (m_primFullUpdates.Count == 0 && m_primFullUpdateTimer.Enabled) 3493 public void FlushPrimUpdates()
3521 lock (m_primFullUpdateTimer) 3494 {
3522 m_primFullUpdateTimer.Stop(); 3495 while (m_primFullUpdates.Count > 0)
3496 {
3497 ProcessPrimFullUpdates();
3498 }
3499 while (m_primTerseUpdates.Count > 0)
3500 {
3501 ProcessPrimTerseUpdates();
3502 }
3503 while (m_avatarTerseUpdates.Count > 0)
3504 {
3505 ProcessAvatarTerseUpdates();
3523 } 3506 }
3524 } 3507 }
3525 3508
3509 #endregion Primitive Packet/Data Sending Methods
3510
3526 /// <summary> 3511 /// <summary>
3527 /// 3512 ///
3528 /// </summary> 3513 /// </summary>
3529 public void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, 3514 /// <param name="localID"></param>
3530 Quaternion rotation, Vector3 velocity, Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint) 3515 /// <param name="rotation"></param>
3516 /// <param name="attachPoint"></param>
3517 public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID)
3531 { 3518 {
3532 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD 3519 if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD
3533 return; 3520 return;
3534 3521
3535 if (rotation.X == rotation.Y && rotation.Y == rotation.Z && rotation.Z == rotation.W && rotation.W == 0) 3522 ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach);
3536 rotation = Quaternion.Identity; 3523 // TODO: don't create new blocks if recycling an old packet
3537 3524 attach.AgentData.AgentID = AgentId;
3538 ImprovedTerseObjectUpdatePacket.ObjectDataBlock objectData = 3525 attach.AgentData.SessionID = m_sessionId;
3539 CreatePrimImprovedBlock(localID, position, rotation, 3526 attach.AgentData.AttachmentPoint = attachPoint;
3540 velocity, rotationalvelocity, state); 3527 attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1];
3541 3528 attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock();
3542 lock (m_primTerseUpdates) 3529 attach.ObjectData[0].ObjectLocalID = localID;
3543 { 3530 attach.ObjectData[0].Rotation = rotation;
3544 if (m_primTerseUpdates.Count == 0) 3531 attach.Header.Zerocoded = true;
3545 m_primTerseUpdateTimer.Start(); 3532 OutPacket(attach, ThrottleOutPacketType.Task);
3546
3547 m_primTerseUpdates.Add(objectData);
3548
3549 if (m_primTerseUpdates.Count >= m_primTerseUpdatesPerPacket)
3550 ProcessPrimTerseUpdates(this, null);
3551 }
3552 } 3533 }
3553 3534
3554 void ProcessPrimTerseUpdates(object sender, ElapsedEventArgs e) 3535 void HandleQueueEmpty(ThrottleOutPacketType queue)
3555 { 3536 {
3556 lock (m_primTerseUpdates) 3537 switch (queue)
3557 { 3538 {
3558 if (m_primTerseUpdates.Count == 0) 3539 case ThrottleOutPacketType.Texture:
3559 { 3540 ProcessTextureRequests();
3560 lock (m_primTerseUpdateTimer) 3541 break;
3561 m_primTerseUpdateTimer.Stop(); 3542 case ThrottleOutPacketType.Task:
3562 3543 if (Monitor.TryEnter(m_avatarTerseUpdates.SyncRoot, 1))
3563 return; 3544 {
3564 } 3545 try
3565 3546 {
3566 ImprovedTerseObjectUpdatePacket outPacket = 3547 if (m_avatarTerseUpdates.Count > 0)
3567 (ImprovedTerseObjectUpdatePacket) 3548 {
3568 PacketPool.Instance.GetPacket(
3569 PacketType.ImprovedTerseObjectUpdate);
3570
3571 outPacket.RegionData.RegionHandle =
3572 Scene.RegionInfo.RegionHandle;
3573 outPacket.RegionData.TimeDilation =
3574 (ushort)(Scene.TimeDilation * ushort.MaxValue);
3575
3576 int max = m_primTerseUpdates.Count;
3577 if (max > m_primTerseUpdatesPerPacket)
3578 max = m_primTerseUpdatesPerPacket;
3579
3580 int count = 0;
3581 int size = 0;
3582
3583 byte[] zerobuffer = new byte[1024];
3584 byte[] blockbuffer = new byte[1024];
3585
3586 for (count = 0 ; count < max ; count++)
3587 {
3588 int length = 0;
3589 m_primTerseUpdates[count].ToBytes(blockbuffer, ref length);
3590 length = Helpers.ZeroEncode(blockbuffer, length, zerobuffer);
3591 if (size + length > Packet.MTU)
3592 break;
3593 size += length;
3594 }
3595
3596 outPacket.ObjectData =
3597 new ImprovedTerseObjectUpdatePacket.
3598 ObjectDataBlock[count];
3599
3600 for (int index = 0 ; index < count ; index++)
3601 {
3602 outPacket.ObjectData[index] = m_primTerseUpdates[0];
3603 m_primTerseUpdates.RemoveAt(0);
3604 }
3605 3549
3606 outPacket.Header.Reliable = false; 3550 ProcessAvatarTerseUpdates();
3607 outPacket.Header.Zerocoded = true; 3551 return;
3608 OutPacket(outPacket, ThrottleOutPacketType.State); 3552 }
3553 }
3554 finally { Monitor.Exit(m_avatarTerseUpdates.SyncRoot); }
3555 }
3556 break;
3557 case ThrottleOutPacketType.State:
3558 if (Monitor.TryEnter(m_primFullUpdates.SyncRoot, 1))
3559 {
3560 try
3561 {
3562 if (m_primFullUpdates.Count > 0)
3563 {
3564 ProcessPrimFullUpdates();
3565 return;
3566 }
3567 }
3568 finally { Monitor.Exit(m_primFullUpdates.SyncRoot); }
3569 }
3609 3570
3610 if (m_primTerseUpdates.Count == 0) 3571 if (Monitor.TryEnter(m_primTerseUpdates.SyncRoot, 1))
3611 lock (m_primTerseUpdateTimer) 3572 {
3612 m_primTerseUpdateTimer.Stop(); 3573 try
3574 {
3575 if (m_primTerseUpdates.Count > 0)
3576 {
3577 ProcessPrimTerseUpdates();
3578 return;
3579 }
3580 }
3581 finally { Monitor.Exit(m_primTerseUpdates.SyncRoot); }
3582 }
3583 break;
3613 } 3584 }
3614 } 3585 }
3615 3586
3616 public void FlushPrimUpdates() 3587 void ProcessTextureRequests()
3617 { 3588 {
3618 while (m_primFullUpdates.Count > 0) 3589 if (m_imageManager != null)
3619 { 3590 m_imageManager.ProcessImageQueue(m_textureSendLimit);
3620 ProcessPrimFullUpdates(this, null);
3621 }
3622 while (m_primTerseUpdates.Count > 0)
3623 {
3624 ProcessPrimTerseUpdates(this, null);
3625 }
3626 while (m_avatarTerseUpdates.Count > 0)
3627 {
3628 ProcessAvatarTerseUpdates(this, null);
3629 }
3630 } 3591 }
3631 3592
3632 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) 3593 public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID)
@@ -3810,8 +3771,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
3810 OutPacket(proper, ThrottleOutPacketType.Task); 3771 OutPacket(proper, ThrottleOutPacketType.Task);
3811 } 3772 }
3812 3773
3813 #endregion
3814
3815 #region Estate Data Sending Methods 3774 #region Estate Data Sending Methods
3816 3775
3817 private static bool convertParamStringToBool(byte[] field) 3776 private static bool convertParamStringToBool(byte[] field)
@@ -4218,325 +4177,221 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4218 4177
4219 #region Helper Methods 4178 #region Helper Methods
4220 4179
4221 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateAvatarImprovedBlock(uint localID, Vector3 pos, 4180 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendAvatarTerseData data)
4222 Vector3 velocity,
4223 Quaternion rotation)
4224 { 4181 {
4225 byte[] bytes = new byte[60]; 4182 return CreateImprovedTerseBlock(true, data.LocalID, 0, data.CollisionPlane, data.Position, data.Velocity,
4226 int i = 0; 4183 data.Acceleration, data.Rotation, Vector3.Zero, data.TextureEntry);
4227 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4228
4229 dat.TextureEntry = new byte[0]; // AvatarTemplate.TextureEntry;
4230
4231 uint ID = localID;
4232
4233 bytes[i++] = (byte)(ID % 256);
4234 bytes[i++] = (byte)((ID >> 8) % 256);
4235 bytes[i++] = (byte)((ID >> 16) % 256);
4236 bytes[i++] = (byte)((ID >> 24) % 256);
4237 bytes[i++] = 0;
4238 bytes[i++] = 1;
4239 i += 14;
4240 bytes[i++] = 128;
4241 bytes[i++] = 63;
4242
4243 byte[] pb = pos.GetBytes();
4244 Array.Copy(pb, 0, bytes, i, pb.Length);
4245 i += 12;
4246
4247 Vector3 internDirec = new Vector3(velocity.X, velocity.Y, velocity.Z);
4248
4249 internDirec = internDirec / 128.0f;
4250 internDirec.X += 1;
4251 internDirec.Y += 1;
4252 internDirec.Z += 1;
4253
4254 ushort InternVelocityX = (ushort)(32768 * internDirec.X);
4255 ushort InternVelocityY = (ushort)(32768 * internDirec.Y);
4256 ushort InternVelocityZ = (ushort)(32768 * internDirec.Z);
4257
4258 ushort ac = 32767;
4259 bytes[i++] = (byte)(InternVelocityX % 256);
4260 bytes[i++] = (byte)((InternVelocityX >> 8) % 256);
4261 bytes[i++] = (byte)(InternVelocityY % 256);
4262 bytes[i++] = (byte)((InternVelocityY >> 8) % 256);
4263 bytes[i++] = (byte)(InternVelocityZ % 256);
4264 bytes[i++] = (byte)((InternVelocityZ >> 8) % 256);
4265
4266 //accel
4267 bytes[i++] = (byte)(ac % 256);
4268 bytes[i++] = (byte)((ac >> 8) % 256);
4269 bytes[i++] = (byte)(ac % 256);
4270 bytes[i++] = (byte)((ac >> 8) % 256);
4271 bytes[i++] = (byte)(ac % 256);
4272 bytes[i++] = (byte)((ac >> 8) % 256);
4273
4274 //rotation
4275 ushort rw, rx, ry, rz;
4276 rw = (ushort)(32768 * (rotation.W + 1));
4277 rx = (ushort)(32768 * (rotation.X + 1));
4278 ry = (ushort)(32768 * (rotation.Y + 1));
4279 rz = (ushort)(32768 * (rotation.Z + 1));
4280
4281 //rot
4282 bytes[i++] = (byte)(rx % 256);
4283 bytes[i++] = (byte)((rx >> 8) % 256);
4284 bytes[i++] = (byte)(ry % 256);
4285 bytes[i++] = (byte)((ry >> 8) % 256);
4286 bytes[i++] = (byte)(rz % 256);
4287 bytes[i++] = (byte)((rz >> 8) % 256);
4288 bytes[i++] = (byte)(rw % 256);
4289 bytes[i++] = (byte)((rw >> 8) % 256);
4290
4291 //rotation vel
4292 bytes[i++] = (byte)(ac % 256);
4293 bytes[i++] = (byte)((ac >> 8) % 256);
4294 bytes[i++] = (byte)(ac % 256);
4295 bytes[i++] = (byte)((ac >> 8) % 256);
4296 bytes[i++] = (byte)(ac % 256);
4297 bytes[i++] = (byte)((ac >> 8) % 256);
4298
4299 dat.Data = bytes;
4300
4301 return (dat);
4302 } 4184 }
4303 4185
4304 /// <summary> 4186 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(SendPrimitiveTerseData data)
4305 ///
4306 /// </summary>
4307 /// <param name="localID"></param>
4308 /// <param name="position"></param>
4309 /// <param name="rotation"></param>
4310 /// <returns></returns>
4311 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreatePrimImprovedBlock(uint localID,
4312 Vector3 position,
4313 Quaternion rotation,
4314 Vector3 velocity,
4315 Vector3 rotationalvelocity,
4316 byte state)
4317 { 4187 {
4318 uint ID = localID; 4188 return CreateImprovedTerseBlock(false, data.LocalID, data.State, Vector4.Zero, data.Position, data.Velocity,
4319 byte[] bytes = new byte[60]; 4189 data.Acceleration, data.Rotation, data.AngularVelocity, data.TextureEntry);
4320
4321 int i = 0;
4322 ImprovedTerseObjectUpdatePacket.ObjectDataBlock dat = PacketPool.GetDataBlock<ImprovedTerseObjectUpdatePacket.ObjectDataBlock>();
4323 dat.TextureEntry = new byte[0];
4324 bytes[i++] = (byte)(ID % 256);
4325 bytes[i++] = (byte)((ID >> 8) % 256);
4326 bytes[i++] = (byte)((ID >> 16) % 256);
4327 bytes[i++] = (byte)((ID >> 24) % 256);
4328 bytes[i++] = (byte)(((state & 0xf0) >> 4) | ((state & 0x0f) << 4));
4329 bytes[i++] = 0;
4330
4331 byte[] pb = position.GetBytes();
4332 Array.Copy(pb, 0, bytes, i, pb.Length);
4333 i += 12;
4334 ushort ac = 32767;
4335
4336 ushort velx, vely, velz;
4337 Vector3 vel = new Vector3(velocity.X, velocity.Y, velocity.Z);
4338
4339 vel = vel / 128.0f;
4340 vel.X += 1;
4341 vel.Y += 1;
4342 vel.Z += 1;
4343 //vel
4344 velx = (ushort)(32768 * (vel.X));
4345 vely = (ushort)(32768 * (vel.Y));
4346 velz = (ushort)(32768 * (vel.Z));
4347
4348 bytes[i++] = (byte)(velx % 256);
4349 bytes[i++] = (byte)((velx >> 8) % 256);
4350 bytes[i++] = (byte)(vely % 256);
4351 bytes[i++] = (byte)((vely >> 8) % 256);
4352 bytes[i++] = (byte)(velz % 256);
4353 bytes[i++] = (byte)((velz >> 8) % 256);
4354
4355 //accel
4356 bytes[i++] = (byte)(ac % 256);
4357 bytes[i++] = (byte)((ac >> 8) % 256);
4358 bytes[i++] = (byte)(ac % 256);
4359 bytes[i++] = (byte)((ac >> 8) % 256);
4360 bytes[i++] = (byte)(ac % 256);
4361 bytes[i++] = (byte)((ac >> 8) % 256);
4362
4363 ushort rw, rx, ry, rz;
4364 rw = (ushort)(32768 * (rotation.W + 1));
4365 rx = (ushort)(32768 * (rotation.X + 1));
4366 ry = (ushort)(32768 * (rotation.Y + 1));
4367 rz = (ushort)(32768 * (rotation.Z + 1));
4368
4369 //rot
4370 bytes[i++] = (byte)(rx % 256);
4371 bytes[i++] = (byte)((rx >> 8) % 256);
4372 bytes[i++] = (byte)(ry % 256);
4373 bytes[i++] = (byte)((ry >> 8) % 256);
4374 bytes[i++] = (byte)(rz % 256);
4375 bytes[i++] = (byte)((rz >> 8) % 256);
4376 bytes[i++] = (byte)(rw % 256);
4377 bytes[i++] = (byte)((rw >> 8) % 256);
4378
4379 //rotation vel
4380 Vector3 rvel = new Vector3(rotationalvelocity.X, rotationalvelocity.Y, rotationalvelocity.Z);
4381
4382 rvel = rvel / 128.0f;
4383 rvel.X += 1;
4384 rvel.Y += 1;
4385 rvel.Z += 1;
4386 //vel
4387 ushort rvelx = (ushort)(32768 * (rvel.X));
4388 ushort rvely = (ushort)(32768 * (rvel.Y));
4389 ushort rvelz = (ushort)(32768 * (rvel.Z));
4390
4391 bytes[i++] = (byte)(rvelx % 256);
4392 bytes[i++] = (byte)((rvelx >> 8) % 256);
4393 bytes[i++] = (byte)(rvely % 256);
4394 bytes[i++] = (byte)((rvely >> 8) % 256);
4395 bytes[i++] = (byte)(rvelz % 256);
4396 bytes[i++] = (byte)((rvelz >> 8) % 256);
4397 dat.Data = bytes;
4398
4399 return dat;
4400 } 4190 }
4401 4191
4402 /// <summary> 4192 protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(bool avatar, uint localID, byte state,
4403 /// Create the ObjectDataBlock for a ObjectUpdatePacket (for a Primitive) 4193 Vector4 collisionPlane, Vector3 position, Vector3 velocity, Vector3 acceleration, Quaternion rotation,
4404 /// </summary> 4194 Vector3 angularVelocity, byte[] textureEntry)
4405 /// <param name="primData"></param> 4195 {
4406 /// <returns></returns> 4196 int pos = 0;
4407 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(PrimitiveBaseShape primShape, uint flags) 4197 byte[] data = new byte[(avatar ? 60 : 44)];
4408 {
4409 ObjectUpdatePacket.ObjectDataBlock objupdate = PacketPool.GetDataBlock<ObjectUpdatePacket.ObjectDataBlock>();
4410 SetDefaultPrimPacketValues(objupdate);
4411 objupdate.UpdateFlags = flags;
4412 SetPrimPacketShapeData(objupdate, primShape);
4413
4414 if ((primShape.PCode == (byte)PCode.NewTree) || (primShape.PCode == (byte)PCode.Tree) || (primShape.PCode == (byte)PCode.Grass))
4415 {
4416 objupdate.Data = new byte[1];
4417 objupdate.Data[0] = primShape.State;
4418 }
4419 return objupdate;
4420 }
4421
4422 protected void SetPrimPacketShapeData(ObjectUpdatePacket.ObjectDataBlock objectData, PrimitiveBaseShape primData)
4423 {
4424 objectData.TextureEntry = primData.TextureEntry;
4425 objectData.PCode = primData.PCode;
4426 objectData.State = primData.State;
4427 objectData.PathBegin = primData.PathBegin;
4428 objectData.PathEnd = primData.PathEnd;
4429 objectData.PathScaleX = primData.PathScaleX;
4430 objectData.PathScaleY = primData.PathScaleY;
4431 objectData.PathShearX = primData.PathShearX;
4432 objectData.PathShearY = primData.PathShearY;
4433 objectData.PathSkew = primData.PathSkew;
4434 objectData.ProfileBegin = primData.ProfileBegin;
4435 objectData.ProfileEnd = primData.ProfileEnd;
4436 objectData.Scale = primData.Scale;
4437 objectData.PathCurve = primData.PathCurve;
4438 objectData.ProfileCurve = primData.ProfileCurve;
4439 objectData.ProfileHollow = primData.ProfileHollow;
4440 objectData.PathRadiusOffset = primData.PathRadiusOffset;
4441 objectData.PathRevolutions = primData.PathRevolutions;
4442 objectData.PathTaperX = primData.PathTaperX;
4443 objectData.PathTaperY = primData.PathTaperY;
4444 objectData.PathTwist = primData.PathTwist;
4445 objectData.PathTwistBegin = primData.PathTwistBegin;
4446 objectData.ExtraParams = primData.ExtraParams;
4447 }
4448 4198
4449 /// <summary> 4199 // LocalID
4450 /// Set some default values in a ObjectUpdatePacket 4200 Utils.UIntToBytes(localID, data, pos);
4451 /// </summary> 4201 pos += 4;
4452 /// <param name="objdata"></param>
4453 protected void SetDefaultPrimPacketValues(ObjectUpdatePacket.ObjectDataBlock objdata)
4454 {
4455 objdata.PSBlock = new byte[0];
4456 objdata.ExtraParams = new byte[1];
4457 objdata.MediaURL = new byte[0];
4458 objdata.NameValue = new byte[0];
4459 objdata.Text = new byte[0];
4460 objdata.TextColor = new byte[4];
4461 objdata.JointAxisOrAnchor = new Vector3(0, 0, 0);
4462 objdata.JointPivot = new Vector3(0, 0, 0);
4463 objdata.Material = 3;
4464 objdata.TextureAnim = new byte[0];
4465 objdata.Sound = UUID.Zero;
4466 objdata.State = 0;
4467 objdata.Data = new byte[0];
4468
4469 objdata.ObjectData = new byte[60];
4470 objdata.ObjectData[46] = 128;
4471 objdata.ObjectData[47] = 63;
4472 }
4473 4202
4474 /// <summary> 4203 // Avatar/CollisionPlane
4475 /// 4204 data[pos++] = state;
4476 /// </summary> 4205 if (avatar)
4477 /// <returns></returns> 4206 {
4478 public ObjectUpdatePacket.ObjectDataBlock CreateDefaultAvatarPacket(byte[] textureEntry) 4207 data[pos++] = 1;
4479 {
4480 ObjectUpdatePacket.ObjectDataBlock objdata = PacketPool.GetDataBlock<ObjectUpdatePacket.ObjectDataBlock>();
4481 // new OpenMetaverse.Packets.ObjectUpdatePacket.ObjectDataBlock(data1, ref i);
4482 4208
4483 SetDefaultAvatarPacketValues(ref objdata); 4209 if (collisionPlane == Vector4.Zero)
4484 objdata.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); 4210 collisionPlane = Vector4.UnitW;
4485 objdata.PathCurve = 16; 4211
4486 objdata.ProfileCurve = 1; 4212 collisionPlane.ToBytes(data, pos);
4487 objdata.PathScaleX = 100; 4213 pos += 16;
4488 objdata.PathScaleY = 100; 4214 }
4489 objdata.ParentID = 0; 4215 else
4490 objdata.OwnerID = UUID.Zero;
4491 objdata.Scale = new Vector3(1, 1, 1);
4492 objdata.PCode = (byte)PCode.Avatar;
4493 if (textureEntry != null)
4494 { 4216 {
4495 objdata.TextureEntry = textureEntry; 4217 ++pos;
4496 } 4218 }
4497 Vector3 pos = new Vector3(objdata.ObjectData, 16);
4498 pos.X = 100f;
4499 objdata.ID = 8880000;
4500 objdata.NameValue = Utils.StringToBytes("FirstName STRING RW SV Test \nLastName STRING RW SV User ");
4501 //Vector3 pos2 = new Vector3(100f, 100f, 23f);
4502 //objdata.FullID=user.AgentId;
4503 byte[] pb = pos.GetBytes();
4504 Array.Copy(pb, 0, objdata.ObjectData, 16, pb.Length);
4505 4219
4506 return objdata; 4220 // Position
4507 } 4221 position.ToBytes(data, pos);
4222 pos += 12;
4508 4223
4509 /// <summary> 4224 // Velocity
4510 /// 4225 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2;
4511 /// </summary> 4226 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2;
4512 /// <param name="objdata"></param> 4227 Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2;
4513 protected void SetDefaultAvatarPacketValues(ref ObjectUpdatePacket.ObjectDataBlock objdata) 4228
4514 { 4229 // Acceleration
4515 objdata.PSBlock = new byte[0]; 4230 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2;
4516 objdata.ExtraParams = new byte[1]; 4231 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2;
4517 objdata.MediaURL = new byte[0]; 4232 Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2;
4518 objdata.NameValue = new byte[0]; 4233
4519 objdata.Text = new byte[0]; 4234 // Rotation
4520 objdata.TextColor = new byte[4]; 4235 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.X, -1.0f, 1.0f), data, pos); pos += 2;
4521 objdata.JointAxisOrAnchor = new Vector3(0, 0, 0); 4236 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Y, -1.0f, 1.0f), data, pos); pos += 2;
4522 objdata.JointPivot = new Vector3(0, 0, 0); 4237 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.Z, -1.0f, 1.0f), data, pos); pos += 2;
4523 objdata.Material = 4; 4238 Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2;
4524 objdata.TextureAnim = new byte[0]; 4239
4525 objdata.Sound = UUID.Zero; 4240 // Angular Velocity
4526 Primitive.TextureEntry ntex = new Primitive.TextureEntry(new UUID("00000000-0000-0000-5005-000000000005")); 4241 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2;
4527 objdata.TextureEntry = ntex.GetBytes(); 4242 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2;
4528 4243 Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2;
4529 objdata.State = 0; 4244
4530 objdata.Data = new byte[0]; 4245 ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock();
4531 4246 block.Data = data;
4532 objdata.ObjectData = new byte[76]; 4247
4533 objdata.ObjectData[15] = 128; 4248 if (textureEntry != null && textureEntry.Length > 0)
4534 objdata.ObjectData[16] = 63; 4249 {
4535 objdata.ObjectData[56] = 128; 4250 byte[] teBytesFinal = new byte[textureEntry.Length + 4];
4536 objdata.ObjectData[61] = 102; 4251
4537 objdata.ObjectData[62] = 40; 4252 // Texture Length
4538 objdata.ObjectData[63] = 61; 4253 Utils.IntToBytes(textureEntry.Length, textureEntry, 0);
4539 objdata.ObjectData[64] = 189; 4254 // Texture
4255 Buffer.BlockCopy(textureEntry, 0, teBytesFinal, 4, textureEntry.Length);
4256
4257 block.TextureEntry = teBytesFinal;
4258 }
4259 else
4260 {
4261 block.TextureEntry = Utils.EmptyBytes;
4262 }
4263
4264 return block;
4265 }
4266
4267 protected ObjectUpdatePacket.ObjectDataBlock CreateAvatarUpdateBlock(SendAvatarData data)
4268 {
4269 byte[] objectData = new byte[60];
4270 data.Position.ToBytes(objectData, 0);
4271 //data.Velocity.ToBytes(objectData, 12);
4272 //data.Acceleration.ToBytes(objectData, 24);
4273 data.Rotation.ToBytes(objectData, 36);
4274 //data.AngularVelocity.ToBytes(objectData, 48);
4275
4276 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4277
4278 update.Data = Utils.EmptyBytes;
4279 update.ExtraParams = new byte[1];
4280 update.FullID = data.AvatarID;
4281 update.ID = data.AvatarLocalID;
4282 update.Material = (byte)Material.Flesh;
4283 update.MediaURL = Utils.EmptyBytes;
4284 update.NameValue = Utils.StringToBytes("FirstName STRING RW SV " + data.FirstName + "\nLastName STRING RW SV " +
4285 data.LastName + "\nTitle STRING RW SV " + data.GroupTitle);
4286 update.ObjectData = objectData;
4287 update.ParentID = data.ParentID;
4288 update.PathCurve = 16;
4289 update.PathScaleX = 100;
4290 update.PathScaleY = 100;
4291 update.PCode = (byte)PCode.Avatar;
4292 update.ProfileCurve = 1;
4293 update.PSBlock = Utils.EmptyBytes;
4294 update.Scale = Vector3.One;
4295 update.Text = Utils.EmptyBytes;
4296 update.TextColor = new byte[4];
4297 update.TextureAnim = Utils.EmptyBytes;
4298 update.TextureEntry = data.TextureEntry ?? Utils.EmptyBytes;
4299 update.UpdateFlags = 61 + (9 << 8) + (130 << 16) + (16 << 24); // TODO: Replace these numbers with PrimFlags
4300
4301 return update;
4302 }
4303
4304 protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SendPrimitiveData data)
4305 {
4306 byte[] objectData = new byte[60];
4307 data.pos.ToBytes(objectData, 0);
4308 data.vel.ToBytes(objectData, 12);
4309 data.acc.ToBytes(objectData, 24);
4310 data.rotation.ToBytes(objectData, 36);
4311 data.rvel.ToBytes(objectData, 48);
4312
4313 ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock();
4314 update.ClickAction = (byte)data.clickAction;
4315 update.CRC = 0;
4316 update.ExtraParams = data.primShape.ExtraParams ?? Utils.EmptyBytes;
4317 update.FullID = data.objectID;
4318 update.ID = data.localID;
4319 //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated
4320 //update.JointPivot = Vector3.Zero;
4321 //update.JointType = 0;
4322 update.Material = data.material;
4323 update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim
4324 if (data.attachment)
4325 {
4326 update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.AssetId);
4327 update.State = (byte)((data.AttachPoint % 16) * 16 + (data.AttachPoint / 16));
4328 }
4329 else
4330 {
4331 update.NameValue = Utils.EmptyBytes;
4332 update.State = data.primShape.State;
4333 }
4334 update.ObjectData = objectData;
4335 update.ParentID = data.parentID;
4336 update.PathBegin = data.primShape.PathBegin;
4337 update.PathCurve = data.primShape.PathCurve;
4338 update.PathEnd = data.primShape.PathEnd;
4339 update.PathRadiusOffset = data.primShape.PathRadiusOffset;
4340 update.PathRevolutions = data.primShape.PathRevolutions;
4341 update.PathScaleX = data.primShape.PathScaleX;
4342 update.PathScaleY = data.primShape.PathScaleY;
4343 update.PathShearX = data.primShape.PathShearX;
4344 update.PathShearY = data.primShape.PathShearY;
4345 update.PathSkew = data.primShape.PathSkew;
4346 update.PathTaperX = data.primShape.PathTaperX;
4347 update.PathTaperY = data.primShape.PathTaperY;
4348 update.PathTwist = data.primShape.PathTwist;
4349 update.PathTwistBegin = data.primShape.PathTwistBegin;
4350 update.PCode = data.primShape.PCode;
4351 update.ProfileBegin = data.primShape.ProfileBegin;
4352 update.ProfileCurve = data.primShape.ProfileCurve;
4353 update.ProfileEnd = data.primShape.ProfileEnd;
4354 update.ProfileHollow = data.primShape.ProfileHollow;
4355 update.PSBlock = data.particleSystem ?? Utils.EmptyBytes;
4356 update.TextColor = data.color ?? Color4.Black.GetBytes(true);
4357 update.TextureAnim = data.textureanim ?? Utils.EmptyBytes;
4358 update.TextureEntry = data.primShape.TextureEntry ?? Utils.EmptyBytes;
4359 update.Scale = data.primShape.Scale;
4360 update.Text = Util.StringToBytes256(data.text);
4361 update.UpdateFlags = (uint)data.flags;
4362
4363 if (data.SoundId != UUID.Zero)
4364 {
4365 update.Sound = data.SoundId;
4366 update.OwnerID = data.ownerID;
4367 update.Gain = (float)data.SoundVolume;
4368 update.Radius = (float)data.SoundRadius;
4369 update.Flags = data.SoundFlags;
4370 }
4371
4372 switch ((PCode)data.primShape.PCode)
4373 {
4374 case PCode.Grass:
4375 case PCode.Tree:
4376 case PCode.NewTree:
4377 update.Data = new byte[] { data.primShape.State };
4378 break;
4379 default:
4380 // TODO: Support ScratchPad
4381 //if (prim.ScratchPad != null)
4382 //{
4383 // update.Data = new byte[prim.ScratchPad.Length];
4384 // Buffer.BlockCopy(prim.ScratchPad, 0, update.Data, 0, update.Data.Length);
4385 //}
4386 //else
4387 //{
4388 // update.Data = Utils.EmptyBytes;
4389 //}
4390 update.Data = Utils.EmptyBytes;
4391 break;
4392 }
4393
4394 return update;
4540 } 4395 }
4541 4396
4542 public void SendNameReply(UUID profileId, string firstname, string lastname) 4397 public void SendNameReply(UUID profileId, string firstname, string lastname)
@@ -4546,8 +4401,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4546 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1]; 4401 packet.UUIDNameBlock = new UUIDNameReplyPacket.UUIDNameBlockBlock[1];
4547 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock(); 4402 packet.UUIDNameBlock[0] = new UUIDNameReplyPacket.UUIDNameBlockBlock();
4548 packet.UUIDNameBlock[0].ID = profileId; 4403 packet.UUIDNameBlock[0].ID = profileId;
4549 packet.UUIDNameBlock[0].FirstName = Utils.StringToBytes(firstname); 4404 packet.UUIDNameBlock[0].FirstName = Util.StringToBytes256(firstname);
4550 packet.UUIDNameBlock[0].LastName = Utils.StringToBytes(lastname); 4405 packet.UUIDNameBlock[0].LastName = Util.StringToBytes256(lastname);
4551 4406
4552 OutPacket(packet, ThrottleOutPacketType.Task); 4407 OutPacket(packet, ThrottleOutPacketType.Task);
4553 } 4408 }
@@ -4743,8 +4598,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP
4743 scriptQuestion.Data.TaskID = taskID; 4598 scriptQuestion.Data.TaskID = taskID;
4744 scriptQuestion.Data.ItemID = itemID; 4599 scriptQuestion.Data.ItemID = itemID;
4745 scriptQuestion.Data.Questions = question; 4600 scriptQuestion.Data.Questions = question;
4746 scriptQuestion.Data.ObjectName = Utils.StringToBytes(taskName); 4601 scriptQuestion.Data.ObjectName = Util.StringToBytes256(taskName);
4747 scriptQuestion.Data.ObjectOwner = Utils.StringToBytes(ownerName); 4602 scriptQuestion.Data.ObjectOwner = Util.StringToBytes256(ownerName);
4748 4603
4749 OutPacket(scriptQuestion, ThrottleOutPacketType.Task); 4604 OutPacket(scriptQuestion, ThrottleOutPacketType.Task);
4750 } 4605 }
@@ -5138,7 +4993,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
5138 if (m_moneyBalance + debit >= 0) 4993 if (m_moneyBalance + debit >= 0)
5139 { 4994 {
5140 m_moneyBalance += debit; 4995 m_moneyBalance += debit;
5141 SendMoneyBalance(UUID.Zero, true, Utils.StringToBytes("Poof Poof!"), m_moneyBalance); 4996 SendMoneyBalance(UUID.Zero, true, Util.StringToBytes256("Poof Poof!"), m_moneyBalance);
5142 return true; 4997 return true;
5143 } 4998 }
5144 return false; 4999 return false;
@@ -8736,19 +8591,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP
8736 8591
8737 #endregion 8592 #endregion
8738 8593
8594 case PacketType.AgentFOV:
8595 AgentFOVPacket fovPacket = (AgentFOVPacket)Pack;
8739 8596
8740 #region unimplemented handlers 8597 if (fovPacket.FOVBlock.GenCounter > m_agentFOVCounter)
8741 8598 {
8742 case PacketType.StartPingCheck: 8599 m_agentFOVCounter = fovPacket.FOVBlock.GenCounter;
8743 StartPingCheckPacket pingStart = (StartPingCheckPacket)Pack; 8600 AgentFOV handlerAgentFOV = OnAgentFOV;
8744 CompletePingCheckPacket pingComplete = new CompletePingCheckPacket(); 8601 if (handlerAgentFOV != null)
8745 pingComplete.PingID.PingID = pingStart.PingID.PingID; 8602 {
8746 m_udpServer.SendPacket(m_udpClient, pingComplete, ThrottleOutPacketType.Unknown, false); 8603 handlerAgentFOV(this, fovPacket.FOVBlock.VerticalAngle);
8604 }
8605 }
8747 break; 8606 break;
8748 8607
8749 case PacketType.CompletePingCheck: 8608 #region unimplemented handlers
8750 // TODO: Do stats tracking or something with these?
8751 break;
8752 8609
8753 case PacketType.ViewerStats: 8610 case PacketType.ViewerStats:
8754 // TODO: handle this packet 8611 // TODO: handle this packet
@@ -9080,7 +8937,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9080 new GroupTitlesReplyPacket.GroupDataBlock(); 8937 new GroupTitlesReplyPacket.GroupDataBlock();
9081 8938
9082 groupTitlesReply.GroupData[i].Title = 8939 groupTitlesReply.GroupData[i].Title =
9083 Utils.StringToBytes(d.Name); 8940 Util.StringToBytes256(d.Name);
9084 groupTitlesReply.GroupData[i].RoleID = 8941 groupTitlesReply.GroupData[i].RoleID =
9085 d.UUID; 8942 d.UUID;
9086 groupTitlesReply.GroupData[i].Selected = 8943 groupTitlesReply.GroupData[i].Selected =
@@ -9117,10 +8974,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9117 groupProfileRequest.GroupData.GroupID); 8974 groupProfileRequest.GroupData.GroupID);
9118 8975
9119 groupProfileReply.GroupData.GroupID = d.GroupID; 8976 groupProfileReply.GroupData.GroupID = d.GroupID;
9120 groupProfileReply.GroupData.Name = Utils.StringToBytes(d.Name); 8977 groupProfileReply.GroupData.Name = Util.StringToBytes256(d.Name);
9121 groupProfileReply.GroupData.Charter = Utils.StringToBytes(d.Charter); 8978 groupProfileReply.GroupData.Charter = Util.StringToBytes1024(d.Charter);
9122 groupProfileReply.GroupData.ShowInList = d.ShowInList; 8979 groupProfileReply.GroupData.ShowInList = d.ShowInList;
9123 groupProfileReply.GroupData.MemberTitle = Utils.StringToBytes(d.MemberTitle); 8980 groupProfileReply.GroupData.MemberTitle = Util.StringToBytes256(d.MemberTitle);
9124 groupProfileReply.GroupData.PowersMask = d.PowersMask; 8981 groupProfileReply.GroupData.PowersMask = d.PowersMask;
9125 groupProfileReply.GroupData.InsigniaID = d.InsigniaID; 8982 groupProfileReply.GroupData.InsigniaID = d.InsigniaID;
9126 groupProfileReply.GroupData.FounderID = d.FounderID; 8983 groupProfileReply.GroupData.FounderID = d.FounderID;
@@ -9192,11 +9049,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9192 groupMembersReply.MemberData[i].Contribution = 9049 groupMembersReply.MemberData[i].Contribution =
9193 m.Contribution; 9050 m.Contribution;
9194 groupMembersReply.MemberData[i].OnlineStatus = 9051 groupMembersReply.MemberData[i].OnlineStatus =
9195 Utils.StringToBytes(m.OnlineStatus); 9052 Util.StringToBytes256(m.OnlineStatus);
9196 groupMembersReply.MemberData[i].AgentPowers = 9053 groupMembersReply.MemberData[i].AgentPowers =
9197 m.AgentPowers; 9054 m.AgentPowers;
9198 groupMembersReply.MemberData[i].Title = 9055 groupMembersReply.MemberData[i].Title =
9199 Utils.StringToBytes(m.Title); 9056 Util.StringToBytes256(m.Title);
9200 groupMembersReply.MemberData[i].IsOwner = 9057 groupMembersReply.MemberData[i].IsOwner =
9201 m.IsOwner; 9058 m.IsOwner;
9202 } 9059 }
@@ -9257,11 +9114,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9257 groupRolesReply.RoleData[i].RoleID = 9114 groupRolesReply.RoleData[i].RoleID =
9258 d.RoleID; 9115 d.RoleID;
9259 groupRolesReply.RoleData[i].Name = 9116 groupRolesReply.RoleData[i].Name =
9260 Utils.StringToBytes(d.Name); 9117 Util.StringToBytes256(d.Name);
9261 groupRolesReply.RoleData[i].Title = 9118 groupRolesReply.RoleData[i].Title =
9262 Utils.StringToBytes(d.Title); 9119 Util.StringToBytes256(d.Title);
9263 groupRolesReply.RoleData[i].Description = 9120 groupRolesReply.RoleData[i].Description =
9264 Utils.StringToBytes(d.Description); 9121 Util.StringToBytes1024(d.Description);
9265 groupRolesReply.RoleData[i].Powers = 9122 groupRolesReply.RoleData[i].Powers =
9266 d.Powers; 9123 d.Powers;
9267 groupRolesReply.RoleData[i].Members = 9124 groupRolesReply.RoleData[i].Members =
@@ -9488,9 +9345,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
9488 groupNoticesListReply.Data[i].Timestamp = 9345 groupNoticesListReply.Data[i].Timestamp =
9489 g.Timestamp; 9346 g.Timestamp;
9490 groupNoticesListReply.Data[i].FromName = 9347 groupNoticesListReply.Data[i].FromName =
9491 Utils.StringToBytes(g.FromName); 9348 Util.StringToBytes256(g.FromName);
9492 groupNoticesListReply.Data[i].Subject = 9349 groupNoticesListReply.Data[i].Subject =
9493 Utils.StringToBytes(g.Subject); 9350 Util.StringToBytes256(g.Subject);
9494 groupNoticesListReply.Data[i].HasAttachment = 9351 groupNoticesListReply.Data[i].HasAttachment =
9495 g.HasAttachment; 9352 g.HasAttachment;
9496 groupNoticesListReply.Data[i].AssetType = 9353 groupNoticesListReply.Data[i].AssetType =
@@ -10089,12 +9946,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10089 byte mediaLoop) 9946 byte mediaLoop)
10090 { 9947 {
10091 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket(); 9948 ParcelMediaUpdatePacket updatePacket = new ParcelMediaUpdatePacket();
10092 updatePacket.DataBlock.MediaURL = Utils.StringToBytes(mediaUrl); 9949 updatePacket.DataBlock.MediaURL = Util.StringToBytes256(mediaUrl);
10093 updatePacket.DataBlock.MediaID = mediaTextureID; 9950 updatePacket.DataBlock.MediaID = mediaTextureID;
10094 updatePacket.DataBlock.MediaAutoScale = autoScale; 9951 updatePacket.DataBlock.MediaAutoScale = autoScale;
10095 9952
10096 updatePacket.DataBlockExtended.MediaType = Utils.StringToBytes(mediaType); 9953 updatePacket.DataBlockExtended.MediaType = Util.StringToBytes256(mediaType);
10097 updatePacket.DataBlockExtended.MediaDesc = Utils.StringToBytes(mediaDesc); 9954 updatePacket.DataBlockExtended.MediaDesc = Util.StringToBytes256(mediaDesc);
10098 updatePacket.DataBlockExtended.MediaWidth = mediaWidth; 9955 updatePacket.DataBlockExtended.MediaWidth = mediaWidth;
10099 updatePacket.DataBlockExtended.MediaHeight = mediaHeight; 9956 updatePacket.DataBlockExtended.MediaHeight = mediaHeight;
10100 updatePacket.DataBlockExtended.MediaLoop = mediaLoop; 9957 updatePacket.DataBlockExtended.MediaLoop = mediaLoop;
@@ -10371,5 +10228,166 @@ namespace OpenSim.Region.ClientStack.LindenUDP
10371 pack.TextureData.TextureID = textureID; 10228 pack.TextureData.TextureID = textureID;
10372 OutPacket(pack, ThrottleOutPacketType.Task); 10229 OutPacket(pack, ThrottleOutPacketType.Task);
10373 } 10230 }
10231
10232 #region PriorityQueue
10233 private class PriorityQueue<TPriority, TValue>
10234 {
10235 internal delegate bool UpdatePriorityHandler(ref TPriority priority, uint local_id);
10236
10237 private MinHeap<MinHeapItem>[] m_heaps = new MinHeap<MinHeapItem>[1];
10238 private Dictionary<uint, LookupItem> m_lookupTable;
10239 private Comparison<TPriority> m_comparison;
10240 private object m_syncRoot = new object();
10241
10242 internal PriorityQueue() :
10243 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, Comparer<TPriority>.Default) { }
10244 internal PriorityQueue(int capacity) :
10245 this(capacity, Comparer<TPriority>.Default) { }
10246 internal PriorityQueue(IComparer<TPriority> comparer) :
10247 this(new Comparison<TPriority>(comparer.Compare)) { }
10248 internal PriorityQueue(Comparison<TPriority> comparison) :
10249 this(MinHeap<MinHeapItem>.DEFAULT_CAPACITY, comparison) { }
10250 internal PriorityQueue(int capacity, IComparer<TPriority> comparer) :
10251 this(capacity, new Comparison<TPriority>(comparer.Compare)) { }
10252 internal PriorityQueue(int capacity, Comparison<TPriority> comparison)
10253 {
10254 m_lookupTable = new Dictionary<uint, LookupItem>(capacity);
10255
10256 for (int i = 0; i < m_heaps.Length; ++i)
10257 m_heaps[i] = new MinHeap<MinHeapItem>(capacity);
10258 this.m_comparison = comparison;
10259 }
10260
10261 internal object SyncRoot { get { return this.m_syncRoot; } }
10262 internal int Count
10263 {
10264 get
10265 {
10266 int count = 0;
10267 for (int i = 0; i < m_heaps.Length; ++i)
10268 count = m_heaps[i].Count;
10269 return count;
10270 }
10271 }
10272
10273 internal bool Enqueue(TPriority priority, TValue value, uint local_id)
10274 {
10275 LookupItem item;
10276
10277 if (m_lookupTable.TryGetValue(local_id, out item))
10278 {
10279 item.Heap[item.Handle] = new MinHeapItem(priority, value, local_id, this.m_comparison);
10280 return false;
10281 }
10282 else
10283 {
10284 item.Heap = m_heaps[0];
10285 item.Heap.Add(new MinHeapItem(priority, value, local_id, this.m_comparison), ref item.Handle);
10286 m_lookupTable.Add(local_id, item);
10287 return true;
10288 }
10289 }
10290
10291 internal TValue Peek()
10292 {
10293 for (int i = 0; i < m_heaps.Length; ++i)
10294 if (m_heaps[i].Count > 0)
10295 return m_heaps[i].Min().Value;
10296 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10297 }
10298
10299 internal TValue Dequeue()
10300 {
10301 for (int i = 0; i < m_heaps.Length; ++i)
10302 {
10303 if (m_heaps[i].Count > 0)
10304 {
10305 MinHeapItem item = m_heaps[i].RemoveMin();
10306 m_lookupTable.Remove(item.LocalID);
10307 return item.Value;
10308 }
10309 }
10310 throw new InvalidOperationException(string.Format("The {0} is empty", this.GetType().ToString()));
10311 }
10312
10313 internal void Reprioritize(UpdatePriorityHandler handler)
10314 {
10315 MinHeapItem item;
10316 TPriority priority;
10317
10318 foreach (LookupItem lookup in new List<LookupItem>(this.m_lookupTable.Values))
10319 {
10320 if (lookup.Heap.TryGetValue(lookup.Handle, out item))
10321 {
10322 priority = item.Priority;
10323 if (handler(ref priority, item.LocalID))
10324 {
10325 if (lookup.Heap.ContainsHandle(lookup.Handle))
10326 lookup.Heap[lookup.Handle] =
10327 new MinHeapItem(priority, item.Value, item.LocalID);
10328 }
10329 else
10330 {
10331 m_log.Warn("[LLCLIENTVIEW]: UpdatePriorityHandler returned false, dropping update");
10332 lookup.Heap.Remove(lookup.Handle);
10333 this.m_lookupTable.Remove(item.LocalID);
10334 }
10335 }
10336 }
10337 }
10338
10339 #region MinHeapItem
10340 private struct MinHeapItem : IComparable<MinHeapItem>
10341 {
10342 private TPriority priority;
10343 private TValue value;
10344 private uint local_id;
10345 private Comparison<TPriority> comparison;
10346
10347 internal MinHeapItem(TPriority priority, TValue value, uint local_id) :
10348 this(priority, value, local_id, Comparer<TPriority>.Default) { }
10349 internal MinHeapItem(TPriority priority, TValue value, uint local_id, IComparer<TPriority> comparer) :
10350 this(priority, value, local_id, new Comparison<TPriority>(comparer.Compare)) { }
10351 internal MinHeapItem(TPriority priority, TValue value, uint local_id, Comparison<TPriority> comparison)
10352 {
10353 this.priority = priority;
10354 this.value = value;
10355 this.local_id = local_id;
10356 this.comparison = comparison;
10357 }
10358
10359 internal TPriority Priority { get { return this.priority; } }
10360 internal TValue Value { get { return this.value; } }
10361 internal uint LocalID { get { return this.local_id; } }
10362
10363 public override string ToString()
10364 {
10365 StringBuilder sb = new StringBuilder();
10366 sb.Append("[");
10367 if (this.priority != null)
10368 sb.Append(this.priority.ToString());
10369 sb.Append(",");
10370 if (this.value != null)
10371 sb.Append(this.value.ToString());
10372 sb.Append("]");
10373 return sb.ToString();
10374 }
10375
10376 public int CompareTo(MinHeapItem other)
10377 {
10378 return this.comparison(this.priority, other.priority);
10379 }
10380 }
10381 #endregion
10382
10383 #region LookupItem
10384 private struct LookupItem {
10385 internal MinHeap<MinHeapItem> Heap;
10386 internal IHandle Handle;
10387 }
10388 #endregion
10389 }
10390 #endregion
10391
10374 } 10392 }
10375} 10393}
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
index d25bf95..938cf50 100644
--- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
+++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs
@@ -51,7 +51,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
51 51
52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 52 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
53 private bool m_shuttingdown; 53 private bool m_shuttingdown;
54 private long m_lastloopprocessed;
55 private AssetBase m_missingImage; 54 private AssetBase m_missingImage;
56 private LLClientView m_client; //Client we're assigned to 55 private LLClientView m_client; //Client we're assigned to
57 private IAssetService m_assetCache; //Asset Cache 56 private IAssetService m_assetCache; //Asset Cache
@@ -169,7 +168,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP
169 168
170 public bool ProcessImageQueue(int packetsToSend) 169 public bool ProcessImageQueue(int packetsToSend)
171 { 170 {
172 m_lastloopprocessed = DateTime.Now.Ticks;
173 int packetsSent = 0; 171 int packetsSent = 0;
174 172
175 while (packetsSent < packetsToSend) 173 while (packetsSent < packetsToSend)
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs
index 4eee6b6..4b6a358 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
@@ -493,8 +506,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP
493 /// for</param> 506 /// for</param>
494 private void BeginFireQueueEmpty(int throttleIndex) 507 private void BeginFireQueueEmpty(int throttleIndex)
495 { 508 {
496 if (!m_onQueueEmptyRunning[throttleIndex]) 509 // Unknown is -1 and Resend is 0. Make sure we are only firing the
497 Util.FireAndForget(FireQueueEmpty, throttleIndex); 510 // callback for categories other than those
511 if (throttleIndex > 0)
512 {
513 if (!m_onQueueEmptyRunning[throttleIndex])
514 Util.FireAndForget(FireQueueEmpty, throttleIndex);
515 }
498 } 516 }
499 517
500 /// <summary> 518 /// <summary>
diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPServer.cs
index 545a0bc..74175d0 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>
@@ -104,7 +107,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
104 /// <summary>Manages authentication for agent circuits</summary> 107 /// <summary>Manages authentication for agent circuits</summary>
105 private AgentCircuitManager m_circuitManager; 108 private AgentCircuitManager m_circuitManager;
106 /// <summary>Reference to the scene this UDP server is attached to</summary> 109 /// <summary>Reference to the scene this UDP server is attached to</summary>
107 private IScene m_scene; 110 private Scene m_scene;
108 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary> 111 /// <summary>The X/Y coordinates of the scene this UDP server is attached to</summary>
109 private Location m_location; 112 private Location m_location;
110 /// <summary>The measured resolution of Environment.TickCount</summary> 113 /// <summary>The measured resolution of Environment.TickCount</summary>
@@ -181,15 +184,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP
181 184
182 public void AddScene(IScene scene) 185 public void AddScene(IScene scene)
183 { 186 {
184 if (m_scene == null) 187 if (m_scene != null)
185 { 188 {
186 m_scene = scene; 189 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene");
187 m_location = new Location(m_scene.RegionInfo.RegionHandle); 190 return;
188 } 191 }
189 else 192
193 if (!(scene is Scene))
190 { 194 {
191 m_log.Error("[LLUDPSERVER]: AddScene() called on an LLUDPServer that already has a scene"); 195 m_log.Error("[LLUDPSERVER]: AddScene() called with an unrecognized scene type " + scene.GetType());
196 return;
192 } 197 }
198
199 m_scene = (Scene)scene;
200 m_location = new Location(m_scene.RegionInfo.RegionHandle);
193 } 201 }
194 202
195 public bool HandlesRegion(Location x) 203 public bool HandlesRegion(Location x)
@@ -267,38 +275,54 @@ namespace OpenSim.Region.ClientStack.LindenUDP
267 { 275 {
268 int dataLength = data.Length; 276 int dataLength = data.Length;
269 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0; 277 bool doZerocode = (data[0] & Helpers.MSG_ZEROCODED) != 0;
278 bool doCopy = true;
270 279
271 // Frequency analysis of outgoing packet sizes shows a large clump of packets at each end of the spectrum. 280 // 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 281 // 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 282 // 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 283 // to accomodate for both common scenarios and provide ample room for ACK appending in both
275 int bufferSize = (dataLength > 180) ? Packet.MTU : 200; 284 int bufferSize = (dataLength > 180) ? LLUDPServer.MTU : 200;
276 285
277 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize); 286 UDPPacketBuffer buffer = new UDPPacketBuffer(udpClient.RemoteEndPoint, bufferSize);
278 287
279 // Zerocode if needed 288 // Zerocode if needed
280 if (doZerocode) 289 if (doZerocode)
281 { 290 {
282 try { dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data); } 291 try
292 {
293 dataLength = Helpers.ZeroEncode(data, dataLength, buffer.Data);
294 doCopy = false;
295 }
283 catch (IndexOutOfRangeException) 296 catch (IndexOutOfRangeException)
284 { 297 {
285 // The packet grew larger than the bufferSize while zerocoding. 298 // The packet grew larger than the bufferSize while zerocoding.
286 // Remove the MSG_ZEROCODED flag and send the unencoded data 299 // Remove the MSG_ZEROCODED flag and send the unencoded data
287 // instead 300 // instead
288 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". Removing MSG_ZEROCODED flag"); 301 m_log.Debug("[LLUDPSERVER]: Packet exceeded buffer size during zerocoding for " + type + ". DataLength=" + dataLength +
302 " and BufferLength=" + buffer.Data.Length + ". Removing MSG_ZEROCODED flag");
289 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED); 303 data[0] = (byte)(data[0] & ~Helpers.MSG_ZEROCODED);
290 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
291 } 304 }
292 } 305 }
293 else 306
307 // If the packet data wasn't already copied during zerocoding, copy it now
308 if (doCopy)
294 { 309 {
295 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength); 310 if (dataLength <= buffer.Data.Length)
311 {
312 Buffer.BlockCopy(data, 0, buffer.Data, 0, dataLength);
313 }
314 else
315 {
316 m_log.Error("[LLUDPSERVER]: Packet exceeded buffer size! This could be an indication of packet assembly not obeying the MTU. Type=" +
317 type + ", DataLength=" + dataLength + ", BufferLength=" + buffer.Data.Length + ". Dropping packet");
318 return;
319 }
296 } 320 }
321
297 buffer.DataLength = dataLength; 322 buffer.DataLength = dataLength;
298 323
299 #region Queue or Send 324 #region Queue or Send
300 325
301 // Look up the UDPClient this is going to
302 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category); 326 OutgoingPacket outgoingPacket = new OutgoingPacket(udpClient, buffer, category);
303 327
304 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket)) 328 if (!outgoingPacket.Client.EnqueueOutgoing(outgoingPacket))
@@ -513,7 +537,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
513 IClientAPI client; 537 IClientAPI client;
514 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView)) 538 if (!m_scene.ClientManager.TryGetValue(address, out client) || !(client is LLClientView))
515 { 539 {
516 m_log.Warn("[LLUDPSERVER]: Received a " + packet.Type + " packet from an unrecognized source: " + address + 540 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"); 541 " in " + m_scene.RegionInfo.RegionName + ", currently tracking " + m_scene.ClientManager.Count + " clients");
518 return; 542 return;
519 } 543 }
@@ -553,6 +577,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP
553 for (int i = 0; i < ackPacket.Packets.Length; i++) 577 for (int i = 0; i < ackPacket.Packets.Length; i++)
554 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent); 578 AcknowledgePacket(udpClient, ackPacket.Packets[i].ID, now, packet.Header.Resent);
555 } 579 }
580
581 // We don't need to do anything else with PacketAck packets
582 return;
556 } 583 }
557 584
558 #endregion ACK Receiving 585 #endregion ACK Receiving
@@ -560,20 +587,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP
560 #region ACK Sending 587 #region ACK Sending
561 588
562 if (packet.Header.Reliable) 589 if (packet.Header.Reliable)
590 {
563 udpClient.PendingAcks.Enqueue(packet.Header.Sequence); 591 udpClient.PendingAcks.Enqueue(packet.Header.Sequence);
564 592
565 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, 593 // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out,
566 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove 594 // add the current received bytes to it, test if 2*MTU bytes have been sent, if so remove
567 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to 595 // 2*MTU bytes from the value and send ACKs, and finally add the local value back to
568 // client.BytesSinceLastACK. Lockless thread safety 596 // client.BytesSinceLastACK. Lockless thread safety
569 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0); 597 int bytesSinceLastACK = Interlocked.Exchange(ref udpClient.BytesSinceLastACK, 0);
570 bytesSinceLastACK += buffer.DataLength; 598 bytesSinceLastACK += buffer.DataLength;
571 if (bytesSinceLastACK > Packet.MTU * 2) 599 if (bytesSinceLastACK > LLUDPServer.MTU * 2)
572 { 600 {
573 bytesSinceLastACK -= Packet.MTU * 2; 601 bytesSinceLastACK -= LLUDPServer.MTU * 2;
574 SendAcks(udpClient); 602 SendAcks(udpClient);
603 }
604 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
575 } 605 }
576 Interlocked.Add(ref udpClient.BytesSinceLastACK, bytesSinceLastACK);
577 606
578 #endregion ACK Sending 607 #endregion ACK Sending
579 608
@@ -593,12 +622,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP
593 622
594 #endregion Incoming Packet Accounting 623 #endregion Incoming Packet Accounting
595 624
596 // Don't bother clogging up the queue with PacketAck packets that are already handled here 625 #region Ping Check Handling
597 if (packet.Type != PacketType.PacketAck) 626
627 if (packet.Type == PacketType.StartPingCheck)
628 {
629 // We don't need to do anything else with ping checks
630 StartPingCheckPacket startPing = (StartPingCheckPacket)packet;
631
632 CompletePingCheckPacket completePing = new CompletePingCheckPacket();
633 completePing.PingID.PingID = startPing.PingID.PingID;
634 SendPacket(udpClient, completePing, ThrottleOutPacketType.Unknown, false);
635 return;
636 }
637 else if (packet.Type == PacketType.CompletePingCheck)
598 { 638 {
599 // Inbox insertion 639 // We don't currently track client ping times
600 packetInbox.Enqueue(new IncomingPacket(udpClient, packet)); 640 return;
601 } 641 }
642
643 #endregion Ping Check Handling
644
645 // Inbox insertion
646 packetInbox.Enqueue(new IncomingPacket(udpClient, packet));
602 } 647 }
603 648
604 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent) 649 protected override void PacketSent(UDPPacketBuffer buffer, int bytesSent)
@@ -693,12 +738,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP
693 // on to en-US to avoid number parsing issues 738 // on to en-US to avoid number parsing issues
694 Culture.SetCurrentCulture(); 739 Culture.SetCurrentCulture();
695 740
696 IncomingPacket incomingPacket = null;
697
698 while (base.IsRunning) 741 while (base.IsRunning)
699 { 742 {
700 if (packetInbox.Dequeue(100, ref incomingPacket)) 743 IncomingPacket incomingPacket = null;
701 Util.FireAndForget(ProcessInPacket, incomingPacket); 744
745 try
746 {
747 if (packetInbox.Dequeue(100, ref incomingPacket))
748 Util.FireAndForget(ProcessInPacket, incomingPacket);
749 }
750 catch (Exception ex)
751 {
752 m_log.Error("[LLUDPSERVER]: Error in the incoming packet handler loop: " + ex.Message, ex);
753 }
702 } 754 }
703 755
704 if (packetInbox.Count > 0) 756 if (packetInbox.Count > 0)
@@ -747,7 +799,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP
747 elapsed500MS = 0; 799 elapsed500MS = 0;
748 } 800 }
749 801
750 m_scene.ClientManager.ForEach( 802 m_scene.ClientManager.ForEachSync(
751 delegate(IClientAPI client) 803 delegate(IClientAPI client)
752 { 804 {
753 if (client is LLClientView) 805 if (client is LLClientView)
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..53c64cb 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -147,9 +147,10 @@ namespace OpenSim.Region.CoreModules.World.Land
147 client.OnParcelDwellRequest += ClientOnParcelDwellRequest; 147 client.OnParcelDwellRequest += ClientOnParcelDwellRequest;
148 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup; 148 client.OnParcelDeedToGroup += ClientOnParcelDeedToGroup;
149 149
150 if (m_scene.Entities.ContainsKey(client.AgentId)) 150 EntityBase presenceEntity;
151 if (m_scene.Entities.TryGetValue(client.AgentId, out presenceEntity) && presenceEntity is ScenePresence)
151 { 152 {
152 SendLandUpdate((ScenePresence)m_scene.Entities[client.AgentId], true); 153 SendLandUpdate((ScenePresence)presenceEntity, true);
153 SendParcelOverlay(client); 154 SendParcelOverlay(client);
154 } 155 }
155 } 156 }
@@ -1061,7 +1062,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1061 { 1062 {
1062 land.LandData.OwnerID = ownerID; 1063 land.LandData.OwnerID = ownerID;
1063 1064
1064 m_scene.Broadcast(SendParcelOverlay); 1065 m_scene.ForEachClient(SendParcelOverlay);
1065 land.SendLandUpdateToClient(remote_client); 1066 land.SendLandUpdateToClient(remote_client);
1066 } 1067 }
1067 } 1068 }
@@ -1083,7 +1084,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1083 land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 1084 land.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
1084 else 1085 else
1085 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; 1086 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1086 m_scene.Broadcast(SendParcelOverlay); 1087 m_scene.ForEachClient(SendParcelOverlay);
1087 land.SendLandUpdateToClient(remote_client); 1088 land.SendLandUpdateToClient(remote_client);
1088 } 1089 }
1089 } 1090 }
@@ -1107,7 +1108,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1107 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID; 1108 land.LandData.OwnerID = m_scene.RegionInfo.MasterAvatarAssignedUUID;
1108 land.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 1109 land.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
1109 land.LandData.IsGroupOwned = false; 1110 land.LandData.IsGroupOwned = false;
1110 m_scene.Broadcast(SendParcelOverlay); 1111 m_scene.ForEachClient(SendParcelOverlay);
1111 land.SendLandUpdateToClient(remote_client); 1112 land.SendLandUpdateToClient(remote_client);
1112 } 1113 }
1113 } 1114 }
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index b9b7da5..bfe85f1 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -139,10 +139,8 @@ namespace OpenSim.Region.CoreModules.World.Land
139 } 139 }
140 else 140 else
141 { 141 {
142 //Normal Calculations 142 // Normal Calculations
143 return Convert.ToInt32( 143 return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.objectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus);
144 Math.Round((Convert.ToDecimal(LandData.Area) / Convert.ToDecimal(65536)) * m_scene.objectCapacity *
145 Convert.ToDecimal(m_scene.RegionInfo.RegionSettings.ObjectBonus))); ;
146 } 144 }
147 } 145 }
148 public int GetSimulatorMaxPrimCount(ILandObject thisObject) 146 public int GetSimulatorMaxPrimCount(ILandObject thisObject)
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..5a5fcfe 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,15 @@ 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 { 527 {
540 } 528 }
541 public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, 529
542 Vector3 position, Quaternion rotation, Vector3 velocity, 530 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
543 Vector3 rotationalvelocity, byte state, UUID AssetId,
544 UUID ownerID, int attachPoint)
545 { 531 {
546 } 532 }
547 533
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/EntityManager.cs b/OpenSim/Region/Framework/Scenes/EntityManager.cs
index 0ceef39..099fcce 100644
--- a/OpenSim/Region/Framework/Scenes/EntityManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EntityManager.cs
@@ -93,40 +93,31 @@ namespace OpenSim.Region.Framework.Scenes
93 { 93 {
94 get 94 get
95 { 95 {
96 lock (m_lock) 96 return m_eb_uuid.Count;
97 {
98 return m_eb_uuid.Count;
99 }
100 } 97 }
101 } 98 }
102 99
103 public bool ContainsKey(UUID id) 100 public bool ContainsKey(UUID id)
104 { 101 {
105 lock (m_lock) 102 try
106 { 103 {
107 try 104 return m_eb_uuid.ContainsKey(id);
108 { 105 }
109 return m_eb_uuid.ContainsKey(id); 106 catch
110 } 107 {
111 catch 108 return false;
112 {
113 return false;
114 }
115 } 109 }
116 } 110 }
117 111
118 public bool ContainsKey(uint localID) 112 public bool ContainsKey(uint localID)
119 { 113 {
120 lock (m_lock) 114 try
121 { 115 {
122 try 116 return m_eb_localID.ContainsKey(localID);
123 { 117 }
124 return m_eb_localID.ContainsKey(localID); 118 catch
125 } 119 {
126 catch 120 return false;
127 {
128 return false;
129 }
130 } 121 }
131 } 122 }
132 123
@@ -136,7 +127,11 @@ namespace OpenSim.Region.Framework.Scenes
136 { 127 {
137 try 128 try
138 { 129 {
139 bool a = m_eb_uuid.Remove(m_eb_localID[localID].UUID); 130 bool a = false;
131 EntityBase entity;
132 if (m_eb_localID.TryGetValue(localID, out entity))
133 a = m_eb_uuid.Remove(entity.UUID);
134
140 bool b = m_eb_localID.Remove(localID); 135 bool b = m_eb_localID.Remove(localID);
141 return a && b; 136 return a && b;
142 } 137 }
@@ -154,7 +149,11 @@ namespace OpenSim.Region.Framework.Scenes
154 { 149 {
155 try 150 try
156 { 151 {
157 bool a = m_eb_localID.Remove(m_eb_uuid[id].LocalId); 152 bool a = false;
153 EntityBase entity;
154 if (m_eb_uuid.TryGetValue(id, out entity))
155 a = m_eb_localID.Remove(entity.LocalId);
156
158 bool b = m_eb_uuid.Remove(id); 157 bool b = m_eb_uuid.Remove(id);
159 return a && b; 158 return a && b;
160 } 159 }
@@ -206,14 +205,11 @@ namespace OpenSim.Region.Framework.Scenes
206 { 205 {
207 lock (m_lock) 206 lock (m_lock)
208 { 207 {
209 try 208 EntityBase entity;
210 { 209 if (m_eb_uuid.TryGetValue(id, out entity))
211 return m_eb_uuid[id]; 210 return entity;
212 } 211 else
213 catch
214 {
215 return null; 212 return null;
216 }
217 } 213 }
218 } 214 }
219 set 215 set
@@ -228,14 +224,11 @@ namespace OpenSim.Region.Framework.Scenes
228 { 224 {
229 lock (m_lock) 225 lock (m_lock)
230 { 226 {
231 try 227 EntityBase entity;
232 { 228 if (m_eb_localID.TryGetValue(localID, out entity))
233 return m_eb_localID[localID]; 229 return entity;
234 } 230 else
235 catch
236 {
237 return null; 231 return null;
238 }
239 } 232 }
240 } 233 }
241 set 234 set
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index c44c4c7..c2b9e73 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -2351,12 +2351,6 @@ namespace OpenSim.Region.Framework.Scenes
2351 item = InventoryService.GetItem(item); 2351 item = InventoryService.GetItem(item);
2352 2352
2353 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); 2353 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/);
2354 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>();
2355 if (ava != null)
2356 {
2357 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2358 }
2359
2360 } 2354 }
2361 return att.UUID; 2355 return att.UUID;
2362 } 2356 }
@@ -2402,12 +2396,6 @@ namespace OpenSim.Region.Framework.Scenes
2402 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 2396 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
2403 item = InventoryService.GetItem(item); 2397 item = InventoryService.GetItem(item);
2404 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); 2398 presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/);
2405
2406 if (m_AvatarFactory != null)
2407 {
2408 m_log.InfoFormat("[SCENE INVENTORY]: Saving avatar attachment. AgentID:{0} ItemID:{1} AttachmentPoint:{2}", remoteClient.AgentId, itemID, AttachmentPt);
2409 m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2410 }
2411 } 2399 }
2412 } 2400 }
2413 2401
@@ -2447,12 +2435,13 @@ namespace OpenSim.Region.Framework.Scenes
2447 if (TryGetAvatar(remoteClient.AgentId, out presence)) 2435 if (TryGetAvatar(remoteClient.AgentId, out presence))
2448 { 2436 {
2449 presence.Appearance.DetachAttachment(itemID); 2437 presence.Appearance.DetachAttachment(itemID);
2450 IAvatarFactory ava = RequestModuleInterface<IAvatarFactory>(); 2438
2451 if (ava != null) 2439 // Save avatar attachment information
2440 if (m_AvatarFactory != null)
2452 { 2441 {
2453 ava.UpdateDatabase(remoteClient.AgentId, presence.Appearance); 2442 m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", ItemID: " + itemID);
2443 m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
2454 } 2444 }
2455
2456 } 2445 }
2457 2446
2458 m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient); 2447 m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient);
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 151df27..2dbc090 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
@@ -222,6 +228,10 @@ namespace OpenSim.Region.Framework.Scenes
222 protected IXMLRPC m_xmlrpcModule; 228 protected IXMLRPC m_xmlrpcModule;
223 protected IWorldComm m_worldCommModule; 229 protected IWorldComm m_worldCommModule;
224 protected IAvatarFactory m_AvatarFactory; 230 protected IAvatarFactory m_AvatarFactory;
231 public IAvatarFactory AvatarFactory
232 {
233 get { return m_AvatarFactory; }
234 }
225 protected IConfigSource m_config; 235 protected IConfigSource m_config;
226 protected IRegionSerialiserModule m_serialiser; 236 protected IRegionSerialiserModule m_serialiser;
227 protected IInterregionCommsOut m_interregionCommsOut; 237 protected IInterregionCommsOut m_interregionCommsOut;
@@ -269,9 +279,14 @@ namespace OpenSim.Region.Framework.Scenes
269 private volatile bool shuttingdown = false; 279 private volatile bool shuttingdown = false;
270 280
271 private int m_lastUpdate = Environment.TickCount; 281 private int m_lastUpdate = Environment.TickCount;
272 private int m_maxPrimsPerFrame = 200;
273 private bool m_firstHeartbeat = true; 282 private bool m_firstHeartbeat = true;
274 283
284 private UpdatePrioritizationSchemes m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
285 private bool m_reprioritization_enabled = true;
286 private double m_reprioritization_interval = 2000.0;
287 private double m_root_reprioritization_distance = 5.0;
288 private double m_child_reprioritization_distance = 10.0;
289
275 private object m_deleting_scene_object = new object(); 290 private object m_deleting_scene_object = new object();
276 291
277 // the minimum time that must elapse before a changed object will be considered for persisted 292 // the minimum time that must elapse before a changed object will be considered for persisted
@@ -283,6 +298,12 @@ namespace OpenSim.Region.Framework.Scenes
283 298
284 #region Properties 299 #region Properties
285 300
301 public UpdatePrioritizationSchemes UpdatePrioritizationScheme { get { return this.m_update_prioritization_scheme; } }
302 public bool IsReprioritizationEnabled { get { return m_reprioritization_enabled; } }
303 public double ReprioritizationInterval { get { return m_reprioritization_interval; } }
304 public double RootReprioritizationDistance { get { return m_root_reprioritization_distance; } }
305 public double ChildReprioritizationDistance { get { return m_child_reprioritization_distance; } }
306
286 public AgentCircuitManager AuthenticateHandler 307 public AgentCircuitManager AuthenticateHandler
287 { 308 {
288 get { return m_authenticateHandler; } 309 get { return m_authenticateHandler; }
@@ -327,12 +348,6 @@ namespace OpenSim.Region.Framework.Scenes
327 get { return m_sceneGraph.m_syncRoot; } 348 get { return m_sceneGraph.m_syncRoot; }
328 } 349 }
329 350
330 public int MaxPrimsPerFrame
331 {
332 get { return m_maxPrimsPerFrame; }
333 set { m_maxPrimsPerFrame = value; }
334 }
335
336 /// <summary> 351 /// <summary>
337 /// This is for llGetRegionFPS 352 /// This is for llGetRegionFPS
338 /// </summary> 353 /// </summary>
@@ -346,13 +361,6 @@ namespace OpenSim.Region.Framework.Scenes
346 get { return m_defaultScriptEngine; } 361 get { return m_defaultScriptEngine; }
347 } 362 }
348 363
349 // Reference to all of the agents in the scene (root and child)
350 protected Dictionary<UUID, ScenePresence> m_scenePresences
351 {
352 get { return m_sceneGraph.ScenePresences; }
353 set { m_sceneGraph.ScenePresences = value; }
354 }
355
356 public EntityManager Entities 364 public EntityManager Entities
357 { 365 {
358 get { return m_sceneGraph.Entities; } 366 get { return m_sceneGraph.Entities; }
@@ -510,7 +518,6 @@ namespace OpenSim.Region.Framework.Scenes
510 518
511 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "DotNetEngine"); 519 m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "DotNetEngine");
512 520
513 m_maxPrimsPerFrame = startupConfig.GetInt("MaxPrimsPerFrame", 200);
514 IConfig packetConfig = m_config.Configs["PacketPool"]; 521 IConfig packetConfig = m_config.Configs["PacketPool"];
515 if (packetConfig != null) 522 if (packetConfig != null)
516 { 523 {
@@ -519,6 +526,35 @@ namespace OpenSim.Region.Framework.Scenes
519 } 526 }
520 527
521 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); 528 m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl);
529
530 IConfig interest_management_config = m_config.Configs["InterestManagement"];
531 if (interest_management_config != null)
532 {
533 string update_prioritization_scheme = interest_management_config.GetString("UpdatePrioritizationScheme", "Time").Trim().ToLower();
534 switch (update_prioritization_scheme)
535 {
536 case "time":
537 m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
538 break;
539 case "distance":
540 m_update_prioritization_scheme = UpdatePrioritizationSchemes.Distance;
541 break;
542 case "simpleangulardistance":
543 m_update_prioritization_scheme = UpdatePrioritizationSchemes.SimpleAngularDistance;
544 break;
545 default:
546 m_log.Warn("[SCENE]: UpdatePrioritizationScheme was not recognized, setting to default settomg of Time");
547 m_update_prioritization_scheme = UpdatePrioritizationSchemes.Time;
548 break;
549 }
550
551 m_reprioritization_enabled = interest_management_config.GetBoolean("ReprioritizationEnabled", true);
552 m_reprioritization_interval = interest_management_config.GetDouble("ReprioritizationInterval", 5000.0);
553 m_root_reprioritization_distance = interest_management_config.GetDouble("RootReprioritizationDistance", 10.0);
554 m_child_reprioritization_distance = interest_management_config.GetDouble("ChildReprioritizationDistance", 20.0);
555 }
556
557 m_log.Info("[SCENE]: Using the " + m_update_prioritization_scheme + " prioritization scheme");
522 } 558 }
523 catch 559 catch
524 { 560 {
@@ -1144,14 +1180,13 @@ namespace OpenSim.Region.Framework.Scenes
1144 /// <param name="stats">Stats on the Simulator's performance</param> 1180 /// <param name="stats">Stats on the Simulator's performance</param>
1145 private void SendSimStatsPackets(SimStats stats) 1181 private void SendSimStatsPackets(SimStats stats)
1146 { 1182 {
1147 List<ScenePresence> StatSendAgents = GetScenePresences(); 1183 ForEachScenePresence(
1148 foreach (ScenePresence agent in StatSendAgents) 1184 delegate(ScenePresence agent)
1149 {
1150 if (!agent.IsChildAgent)
1151 { 1185 {
1152 agent.ControllingClient.SendSimStats(stats); 1186 if (!agent.IsChildAgent)
1187 agent.ControllingClient.SendSimStats(stats);
1153 } 1188 }
1154 } 1189 );
1155 } 1190 }
1156 1191
1157 /// <summary> 1192 /// <summary>
@@ -1200,15 +1235,6 @@ namespace OpenSim.Region.Framework.Scenes
1200 } 1235 }
1201 1236
1202 /// <summary> 1237 /// <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. 1238 /// Backup the scene. This acts as the main method of the backup thread.
1213 /// </summary> 1239 /// </summary>
1214 /// <returns></returns> 1240 /// <returns></returns>
@@ -3054,17 +3080,13 @@ namespace OpenSim.Region.Framework.Scenes
3054 } 3080 }
3055 3081
3056 m_eventManager.TriggerOnRemovePresence(agentID); 3082 m_eventManager.TriggerOnRemovePresence(agentID);
3057 Broadcast(delegate(IClientAPI client) 3083 ForEachClient(
3058 { 3084 delegate(IClientAPI client)
3059 try 3085 {
3060 { 3086 //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway
3061 client.SendKillObject(avatar.RegionHandle, avatar.LocalId); 3087 try { client.SendKillObject(avatar.RegionHandle, avatar.LocalId); }
3062 } 3088 catch (NullReferenceException) { }
3063 catch (NullReferenceException) 3089 });
3064 {
3065 //We can safely ignore null reference exceptions. It means the avatar are dead and cleaned up anyway.
3066 }
3067 });
3068 3090
3069 ForEachScenePresence( 3091 ForEachScenePresence(
3070 delegate(ScenePresence presence) { presence.CoarseLocationChange(); }); 3092 delegate(ScenePresence presence) { presence.CoarseLocationChange(); });
@@ -3149,7 +3171,7 @@ namespace OpenSim.Region.Framework.Scenes
3149 return; 3171 return;
3150 } 3172 }
3151 } 3173 }
3152 Broadcast(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); }); 3174 ForEachClient(delegate(IClientAPI client) { client.SendKillObject(m_regionHandle, localID); });
3153 } 3175 }
3154 3176
3155 #endregion 3177 #endregion
@@ -3475,10 +3497,8 @@ namespace OpenSim.Region.Framework.Scenes
3475 { 3497 {
3476 ScenePresence presence; 3498 ScenePresence presence;
3477 3499
3478 lock (m_scenePresences) 3500 lock (m_sceneGraph.ScenePresences)
3479 { 3501 m_sceneGraph.ScenePresences.TryGetValue(agentID, out presence);
3480 m_scenePresences.TryGetValue(agentID, out presence);
3481 }
3482 3502
3483 if (presence != null) 3503 if (presence != null)
3484 { 3504 {
@@ -3688,12 +3708,9 @@ namespace OpenSim.Region.Framework.Scenes
3688 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, 3708 public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position,
3689 Vector3 lookAt, uint teleportFlags) 3709 Vector3 lookAt, uint teleportFlags)
3690 { 3710 {
3691 ScenePresence sp = null; 3711 ScenePresence sp;
3692 lock (m_scenePresences) 3712 lock (m_sceneGraph.ScenePresences)
3693 { 3713 m_sceneGraph.ScenePresences.TryGetValue(remoteClient.AgentId, out sp);
3694 if (m_scenePresences.ContainsKey(remoteClient.AgentId))
3695 sp = m_scenePresences[remoteClient.AgentId];
3696 }
3697 3714
3698 if (sp != null) 3715 if (sp != null)
3699 { 3716 {
@@ -4142,7 +4159,7 @@ namespace OpenSim.Region.Framework.Scenes
4142 public void ForEachScenePresence(Action<ScenePresence> action) 4159 public void ForEachScenePresence(Action<ScenePresence> action)
4143 { 4160 {
4144 // We don't want to try to send messages if there are no avatars. 4161 // We don't want to try to send messages if there are no avatars.
4145 if (m_scenePresences != null) 4162 if (m_sceneGraph != null && m_sceneGraph.ScenePresences != null)
4146 { 4163 {
4147 try 4164 try
4148 { 4165 {
@@ -4222,7 +4239,7 @@ namespace OpenSim.Region.Framework.Scenes
4222 4239
4223 public void ForEachClient(Action<IClientAPI> action) 4240 public void ForEachClient(Action<IClientAPI> action)
4224 { 4241 {
4225 m_sceneGraph.ForEachClient(action); 4242 ClientManager.ForEach(action);
4226 } 4243 }
4227 4244
4228 public void ForEachSOG(Action<SceneObjectGroup> action) 4245 public void ForEachSOG(Action<SceneObjectGroup> action)
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 9cd2247..e51f6ef 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -467,7 +467,6 @@ namespace OpenSim.Region.Framework.Scenes
467 protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) 467 protected internal void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent)
468 { 468 {
469 // If we can't take it, we can't attach it! 469 // If we can't take it, we can't attach it!
470 //
471 SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID); 470 SceneObjectPart part = m_parentScene.GetSceneObjectPart(objectLocalID);
472 if (part == null) 471 if (part == null)
473 return; 472 return;
@@ -477,9 +476,16 @@ namespace OpenSim.Region.Framework.Scenes
477 return; 476 return;
478 477
479 // Calls attach with a Zero position 478 // Calls attach with a Zero position
480 //
481 AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false); 479 AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false);
482 m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); 480 m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
481
482 // Save avatar attachment information
483 ScenePresence presence;
484 if (m_parentScene.AvatarFactory != null && m_parentScene.TryGetAvatar(remoteClient.AgentId, out presence))
485 {
486 m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", AttachmentPoint: " + AttachmentPt);
487 m_parentScene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance);
488 }
483 } 489 }
484 490
485 public SceneObjectGroup RezSingleAttachment( 491 public SceneObjectGroup RezSingleAttachment(
@@ -574,7 +580,7 @@ namespace OpenSim.Region.Framework.Scenes
574 } 580 }
575 581
576 582
577 group.SetAttachmentPoint(Convert.ToByte(AttachmentPt)); 583 group.SetAttachmentPoint((byte)AttachmentPt);
578 group.AbsolutePosition = attachPos; 584 group.AbsolutePosition = attachPos;
579 585
580 // Saves and gets itemID 586 // Saves and gets itemID
@@ -613,7 +619,6 @@ namespace OpenSim.Region.Framework.Scenes
613 619
614 newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance); 620 newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance);
615 newAvatar.IsChildAgent = true; 621 newAvatar.IsChildAgent = true;
616 newAvatar.MaxPrimsPerFrame = m_parentScene.MaxPrimsPerFrame;
617 622
618 AddScenePresence(newAvatar); 623 AddScenePresence(newAvatar);
619 624
@@ -847,7 +852,7 @@ namespace OpenSim.Region.Framework.Scenes
847 /// </summary> 852 /// </summary>
848 /// <param name="localID"></param> 853 /// <param name="localID"></param>
849 /// <returns>null if no scene object group containing that prim is found</returns> 854 /// <returns>null if no scene object group containing that prim is found</returns>
850 private SceneObjectGroup GetGroupByPrim(uint localID) 855 public SceneObjectGroup GetGroupByPrim(uint localID)
851 { 856 {
852 if (Entities.ContainsKey(localID)) 857 if (Entities.ContainsKey(localID))
853 return Entities[localID] as SceneObjectGroup; 858 return Entities[localID] as SceneObjectGroup;
@@ -1107,23 +1112,6 @@ namespace OpenSim.Region.Framework.Scenes
1107 return UUID.Zero; 1112 return UUID.Zero;
1108 } 1113 }
1109 1114
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) 1115 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1128 { 1116 {
1129 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1117 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..810dfd1 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs
@@ -899,7 +899,7 @@ namespace OpenSim.Region.Framework.Scenes
899 SetAttachmentPoint(Convert.ToByte(attachmentpoint)); 899 SetAttachmentPoint(Convert.ToByte(attachmentpoint));
900 900
901 avatar.AddAttachment(this); 901 avatar.AddAttachment(this);
902 m_log.DebugFormat("[SOG]: Added att {0} to avie {1}", UUID, avatar.UUID); 902 m_log.Debug("[SOG]: Added attachment " + UUID + " to avatar " + avatar.UUID);
903 903
904 if (!silent) 904 if (!silent)
905 { 905 {
@@ -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..a078b3d 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>
@@ -3801,15 +3791,15 @@ if (m_shape != null) {
3801 if (ParentGroup.RootPart == this) 3791 if (ParentGroup.RootPart == this)
3802 lPos = AbsolutePosition; 3792 lPos = AbsolutePosition;
3803 } 3793 }
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, Acceleration,
3811 RotationalVelocity, state, FromItemID, 3801 RotationalVelocity, state, FromItemID,
3812 OwnerID, (int)AttachmentPoint); 3802 OwnerID, (int)AttachmentPoint, null, 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..bdd80c6 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -28,6 +28,7 @@
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Reflection; 30using System.Reflection;
31using System.Timers;
31using OpenMetaverse; 32using OpenMetaverse;
32using log4net; 33using log4net;
33using OpenSim.Framework; 34using OpenSim.Framework;
@@ -172,6 +173,11 @@ namespace OpenSim.Region.Framework.Scenes
172 173
173 // Position of agent's camera in world (region cordinates) 174 // Position of agent's camera in world (region cordinates)
174 protected Vector3 m_CameraCenter = Vector3.Zero; 175 protected Vector3 m_CameraCenter = Vector3.Zero;
176 protected Vector3 m_lastCameraCenter = Vector3.Zero;
177
178 protected Timer m_reprioritization_timer;
179 protected bool m_reprioritizing = false;
180 protected bool m_reprioritization_called = false;
175 181
176 // Use these three vectors to figure out what the agent is looking at 182 // Use these three vectors to figure out what the agent is looking at
177 // Convert it to a Matrix and/or Quaternion 183 // Convert it to a Matrix and/or Quaternion
@@ -403,12 +409,6 @@ namespace OpenSim.Region.Framework.Scenes
403 set { m_parentPosition = value; } 409 set { m_parentPosition = value; }
404 } 410 }
405 411
406 public int MaxPrimsPerFrame
407 {
408 get { return m_sceneViewer.MaxPrimsPerFrame; }
409 set { m_sceneViewer.MaxPrimsPerFrame = value; }
410 }
411
412 /// <summary> 412 /// <summary>
413 /// Absolute position of this avatar in 'region cordinates' 413 /// Absolute position of this avatar in 'region cordinates'
414 /// </summary> 414 /// </summary>
@@ -645,7 +645,14 @@ namespace OpenSim.Region.Framework.Scenes
645 645
646 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>(); 646 m_scriptEngines = m_scene.RequestModuleInterfaces<IScriptModule>();
647 647
648 AbsolutePosition = m_controllingClient.StartPos; 648 AbsolutePosition = posLastSignificantMove = m_CameraCenter =
649 m_lastCameraCenter = m_controllingClient.StartPos;
650
651 m_reprioritization_timer = new Timer(world.ReprioritizationInterval);
652 m_reprioritization_timer.Elapsed += new ElapsedEventHandler(Reprioritize);
653 m_reprioritization_timer.AutoReset = false;
654
655
649 AdjustKnownSeeds(); 656 AdjustKnownSeeds();
650 657
651 TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here... 658 TrySetMovementAnimation("STAND"); // TODO: I think, this won't send anything, as we are still a child here...
@@ -1153,15 +1160,21 @@ namespace OpenSim.Region.Framework.Scenes
1153 /// </summary> 1160 /// </summary>
1154 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) 1161 public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData)
1155 { 1162 {
1156 lock (m_agentUpdates) 1163 const int AGENT_UPDATE_TIMEOUT_MS = 1000 * 3;
1164
1165 if (System.Threading.Monitor.TryEnter(m_agentUpdates, AGENT_UPDATE_TIMEOUT_MS))
1157 { 1166 {
1158 if (m_updatesAllowed) 1167 try
1159 { 1168 {
1160 RealHandleAgentUpdate(remoteClient, agentData); 1169 if (m_updatesAllowed)
1161 return; 1170 {
1171 RealHandleAgentUpdate(remoteClient, agentData);
1172 return;
1173 }
1174
1175 m_agentUpdates.Add(agentData);
1162 } 1176 }
1163 1177 finally { System.Threading.Monitor.Exit(m_agentUpdates); }
1164 m_agentUpdates.Add(agentData);
1165 } 1178 }
1166 } 1179 }
1167 1180
@@ -1225,6 +1238,11 @@ namespace OpenSim.Region.Framework.Scenes
1225 // Camera location in world. We'll need to raytrace 1238 // Camera location in world. We'll need to raytrace
1226 // from this location from time to time. 1239 // from this location from time to time.
1227 m_CameraCenter = agentData.CameraCenter; 1240 m_CameraCenter = agentData.CameraCenter;
1241 if (Vector3.Distance(m_lastCameraCenter, m_CameraCenter) >= Scene.RootReprioritizationDistance)
1242 {
1243 ReprioritizeUpdates();
1244 m_lastCameraCenter = m_CameraCenter;
1245 }
1228 1246
1229 // Use these three vectors to figure out what the agent is looking at 1247 // Use these three vectors to figure out what the agent is looking at
1230 // Convert it to a Matrix and/or Quaternion 1248 // Convert it to a Matrix and/or Quaternion
@@ -2456,11 +2474,10 @@ namespace OpenSim.Region.Framework.Scenes
2456 m_perfMonMS = Environment.TickCount; 2474 m_perfMonMS = Environment.TickCount;
2457 2475
2458 Vector3 pos = m_pos; 2476 Vector3 pos = m_pos;
2459 Vector3 vel = Velocity;
2460 Quaternion rot = m_bodyRot;
2461 pos.Z -= m_appearance.HipOffset; 2477 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), 2478
2463 new Vector3(vel.X, vel.Y, vel.Z), rot, m_uuid); 2479 remoteClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_regionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId,
2480 pos, m_velocity, Vector3.Zero, m_rotation, Vector4.Zero, m_uuid, null, GetUpdatePriority(remoteClient)));
2464 2481
2465 m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS); 2482 m_scene.StatsReporter.AddAgentTime(Environment.TickCount - m_perfMonMS);
2466 m_scene.StatsReporter.AddAgentUpdates(1); 2483 m_scene.StatsReporter.AddAgentUpdates(1);
@@ -2474,7 +2491,7 @@ namespace OpenSim.Region.Framework.Scenes
2474 { 2491 {
2475 m_perfMonMS = Environment.TickCount; 2492 m_perfMonMS = Environment.TickCount;
2476 2493
2477 m_scene.Broadcast(SendTerseUpdateToClient); 2494 m_scene.ForEachClient(SendTerseUpdateToClient);
2478 2495
2479 m_lastVelocity = m_velocity; 2496 m_lastVelocity = m_velocity;
2480 lastPhysPos = AbsolutePosition; 2497 lastPhysPos = AbsolutePosition;
@@ -2566,9 +2583,9 @@ namespace OpenSim.Region.Framework.Scenes
2566 Vector3 pos = m_pos; 2583 Vector3 pos = m_pos;
2567 pos.Z -= m_appearance.HipOffset; 2584 pos.Z -= m_appearance.HipOffset;
2568 2585
2569 remoteAvatar.m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, 2586 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(), 2587 LocalId, m_pos, m_appearance.Texture.GetBytes(),
2571 m_parentID, rot); 2588 m_parentID, rot));
2572 m_scene.StatsReporter.AddAgentUpdates(1); 2589 m_scene.StatsReporter.AddAgentUpdates(1);
2573 } 2590 }
2574 2591
@@ -2637,8 +2654,8 @@ namespace OpenSim.Region.Framework.Scenes
2637 Vector3 pos = m_pos; 2654 Vector3 pos = m_pos;
2638 pos.Z -= m_appearance.HipOffset; 2655 pos.Z -= m_appearance.HipOffset;
2639 2656
2640 m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2657 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); 2658 m_pos, m_appearance.Texture.GetBytes(), m_parentID, rot));
2642 2659
2643 if (!m_isChildAgent) 2660 if (!m_isChildAgent)
2644 { 2661 {
@@ -2744,8 +2761,8 @@ namespace OpenSim.Region.Framework.Scenes
2744 } 2761 }
2745 2762
2746 Quaternion rot = m_bodyRot; 2763 Quaternion rot = m_bodyRot;
2747 m_controllingClient.SendAvatarData(m_regionInfo.RegionHandle, m_firstname, m_lastname, m_grouptitle, m_uuid, LocalId, 2764 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); 2765 m_pos, m_appearance.Texture.GetBytes(), m_parentID, rot));
2749 2766
2750 } 2767 }
2751 2768
@@ -2776,7 +2793,7 @@ namespace OpenSim.Region.Framework.Scenes
2776 if (m_isChildAgent) 2793 if (m_isChildAgent)
2777 return; 2794 return;
2778 2795
2779 m_scene.Broadcast( 2796 m_scene.ForEachClient(
2780 delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId, objectIDs); }); 2797 delegate(IClientAPI client) { client.SendAnimations(animations, seqs, m_controllingClient.AgentId, objectIDs); });
2781 } 2798 }
2782 2799
@@ -2830,7 +2847,7 @@ namespace OpenSim.Region.Framework.Scenes
2830 } 2847 }
2831 2848
2832 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m 2849 // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m
2833 if (Util.GetDistanceTo(AbsolutePosition,m_LastChildAgentUpdatePosition) > 32) 2850 if (Util.GetDistanceTo(AbsolutePosition, m_LastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance)
2834 { 2851 {
2835 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); 2852 ChildAgentDataUpdate cadu = new ChildAgentDataUpdate();
2836 cadu.ActiveGroupID = UUID.Zero.Guid; 2853 cadu.ActiveGroupID = UUID.Zero.Guid;
@@ -3125,6 +3142,12 @@ namespace OpenSim.Region.Framework.Scenes
3125 if (cAgentData.Position != new Vector3(-1, -1, -1)) // UGH!! 3142 if (cAgentData.Position != new Vector3(-1, -1, -1)) // UGH!!
3126 m_pos = new Vector3(cAgentData.Position.X + shiftx, cAgentData.Position.Y + shifty, cAgentData.Position.Z); 3143 m_pos = new Vector3(cAgentData.Position.X + shiftx, cAgentData.Position.Y + shifty, cAgentData.Position.Z);
3127 3144
3145 if (Vector3.Distance(AbsolutePosition, posLastSignificantMove) >= Scene.ChildReprioritizationDistance)
3146 {
3147 posLastSignificantMove = AbsolutePosition;
3148 ReprioritizeUpdates();
3149 }
3150
3128 // It's hard to say here.. We can't really tell where the camera position is unless it's in world cordinates from the sending region 3151 // It's hard to say here.. We can't really tell where the camera position is unless it's in world cordinates from the sending region
3129 m_CameraCenter = cAgentData.Center; 3152 m_CameraCenter = cAgentData.Center;
3130 3153
@@ -3487,7 +3510,6 @@ namespace OpenSim.Region.Framework.Scenes
3487 3510
3488 public void Close() 3511 public void Close()
3489 { 3512 {
3490
3491 lock (m_attachments) 3513 lock (m_attachments)
3492 { 3514 {
3493 // Delete attachments from scene 3515 // Delete attachments from scene
@@ -3505,10 +3527,19 @@ namespace OpenSim.Region.Framework.Scenes
3505 { 3527 {
3506 m_knownChildRegions.Clear(); 3528 m_knownChildRegions.Clear();
3507 } 3529 }
3530
3531 lock (m_reprioritization_timer)
3532 {
3533 m_reprioritization_timer.Enabled = false;
3534 m_reprioritization_timer.Elapsed -= new ElapsedEventHandler(Reprioritize);
3535 }
3536 // I don't get it but mono crashes when you try to dispose of this timer,
3537 // unsetting the elapsed callback should be enough to allow for cleanup however.
3538 //m_reprioritizationTimer.Dispose();
3539
3508 m_sceneViewer.Close(); 3540 m_sceneViewer.Close();
3509 3541
3510 RemoveFromPhysicalScene(); 3542 RemoveFromPhysicalScene();
3511 GC.Collect();
3512 } 3543 }
3513 3544
3514 public ScenePresence() 3545 public ScenePresence()
@@ -3884,5 +3915,115 @@ namespace OpenSim.Region.Framework.Scenes
3884 } 3915 }
3885 } 3916 }
3886 } 3917 }
3918
3919 public double GetUpdatePriority(IClientAPI client)
3920 {
3921 switch (Scene.UpdatePrioritizationScheme)
3922 {
3923 case Scene.UpdatePrioritizationSchemes.Time:
3924 return GetPriorityByTime();
3925 case Scene.UpdatePrioritizationSchemes.Distance:
3926 return GetPriorityByDistance(client);
3927 case Scene.UpdatePrioritizationSchemes.SimpleAngularDistance:
3928 return GetPriorityByDistance(client);
3929 default:
3930 throw new InvalidOperationException("UpdatePrioritizationScheme not defined.");
3931 }
3932 }
3933
3934 private double GetPriorityByTime()
3935 {
3936 return DateTime.Now.ToOADate();
3937 }
3938
3939 private double GetPriorityByDistance(IClientAPI client)
3940 {
3941 ScenePresence presence = Scene.GetScenePresence(client.AgentId);
3942 if (presence != null)
3943 {
3944 return GetPriorityByDistance((presence.IsChildAgent) ?
3945 presence.AbsolutePosition : presence.CameraPosition);
3946 }
3947 return double.NaN;
3948 }
3949
3950 private double GetPriorityByDistance(Vector3 position)
3951 {
3952 return Vector3.Distance(AbsolutePosition, position);
3953 }
3954
3955 private double GetSOGUpdatePriority(SceneObjectGroup sog)
3956 {
3957 switch (Scene.UpdatePrioritizationScheme)
3958 {
3959 case Scene.UpdatePrioritizationSchemes.Time:
3960 throw new InvalidOperationException("UpdatePrioritizationScheme for time not supported for reprioritization");
3961 case Scene.UpdatePrioritizationSchemes.Distance:
3962 return sog.GetPriorityByDistance((IsChildAgent) ? AbsolutePosition : CameraPosition);
3963 case Scene.UpdatePrioritizationSchemes.SimpleAngularDistance:
3964 return sog.GetPriorityBySimpleAngularDistance((IsChildAgent) ? AbsolutePosition : CameraPosition);
3965 default:
3966 throw new InvalidOperationException("UpdatePrioritizationScheme not defined");
3967 }
3968 }
3969
3970 private double UpdatePriority(UpdatePriorityData data)
3971 {
3972 EntityBase entity;
3973 SceneObjectGroup group;
3974
3975 if (Scene.Entities.TryGetValue(data.localID, out entity))
3976 {
3977 group = entity as SceneObjectGroup;
3978 if (group != null)
3979 return GetSOGUpdatePriority(group);
3980
3981 ScenePresence presence = entity as ScenePresence;
3982 if (presence == null)
3983 throw new InvalidOperationException("entity found is neither SceneObjectGroup nor ScenePresence");
3984 switch (Scene.UpdatePrioritizationScheme)
3985 {
3986 case Scene.UpdatePrioritizationSchemes.Time:
3987 throw new InvalidOperationException("UpdatePrioritization for time not supported for reprioritization");
3988 case Scene.UpdatePrioritizationSchemes.Distance:
3989 case Scene.UpdatePrioritizationSchemes.SimpleAngularDistance:
3990 return GetPriorityByDistance((IsChildAgent) ? AbsolutePosition : CameraPosition);
3991 default:
3992 throw new InvalidOperationException("UpdatePrioritizationScheme not defined");
3993 }
3994 }
3995 else
3996 {
3997 group = Scene.SceneGraph.GetGroupByPrim(data.localID);
3998 if (group != null)
3999 return GetSOGUpdatePriority(group);
4000 }
4001 return double.NaN;
4002 }
4003
4004 private void ReprioritizeUpdates()
4005 {
4006 if (Scene.IsReprioritizationEnabled && Scene.UpdatePrioritizationScheme != Scene.UpdatePrioritizationSchemes.Time)
4007 {
4008 lock (m_reprioritization_timer)
4009 {
4010 if (!m_reprioritizing)
4011 m_reprioritization_timer.Enabled = m_reprioritizing = true;
4012 else
4013 m_reprioritization_called = true;
4014 }
4015 }
4016 }
4017
4018 private void Reprioritize(object sender, ElapsedEventArgs e)
4019 {
4020 m_controllingClient.ReprioritizeUpdates(StateUpdateTypes.All, UpdatePriority);
4021
4022 lock (m_reprioritization_timer)
4023 {
4024 m_reprioritization_timer.Enabled = m_reprioritizing = m_reprioritization_called;
4025 m_reprioritization_called = false;
4026 }
4027 }
3887 } 4028 }
3888} 4029}
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 434da0a..df03b8d 100644
--- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
+++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs
@@ -1013,12 +1013,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1013 1013
1014 } 1014 }
1015 1015
1016 public void SendAvatarData(ulong regionHandle, string firstName, string lastName, string grouptitle, UUID avatarID, uint avatarLocalID, Vector3 Pos, byte[] textureEntry, uint parentID, Quaternion rotation) 1016 public void SendAvatarData(SendAvatarData data)
1017 { 1017 {
1018 1018
1019 } 1019 }
1020 1020
1021 public void SendAvatarTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, Vector3 position, Vector3 velocity, Quaternion rotation, UUID agentid) 1021 public void SendAvatarTerseUpdate(SendAvatarTerseData data)
1022 { 1022 {
1023 1023
1024 } 1024 }
@@ -1038,19 +1038,19 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server
1038 1038
1039 } 1039 }
1040 1040
1041 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) 1041 public void SendPrimitiveToClient(SendPrimitiveData data)
1042 { 1042 {
1043 1043
1044 } 1044 }
1045 1045
1046 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) 1046 public void SendPrimTerseUpdate(SendPrimitiveTerseData data)
1047 { 1047 {
1048 1048
1049 } 1049 }
1050 1050
1051 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) 1051 public void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
1052 { 1052 {
1053 1053
1054 } 1054 }
1055 1055
1056 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, bool fetchFolders, bool fetchItems) 1056 public void SendInventoryFolderDetails(UUID ownerID, UUID folderID, List<InventoryItemBase> items, List<InventoryFolderBase> folders, bool fetchFolders, bool fetchItems)
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..f7cadaa 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,15 @@ 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 { 616 {
629 } 617 }
630 public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, 618
631 Vector3 position, Quaternion rotation, Vector3 velocity, 619 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
632 Vector3 rotationalvelocity, byte state, UUID AssetId, UUID ownerID, int attachPoint)
633 { 620 {
634 } 621 }
635 622
diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
index 1ea08e2..f609e73 100644
--- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
+++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs
@@ -289,6 +289,9 @@ namespace OpenSim.Region.Physics.Meshing
289 ManagedImage managedImage; // we never use this 289 ManagedImage managedImage; // we never use this
290 OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage, out idata); 290 OpenJPEG.DecodeToImage(primShape.SculptData, out managedImage, out idata);
291 291
292 // Remove the reference to the encoded JPEG2000 data so it can be GCed
293 primShape.SculptData = Utils.EmptyBytes;
294
292 if (cacheSculptMaps) 295 if (cacheSculptMaps)
293 { 296 {
294 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); } 297 try { idata.Save(decodedSculptFileName, ImageFormat.MemoryBmp); }
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index 1fff846..ef0e56e 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -139,8 +139,14 @@ namespace OpenSim.Region.Physics.OdePlugin
139 public int m_eventsubscription = 0; 139 public int m_eventsubscription = 0;
140 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate(); 140 private CollisionEventUpdate CollisionEventsThisFrame = new CollisionEventUpdate();
141 141
142 // unique UUID of this character object
143 public UUID m_uuid;
144 public bool bad = false;
145
142 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, CollisionLocker dode, PhysicsVector size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor) 146 public OdeCharacter(String avName, OdeScene parent_scene, PhysicsVector pos, CollisionLocker dode, PhysicsVector size, float pid_d, float pid_p, float capsule_radius, float tensor, float density, float height_fudge_factor, float walk_divisor, float rundivisor)
143 { 147 {
148 m_uuid = UUID.Random();
149
144 // ode = dode; 150 // ode = dode;
145 _velocity = new PhysicsVector(); 151 _velocity = new PhysicsVector();
146 _target_velocity = new PhysicsVector(); 152 _target_velocity = new PhysicsVector();
@@ -1112,10 +1118,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1112 } 1118 }
1113 catch (NullReferenceException) 1119 catch (NullReferenceException)
1114 { 1120 {
1121 bad = true;
1115 _parent_scene.BadCharacter(this); 1122 _parent_scene.BadCharacter(this);
1116 vec = new d.Vector3(_position.X, _position.Y, _position.Z); 1123 vec = new d.Vector3(_position.X, _position.Y, _position.Z);
1117 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! 1124 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
1118 m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar: {0}", m_name); 1125 m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid);
1119 } 1126 }
1120 1127
1121 1128
diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
index 92afe39..0c94fb6 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs
@@ -1664,6 +1664,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1664 if (!_characters.Contains(chr)) 1664 if (!_characters.Contains(chr))
1665 { 1665 {
1666 _characters.Add(chr); 1666 _characters.Add(chr);
1667 if (chr.bad)
1668 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1667 } 1669 }
1668 } 1670 }
1669 } 1671 }
@@ -2581,7 +2583,11 @@ namespace OpenSim.Region.Physics.OdePlugin
2581 lock (_taintedActors) 2583 lock (_taintedActors)
2582 { 2584 {
2583 if (!(_taintedActors.Contains(taintedchar))) 2585 if (!(_taintedActors.Contains(taintedchar)))
2586 {
2584 _taintedActors.Add(taintedchar); 2587 _taintedActors.Add(taintedchar);
2588 if (taintedchar.bad)
2589 m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid);
2590 }
2585 } 2591 }
2586 } 2592 }
2587 } 2593 }
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..0f642b9 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,15 @@ 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 { 620 {
633 } 621 }
634 public virtual void SendPrimTerseUpdate(ulong regionHandle, ushort timeDilation, uint localID, 622
635 Vector3 position, Quaternion rotation, Vector3 velocity, 623 public virtual void ReprioritizeUpdates(StateUpdateTypes type, UpdatePriorityHandler handler)
636 Vector3 rotationalvelocity, byte state, UUID AssetId,
637 UUID ownerID, int attachPoint)
638 { 624 {
639 } 625 }
640 626