aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim
diff options
context:
space:
mode:
authorMelanie2011-11-24 01:16:37 +0000
committerMelanie2011-11-24 01:16:37 +0000
commita8270cb48cf8dbca7595da5963d8fafdb1141529 (patch)
treecf878acca0c652239f4441c3783647b6b0b688a6 /OpenSim
parentMerge branch 'master' into bigmerge (diff)
parentAppend asset ID to URL for storage requests to allow caching proxies to work ... (diff)
downloadopensim-SC-a8270cb48cf8dbca7595da5963d8fafdb1141529.zip
opensim-SC-a8270cb48cf8dbca7595da5963d8fafdb1141529.tar.gz
opensim-SC-a8270cb48cf8dbca7595da5963d8fafdb1141529.tar.bz2
opensim-SC-a8270cb48cf8dbca7595da5963d8fafdb1141529.tar.xz
Merge branch 'master' into bigmerge
Diffstat (limited to 'OpenSim')
-rw-r--r--OpenSim/Framework/IScene.cs22
-rw-r--r--OpenSim/Region/Application/ConfigurationLoader.cs20
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs9
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneBase.cs2
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPart.cs37
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs10
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs26
-rwxr-xr-xOpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs2
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsActor.cs13
-rw-r--r--OpenSim/Region/Physics/Manager/PhysicsScene.cs10
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODECharacter.cs341
-rw-r--r--OpenSim/Region/Physics/OdePlugin/ODEPrim.cs20
-rw-r--r--OpenSim/Region/Physics/OdePlugin/OdeScene.cs680
-rw-r--r--OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs54
-rw-r--r--OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs65
-rw-r--r--OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs4
-rw-r--r--OpenSim/Tests/ConfigurationLoaderTest.cs4
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs2
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs2
-rw-r--r--OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs75
-rw-r--r--OpenSim/Tools/pCampBot/Bot.cs35
-rw-r--r--OpenSim/Tools/pCampBot/BotManager.cs100
-rw-r--r--OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs9
-rw-r--r--OpenSim/Tools/pCampBot/pCampBot.cs2
25 files changed, 882 insertions, 675 deletions
diff --git a/OpenSim/Framework/IScene.cs b/OpenSim/Framework/IScene.cs
index f1b4732..76b731f 100644
--- a/OpenSim/Framework/IScene.cs
+++ b/OpenSim/Framework/IScene.cs
@@ -102,12 +102,28 @@ namespace OpenSim.Framework
102 102
103 bool TryGetScenePresence(UUID agentID, out object scenePresence); 103 bool TryGetScenePresence(UUID agentID, out object scenePresence);
104 104
105 T RequestModuleInterface<T>(); 105 /// <summary>
106 T[] RequestModuleInterfaces<T>(); 106 /// Register an interface to a region module. This allows module methods to be called directly as
107 107 /// well as via events. If there is already a module registered for this interface, it is not replaced
108 /// (is this the best behaviour?)
109 /// </summary>
110 /// <param name="mod"></param>
108 void RegisterModuleInterface<M>(M mod); 111 void RegisterModuleInterface<M>(M mod);
112
109 void StackModuleInterface<M>(M mod); 113 void StackModuleInterface<M>(M mod);
110 114
115 /// <summary>
116 /// For the given interface, retrieve the region module which implements it.
117 /// </summary>
118 /// <returns>null if there is no registered module implementing that interface</returns>
119 T RequestModuleInterface<T>();
120
121 /// <summary>
122 /// For the given interface, retrieve an array of region modules that implement it.
123 /// </summary>
124 /// <returns>an empty array if there are no registered modules implementing that interface</returns>
125 T[] RequestModuleInterfaces<T>();
126
111// void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback); 127// void AddCommand(object module, string command, string shorthelp, string longhelp, CommandDelegate callback);
112 128
113 ISceneObject DeserializeObject(string representation); 129 ISceneObject DeserializeObject(string representation);
diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs
index d0f6ab7..4a7c8b0 100644
--- a/OpenSim/Region/Application/ConfigurationLoader.cs
+++ b/OpenSim/Region/Application/ConfigurationLoader.cs
@@ -70,7 +70,7 @@ namespace OpenSim
70 /// <param name="networkInfo"></param> 70 /// <param name="networkInfo"></param>
71 /// <returns>A configuration that gets passed to modules</returns> 71 /// <returns>A configuration that gets passed to modules</returns>
72 public OpenSimConfigSource LoadConfigSettings( 72 public OpenSimConfigSource LoadConfigSettings(
73 IConfigSource argvSource, out ConfigSettings configSettings, 73 IConfigSource argvSource, EnvConfigSource envConfigSource, out ConfigSettings configSettings,
74 out NetworkServersInfo networkInfo) 74 out NetworkServersInfo networkInfo)
75 { 75 {
76 m_configSettings = configSettings = new ConfigSettings(); 76 m_configSettings = configSettings = new ConfigSettings();
@@ -195,6 +195,24 @@ namespace OpenSim
195 // Make sure command line options take precedence 195 // Make sure command line options take precedence
196 m_config.Source.Merge(argvSource); 196 m_config.Source.Merge(argvSource);
197 197
198
199 IConfig enVars = m_config.Source.Configs["Environment"];
200
201 if( enVars != null )
202 {
203 string[] env_keys = enVars.GetKeys();
204
205 foreach ( string key in env_keys )
206 {
207 envConfigSource.AddEnv(key, string.Empty);
208 }
209
210 envConfigSource.LoadEnv();
211 m_config.Source.Merge(envConfigSource);
212 m_config.Source.ExpandKeyValues();
213 }
214
215
198 ReadConfigSettings(); 216 ReadConfigSettings();
199 217
200 return m_config; 218 return m_config;
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 542211a..8e1eb95 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -112,6 +112,13 @@ namespace OpenSim
112 get { return m_clientServers; } 112 get { return m_clientServers; }
113 } 113 }
114 114
115 protected EnvConfigSource m_EnvConfigSource = new EnvConfigSource();
116
117 public EnvConfigSource envConfigSource
118 {
119 get { return m_EnvConfigSource; }
120 }
121
115 protected List<IClientNetworkServer> m_clientServers = new List<IClientNetworkServer>(); 122 protected List<IClientNetworkServer> m_clientServers = new List<IClientNetworkServer>();
116 123
117 public uint HttpServerPort 124 public uint HttpServerPort
@@ -146,7 +153,7 @@ namespace OpenSim
146 protected virtual void LoadConfigSettings(IConfigSource configSource) 153 protected virtual void LoadConfigSettings(IConfigSource configSource)
147 { 154 {
148 m_configLoader = new ConfigurationLoader(); 155 m_configLoader = new ConfigurationLoader();
149 m_config = m_configLoader.LoadConfigSettings(configSource, out m_configSettings, out m_networkServersInfo); 156 m_config = m_configLoader.LoadConfigSettings(configSource, envConfigSource, out m_configSettings, out m_networkServersInfo);
150 ReadExtraConfigSettings(); 157 ReadExtraConfigSettings();
151 } 158 }
152 159
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 53f0f2e..245f258 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -82,16 +82,9 @@ namespace OpenSim.Region.Framework.Scenes
82 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); 82 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene");
83 83
84 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>(); 84 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
85 if (engines != null) 85
86 { 86 foreach (IScriptModule engine in engines)
87 foreach (IScriptModule engine in engines) 87 engine.StartProcessing();
88 {
89 if (engine != null)
90 {
91 engine.StartProcessing();
92 }
93 }
94 }
95 } 88 }
96 89
97 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) 90 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item)
diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs
index 73e9392..0fd5164 100644
--- a/OpenSim/Region/Framework/Scenes/SceneBase.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs
@@ -451,7 +451,7 @@ namespace OpenSim.Region.Framework.Scenes
451 } 451 }
452 else 452 else
453 { 453 {
454 return new T[] { default(T) }; 454 return new T[] {};
455 } 455 }
456 } 456 }
457 457
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index e214f57..11040b7 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -252,7 +252,6 @@ namespace OpenSim.Region.Framework.Scenes
252 private byte[] m_TextureAnimation; 252 private byte[] m_TextureAnimation;
253 private byte m_clickAction; 253 private byte m_clickAction;
254 private Color m_color = Color.Black; 254 private Color m_color = Color.Black;
255 private string m_description = String.Empty;
256 private readonly List<uint> m_lastColliders = new List<uint>(); 255 private readonly List<uint> m_lastColliders = new List<uint>();
257 private int m_linkNum; 256 private int m_linkNum;
258 257
@@ -331,11 +330,14 @@ namespace OpenSim.Region.Framework.Scenes
331 /// </summary> 330 /// </summary>
332 public SceneObjectPart() 331 public SceneObjectPart()
333 { 332 {
334 // It's not necessary to persist this
335 m_TextureAnimation = Utils.EmptyBytes; 333 m_TextureAnimation = Utils.EmptyBytes;
336 m_particleSystem = Utils.EmptyBytes; 334 m_particleSystem = Utils.EmptyBytes;
337 Rezzed = DateTime.UtcNow; 335 Rezzed = DateTime.UtcNow;
338 336 Description = String.Empty;
337
338 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
339 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
340 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
339 m_inventory = new SceneObjectPartInventory(this); 341 m_inventory = new SceneObjectPartInventory(this);
340 } 342 }
341 343
@@ -349,11 +351,10 @@ namespace OpenSim.Region.Framework.Scenes
349 /// <param name="offsetPosition"></param> 351 /// <param name="offsetPosition"></param>
350 public SceneObjectPart( 352 public SceneObjectPart(
351 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition, 353 UUID ownerID, PrimitiveBaseShape shape, Vector3 groupPosition,
352 Quaternion rotationOffset, Vector3 offsetPosition) 354 Quaternion rotationOffset, Vector3 offsetPosition) : this()
353 { 355 {
354 m_name = "Object"; 356 m_name = "Object";
355 357
356 Rezzed = DateTime.UtcNow;
357 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed); 358 CreationDate = (int)Utils.DateTimeToUnixTime(Rezzed);
358 LastOwnerID = CreatorID = OwnerID = ownerID; 359 LastOwnerID = CreatorID = OwnerID = ownerID;
359 UUID = UUID.Random(); 360 UUID = UUID.Random();
@@ -368,19 +369,10 @@ namespace OpenSim.Region.Framework.Scenes
368 Velocity = Vector3.Zero; 369 Velocity = Vector3.Zero;
369 AngularVelocity = Vector3.Zero; 370 AngularVelocity = Vector3.Zero;
370 Acceleration = Vector3.Zero; 371 Acceleration = Vector3.Zero;
371 m_TextureAnimation = Utils.EmptyBytes;
372 m_particleSystem = Utils.EmptyBytes;
373
374 // Prims currently only contain a single folder (Contents). From looking at the Second Life protocol,
375 // this appears to have the same UUID (!) as the prim. If this isn't the case, one can't drag items from
376 // the prim into an agent inventory (Linden client reports that the "Object not found for drop" in its log
377
378 Flags = 0; 372 Flags = 0;
379 CreateSelected = true; 373 CreateSelected = true;
380 374
381 TrimPermissions(); 375 TrimPermissions();
382
383 m_inventory = new SceneObjectPartInventory(this);
384 } 376 }
385 377
386 #endregion Constructors 378 #endregion Constructors
@@ -938,19 +930,7 @@ namespace OpenSim.Region.Framework.Scenes
938 set { m_acceleration = value; } 930 set { m_acceleration = value; }
939 } 931 }
940 932
941 public string Description 933 public string Description { get; set; }
942 {
943 get { return m_description; }
944 set
945 {
946 m_description = value;
947 PhysicsActor actor = PhysActor;
948 if (actor != null)
949 {
950 actor.SOPDescription = value;
951 }
952 }
953 }
954 934
955 /// <value> 935 /// <value>
956 /// Text color. 936 /// Text color.
@@ -1595,8 +1575,7 @@ namespace OpenSim.Region.Framework.Scenes
1595 // Basic Physics returns null.. joy joy joy. 1575 // Basic Physics returns null.. joy joy joy.
1596 if (PhysActor != null) 1576 if (PhysActor != null)
1597 { 1577 {
1598 PhysActor.SOPName = this.Name; // save object name and desc into the PhysActor so ODE internals know the joint/body info 1578 PhysActor.SOPName = this.Name; // save object into the PhysActor so ODE internals know the joint/body info
1599 PhysActor.SOPDescription = this.Description;
1600 PhysActor.SetMaterial(Material); 1579 PhysActor.SetMaterial(Material);
1601 DoPhysicsPropertyUpdate(RigidBody, true); 1580 DoPhysicsPropertyUpdate(RigidBody, true);
1602 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); 1581 PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0);
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 309f543..c485e87 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -282,8 +282,6 @@ namespace OpenSim.Region.Framework.Scenes
282 ArrayList ret = new ArrayList(); 282 ArrayList ret = new ArrayList();
283 283
284 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 284 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
285 if (engines == null) // No engine at all
286 return ret;
287 285
288 foreach (IScriptModule e in engines) 286 foreach (IScriptModule e in engines)
289 { 287 {
@@ -397,7 +395,7 @@ namespace OpenSim.Region.Framework.Scenes
397 private void RestoreSavedScriptState(UUID oldID, UUID newID) 395 private void RestoreSavedScriptState(UUID oldID, UUID newID)
398 { 396 {
399 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 397 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
400 if (engines == null) // No engine at all 398 if (engines.Length == 0) // No engine at all
401 return; 399 return;
402 400
403 if (m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID)) 401 if (m_part.ParentGroup.m_savedScriptState.ContainsKey(oldID))
@@ -437,6 +435,7 @@ namespace OpenSim.Region.Framework.Scenes
437 435
438 m_part.ParentGroup.m_savedScriptState[oldID] = newDoc.OuterXml; 436 m_part.ParentGroup.m_savedScriptState[oldID] = newDoc.OuterXml;
439 } 437 }
438
440 foreach (IScriptModule e in engines) 439 foreach (IScriptModule e in engines)
441 { 440 {
442 if (e != null) 441 if (e != null)
@@ -445,6 +444,7 @@ namespace OpenSim.Region.Framework.Scenes
445 break; 444 break;
446 } 445 }
447 } 446 }
447
448 m_part.ParentGroup.m_savedScriptState.Remove(oldID); 448 m_part.ParentGroup.m_savedScriptState.Remove(oldID);
449 } 449 }
450 } 450 }
@@ -1327,7 +1327,7 @@ namespace OpenSim.Region.Framework.Scenes
1327 1327
1328 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1328 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1329 1329
1330 if (engines == null) // No engine at all 1330 if (engines.Length == 0) // No engine at all
1331 return ret; 1331 return ret;
1332 1332
1333 Items.LockItemsForRead(true); 1333 Items.LockItemsForRead(true);
@@ -1365,7 +1365,7 @@ namespace OpenSim.Region.Framework.Scenes
1365 public void ResumeScripts() 1365 public void ResumeScripts()
1366 { 1366 {
1367 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>(); 1367 IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces<IScriptModule>();
1368 if (engines == null) 1368 if (engines.Length == 0)
1369 return; 1369 return;
1370 1370
1371 1371
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index d89c1c0..0eaac64 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -3535,23 +3535,23 @@ namespace OpenSim.Region.Framework.Scenes
3535 /// <param name="args">The arguments for the event</param> 3535 /// <param name="args">The arguments for the event</param>
3536 public void SendScriptEventToAttachments(string eventName, Object[] args) 3536 public void SendScriptEventToAttachments(string eventName, Object[] args)
3537 { 3537 {
3538 if (m_scriptEngines != null) 3538 if (m_scriptEngines.Length == 0)
3539 return;
3540
3541 lock (m_attachments)
3539 { 3542 {
3540 lock (m_attachments) 3543 foreach (SceneObjectGroup grp in m_attachments)
3541 { 3544 {
3542 foreach (SceneObjectGroup grp in m_attachments) 3545 // 16384 is CHANGED_ANIMATION
3546 //
3547 // Send this to all attachment root prims
3548 //
3549 foreach (IScriptModule m in m_scriptEngines)
3543 { 3550 {
3544 // 16384 is CHANGED_ANIMATION 3551 if (m == null) // No script engine loaded
3545 // 3552 continue;
3546 // Send this to all attachment root prims
3547 //
3548 foreach (IScriptModule m in m_scriptEngines)
3549 {
3550 if (m == null) // No script engine loaded
3551 continue;
3552 3553
3553 m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION }); 3554 m.PostObjectEvent(grp.RootPart.UUID, "changed", new Object[] { (int)Changed.ANIMATION });
3554 }
3555 } 3555 }
3556 } 3556 }
3557 } 3557 }
diff --git a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
index 2a44360..23ef757 100755
--- a/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
+++ b/OpenSim/Region/OptionalModules/PhysicsParameters/PhysicsParameters.cs
@@ -48,7 +48,7 @@ namespace OpenSim.Region.OptionalModules.PhysicsParameters
48 public class PhysicsParameters : ISharedRegionModule 48 public class PhysicsParameters : ISharedRegionModule
49 { 49 {
50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
51 private static string LogHeader = "[PHYSICS PARAMETERS]"; 51// private static string LogHeader = "[PHYSICS PARAMETERS]";
52 52
53 private List<Scene> m_scenes = new List<Scene>(); 53 private List<Scene> m_scenes = new List<Scene>();
54 private static bool m_commandsLoaded = false; 54 private static bool m_commandsLoaded = false;
diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
index 798a0a4..c2acf97 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs
@@ -160,8 +160,19 @@ namespace OpenSim.Region.Physics.Manager
160 160
161 public abstract bool Selected { set; } 161 public abstract bool Selected { set; }
162 162
163 /// <summary>
164 /// Name of this actor.
165 /// </summary>
166 /// <remarks>
167 /// XXX: Bizarrely, this cannot be "Terrain" or "Water" right now unless it really is simulating terrain or
168 /// water. This is not a problem due to the formatting of names given by prims and avatars.
169 /// </remarks>
170 public string Name { get; protected set; }
171
172 /// <summary>
173 /// This is being used by ODE joint code.
174 /// </summary>
163 public string SOPName; 175 public string SOPName;
164 public string SOPDescription;
165 176
166 public abstract void CrossingFailure(); 177 public abstract void CrossingFailure();
167 178
diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
index acedf44..1f631ee 100644
--- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs
+++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs
@@ -224,15 +224,9 @@ namespace OpenSim.Region.Physics.Manager
224 return false; 224 return false;
225 } 225 }
226 226
227 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) 227 public virtual void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) {}
228 {
229 return;
230 }
231 228
232 public virtual void UnCombine(PhysicsScene pScene) 229 public virtual void UnCombine(PhysicsScene pScene) {}
233 {
234
235 }
236 230
237 /// <summary> 231 /// <summary>
238 /// Queue a raycast against the physics scene. 232 /// Queue a raycast against the physics scene.
diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
index c37d588..489a23a 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs
@@ -70,7 +70,6 @@ namespace OpenSim.Region.Physics.OdePlugin
70 70
71 private Vector3 _position; 71 private Vector3 _position;
72 private d.Vector3 _zeroPosition; 72 private d.Vector3 _zeroPosition;
73 // private d.Matrix3 m_StandUpRotation;
74 private bool _zeroFlag = false; 73 private bool _zeroFlag = false;
75 private bool m_lastUpdateSent = false; 74 private bool m_lastUpdateSent = false;
76 private Vector3 _velocity; 75 private Vector3 _velocity;
@@ -123,9 +122,6 @@ namespace OpenSim.Region.Physics.OdePlugin
123 private float m_buoyancy = 0f; 122 private float m_buoyancy = 0f;
124 123
125 // private CollisionLocker ode; 124 // private CollisionLocker ode;
126
127 private string m_name = String.Empty;
128
129 private bool[] m_colliderarr = new bool[11]; 125 private bool[] m_colliderarr = new bool[11];
130 private bool[] m_colliderGroundarr = new bool[11]; 126 private bool[] m_colliderGroundarr = new bool[11];
131 127
@@ -181,7 +177,7 @@ namespace OpenSim.Region.Physics.OdePlugin
181 parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); 177 parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f);
182 m_taintPosition = _position; 178 m_taintPosition = _position;
183 179
184 m_log.Warn("[PHYSICS]: Got NaN Position on Character Create"); 180 m_log.WarnFormat("[ODE CHARACTER]: Got NaN Position on Character Create for {0}", avName);
185 } 181 }
186 182
187 _parent_scene = parent_scene; 183 _parent_scene = parent_scene;
@@ -204,7 +200,7 @@ namespace OpenSim.Region.Physics.OdePlugin
204 m_colliderarr[i] = false; 200 m_colliderarr[i] = false;
205 } 201 }
206 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; 202 CAPSULE_LENGTH = (size.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
207 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); 203 //m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH.ToString());
208 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH; 204 m_tainted_CAPSULE_LENGTH = CAPSULE_LENGTH;
209 205
210 m_isPhysical = false; // current status: no ODE information exists 206 m_isPhysical = false; // current status: no ODE information exists
@@ -212,7 +208,7 @@ namespace OpenSim.Region.Physics.OdePlugin
212 208
213 _parent_scene.AddPhysicsActorTaint(this); 209 _parent_scene.AddPhysicsActorTaint(this);
214 210
215 m_name = avName; 211 Name = avName;
216 } 212 }
217 213
218 public override int PhysicsActorType 214 public override int PhysicsActorType
@@ -269,7 +265,7 @@ namespace OpenSim.Region.Physics.OdePlugin
269 set 265 set
270 { 266 {
271 flying = value; 267 flying = value;
272// m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying); 268// m_log.DebugFormat("[ODE CHARACTER]: Set OdeCharacter Flying to {0}", flying);
273 } 269 }
274 } 270 }
275 271
@@ -440,7 +436,7 @@ namespace OpenSim.Region.Physics.OdePlugin
440 } 436 }
441 else 437 else
442 { 438 {
443 m_log.Warn("[PHYSICS]: Got a NaN Position from Scene on a Character"); 439 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Position from Scene on character {0}", Name);
444 } 440 }
445 } 441 }
446 } 442 }
@@ -467,7 +463,7 @@ namespace OpenSim.Region.Physics.OdePlugin
467 463
468 Vector3 SetSize = value; 464 Vector3 SetSize = value;
469 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f; 465 m_tainted_CAPSULE_LENGTH = (SetSize.Z * 1.15f) - CAPSULE_RADIUS * 2.0f;
470// m_log.Info("[SIZE]: " + CAPSULE_LENGTH); 466// m_log.Info("[ODE CHARACTER]: " + CAPSULE_LENGTH);
471 467
472 // If we reset velocity here, then an avatar stalls when it crosses a border for the first time 468 // If we reset velocity here, then an avatar stalls when it crosses a border for the first time
473 // (as the height of the new root agent is set). 469 // (as the height of the new root agent is set).
@@ -477,7 +473,7 @@ namespace OpenSim.Region.Physics.OdePlugin
477 } 473 }
478 else 474 else
479 { 475 {
480 m_log.Warn("[PHYSICS]: Got a NaN Size from Scene on a Character"); 476 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN Size from Scene on {0}", Name);
481 } 477 }
482 } 478 }
483 } 479 }
@@ -529,7 +525,6 @@ namespace OpenSim.Region.Physics.OdePlugin
529 } 525 }
530 } 526 }
531 527
532
533 // movementVector.Z is zero 528 // movementVector.Z is zero
534 529
535 // calculate tilt components based on desired amount of tilt and current (snapped) heading. 530 // calculate tilt components based on desired amount of tilt and current (snapped) heading.
@@ -537,7 +532,7 @@ namespace OpenSim.Region.Physics.OdePlugin
537 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane; 532 float xTiltComponent = -movementVector.X * m_tiltMagnitudeWhenProjectedOnXYPlane;
538 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane; 533 float yTiltComponent = -movementVector.Y * m_tiltMagnitudeWhenProjectedOnXYPlane;
539 534
540 //m_log.Debug("[PHYSICS] changing avatar tilt"); 535 //m_log.Debug("[ODE CHARACTER]: changing avatar tilt");
541 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent); 536 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, xTiltComponent);
542 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced 537 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, xTiltComponent); // must be same as lowstop, else a different, spurious tilt is introduced
543 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent); 538 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, yTiltComponent);
@@ -547,124 +542,6 @@ namespace OpenSim.Region.Physics.OdePlugin
547 } 542 }
548 543
549 /// <summary> 544 /// <summary>
550 /// This creates the Avatar's physical Surrogate at the position supplied
551 /// </summary>
552 /// <param name="npositionX"></param>
553 /// <param name="npositionY"></param>
554 /// <param name="npositionZ"></param>
555
556 // WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
557 // to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
558 // place that is safe to call this routine AvatarGeomAndBodyCreation.
559 private void AvatarGeomAndBodyCreation(float npositionX, float npositionY, float npositionZ, float tensor)
560 {
561 //CAPSULE_LENGTH = -5;
562 //CAPSULE_RADIUS = -5;
563 int dAMotorEuler = 1;
564 _parent_scene.waitForSpaceUnlock(_parent_scene.space);
565 if (CAPSULE_LENGTH <= 0)
566 {
567 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
568 CAPSULE_LENGTH = 0.01f;
569
570 }
571
572 if (CAPSULE_RADIUS <= 0)
573 {
574 m_log.Warn("[PHYSICS]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
575 CAPSULE_RADIUS = 0.01f;
576
577 }
578 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
579
580 d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
581 d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
582
583 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
584 Body = d.BodyCreate(_parent_scene.world);
585 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
586
587 _position.X = npositionX;
588 _position.Y = npositionY;
589 _position.Z = npositionZ;
590
591 m_taintPosition = _position;
592
593 d.BodySetMass(Body, ref ShellMass);
594 d.Matrix3 m_caprot;
595 // 90 Stand up on the cap of the capped cyllinder
596 if (_parent_scene.IsAvCapsuleTilted)
597 {
598 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
599 }
600 else
601 {
602 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
603 }
604
605
606 d.GeomSetRotation(Shell, ref m_caprot);
607 d.BodySetRotation(Body, ref m_caprot);
608
609 d.GeomSetBody(Shell, Body);
610
611
612 // The purpose of the AMotor here is to keep the avatar's physical
613 // surrogate from rotating while moving
614 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
615 d.JointAttach(Amotor, Body, IntPtr.Zero);
616 d.JointSetAMotorMode(Amotor, dAMotorEuler);
617 d.JointSetAMotorNumAxes(Amotor, 3);
618 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
619 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
620 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
621 d.JointSetAMotorAngle(Amotor, 0, 0);
622 d.JointSetAMotorAngle(Amotor, 1, 0);
623 d.JointSetAMotorAngle(Amotor, 2, 0);
624
625 // These lowstops and high stops are effectively (no wiggle room)
626 if (_parent_scene.IsAvCapsuleTilted)
627 {
628 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
629 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
630 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
631 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
632 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
633 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
634 }
635 else
636 {
637 #region Documentation of capsule motor LowStop and HighStop parameters
638 // Intentionally introduce some tilt into the capsule by setting
639 // the motor stops to small epsilon values. This small tilt prevents
640 // the capsule from falling into the terrain; a straight-up capsule
641 // (with -0..0 motor stops) falls into the terrain for reasons yet
642 // to be comprehended in their entirety.
643 #endregion
644 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
645 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
646 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
647 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
648 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
649 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
650 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
651 }
652
653 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
654 // capped cyllinder will fall over
655 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
656 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
657
658 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
659 //d.QfromR(
660 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
661 //
662 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
663 //standupStraight();
664 }
665
666 //
667 /// <summary>
668 /// Uses the capped cyllinder volume formula to calculate the avatar's mass. 545 /// Uses the capped cyllinder volume formula to calculate the avatar's mass.
669 /// This may be used in calculations in the scene/scenepresence 546 /// This may be used in calculations in the scene/scenepresence
670 /// </summary> 547 /// </summary>
@@ -774,7 +651,7 @@ namespace OpenSim.Region.Physics.OdePlugin
774 } 651 }
775 else 652 else
776 { 653 {
777 m_log.Warn("[PHYSICS]: Got a NaN velocity from Scene in a Character"); 654 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN velocity from Scene for {0}", Name);
778 } 655 }
779 656
780// m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity); 657// m_log.DebugFormat("[PHYSICS]: Set target velocity of {0}", m_taintTargetVelocity);
@@ -836,7 +713,6 @@ namespace OpenSim.Region.Physics.OdePlugin
836 m_taintForce += force; 713 m_taintForce += force;
837 _parent_scene.AddPhysicsActorTaint(this); 714 _parent_scene.AddPhysicsActorTaint(this);
838 715
839 //doForce(force);
840 // If uncommented, things get pushed off world 716 // If uncommented, things get pushed off world
841 // 717 //
842 // m_log.Debug("Push!"); 718 // m_log.Debug("Push!");
@@ -852,7 +728,7 @@ namespace OpenSim.Region.Physics.OdePlugin
852 } 728 }
853 else 729 else
854 { 730 {
855 m_log.Warn("[PHYSICS]: Got a NaN force applied to a Character"); 731 m_log.WarnFormat("[ODE CHARACTER]: Got a NaN force applied to {0}", Name);
856 } 732 }
857 //m_lastUpdateSent = false; 733 //m_lastUpdateSent = false;
858 } 734 }
@@ -861,15 +737,6 @@ namespace OpenSim.Region.Physics.OdePlugin
861 { 737 {
862 } 738 }
863 739
864 /// <summary>
865 /// After all of the forces add up with 'add force' we apply them with doForce
866 /// </summary>
867 /// <param name="force"></param>
868 public void doForce(Vector3 force)
869 {
870 d.BodyAddForce(Body, force.X, force.Y, force.Z);
871 }
872
873 public override void SetMomentum(Vector3 momentum) 740 public override void SetMomentum(Vector3 momentum)
874 { 741 {
875 } 742 }
@@ -878,9 +745,8 @@ namespace OpenSim.Region.Physics.OdePlugin
878 /// Called from Simulate 745 /// Called from Simulate
879 /// This is the avatar's movement control + PID Controller 746 /// This is the avatar's movement control + PID Controller
880 /// </summary> 747 /// </summary>
881 /// <param name="defects"> 748 /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
882 /// If there is something wrong with the character (e.g. its position is non-finite) 749 /// position or velocity).
883 /// then it is added to this list. The ODE structures associated with it are also destroyed.
884 /// </param> 750 /// </param>
885 internal void Move(List<OdeCharacter> defects) 751 internal void Move(List<OdeCharacter> defects)
886 { 752 {
@@ -903,12 +769,11 @@ namespace OpenSim.Region.Physics.OdePlugin
903 769
904 if (!localPos.IsFinite()) 770 if (!localPos.IsFinite())
905 { 771 {
906 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!"); 772 m_log.WarnFormat(
773 "[ODE CHARACTER]: Avatar position of {0} for {1} is non-finite! Removing from physics scene.",
774 localPos, Name);
907 775
908 defects.Add(this); 776 defects.Add(this);
909 // _parent_scene.RemoveCharacter(this);
910
911 DestroyOdeStructures();
912 777
913 return; 778 return;
914 } 779 }
@@ -1035,26 +900,31 @@ namespace OpenSim.Region.Physics.OdePlugin
1035 900
1036 if (vec.IsFinite()) 901 if (vec.IsFinite())
1037 { 902 {
1038 doForce(vec); 903 // Apply the total force acting on this avatar
904 d.BodyAddForce(Body, vec.X, vec.Y, vec.Z);
1039 905
1040 if (!_zeroFlag) 906 if (!_zeroFlag)
1041 AlignAvatarTiltWithCurrentDirectionOfMovement(vec); 907 AlignAvatarTiltWithCurrentDirectionOfMovement(vec);
1042 } 908 }
1043 else 909 else
1044 { 910 {
1045 m_log.Warn("[PHYSICS]: Got a NaN force vector in Move()"); 911 m_log.WarnFormat(
1046 m_log.Warn("[PHYSICS]: Avatar Position is non-finite!"); 912 "[ODE CHARACTER]: Got a NaN force vector {0} in Move() for {1}. Removing character from physics scene.",
913 vec, Name);
914
1047 defects.Add(this); 915 defects.Add(this);
1048 // _parent_scene.RemoveCharacter(this);
1049 916
1050 DestroyOdeStructures(); 917 return;
1051 } 918 }
1052 } 919 }
1053 920
1054 /// <summary> 921 /// <summary>
1055 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence. 922 /// Updates the reported position and velocity. This essentially sends the data up to ScenePresence.
1056 /// </summary> 923 /// </summary>
1057 internal void UpdatePositionAndVelocity() 924 /// <param name="defects">The character will be added to this list if there is something wrong (non-finite
925 /// position or velocity).
926 /// </param>
927 internal void UpdatePositionAndVelocity(List<OdeCharacter> defects)
1058 { 928 {
1059 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit! 929 // no lock; called from Simulate() -- if you call this from elsewhere, gotta lock or do Monitor.Enter/Exit!
1060 d.Vector3 newPos; 930 d.Vector3 newPos;
@@ -1065,10 +935,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1065 catch (NullReferenceException) 935 catch (NullReferenceException)
1066 { 936 {
1067 bad = true; 937 bad = true;
1068 _parent_scene.BadCharacter(this); 938 defects.Add(this);
1069 newPos = new d.Vector3(_position.X, _position.Y, _position.Z); 939 newPos = new d.Vector3(_position.X, _position.Y, _position.Z);
1070 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem! 940 base.RaiseOutOfBounds(_position); // Tells ScenePresence that there's a problem!
1071 m_log.WarnFormat("[ODEPLUGIN]: Avatar Null reference for Avatar {0}, physical actor {1}", m_name, m_uuid); 941 m_log.WarnFormat("[ODE CHARACTER]: Avatar Null reference for Avatar {0}, physical actor {1}", Name, m_uuid);
942
943 return;
1072 } 944 }
1073 945
1074 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!) 946 // kluge to keep things in bounds. ODE lets dead avatars drift away (they should be removed!)
@@ -1137,6 +1009,123 @@ namespace OpenSim.Region.Physics.OdePlugin
1137 } 1009 }
1138 1010
1139 /// <summary> 1011 /// <summary>
1012 /// This creates the Avatar's physical Surrogate in ODE at the position supplied
1013 /// </summary>
1014 /// <remarks>
1015 /// WARNING: This MUST NOT be called outside of ProcessTaints, else we can have unsynchronized access
1016 /// to ODE internals. ProcessTaints is called from within thread-locked Simulate(), so it is the only
1017 /// place that is safe to call this routine AvatarGeomAndBodyCreation.
1018 /// </remarks>
1019 /// <param name="npositionX"></param>
1020 /// <param name="npositionY"></param>
1021 /// <param name="npositionZ"></param>
1022 /// <param name="tensor"></param>
1023 private void CreateOdeStructures(float npositionX, float npositionY, float npositionZ, float tensor)
1024 {
1025 int dAMotorEuler = 1;
1026// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1027 if (CAPSULE_LENGTH <= 0)
1028 {
1029 m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
1030 CAPSULE_LENGTH = 0.01f;
1031 }
1032
1033 if (CAPSULE_RADIUS <= 0)
1034 {
1035 m_log.Warn("[ODE CHARACTER]: The capsule size you specified in opensim.ini is invalid! Setting it to the smallest possible size!");
1036 CAPSULE_RADIUS = 0.01f;
1037 }
1038
1039 Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH);
1040
1041 d.GeomSetCategoryBits(Shell, (int)m_collisionCategories);
1042 d.GeomSetCollideBits(Shell, (int)m_collisionFlags);
1043
1044 d.MassSetCapsuleTotal(out ShellMass, m_mass, 2, CAPSULE_RADIUS, CAPSULE_LENGTH);
1045 Body = d.BodyCreate(_parent_scene.world);
1046 d.BodySetPosition(Body, npositionX, npositionY, npositionZ);
1047
1048 _position.X = npositionX;
1049 _position.Y = npositionY;
1050 _position.Z = npositionZ;
1051
1052 m_taintPosition = _position;
1053
1054 d.BodySetMass(Body, ref ShellMass);
1055 d.Matrix3 m_caprot;
1056 // 90 Stand up on the cap of the capped cyllinder
1057 if (_parent_scene.IsAvCapsuleTilted)
1058 {
1059 d.RFromAxisAndAngle(out m_caprot, 1, 0, 1, (float)(Math.PI / 2));
1060 }
1061 else
1062 {
1063 d.RFromAxisAndAngle(out m_caprot, 0, 0, 1, (float)(Math.PI / 2));
1064 }
1065
1066 d.GeomSetRotation(Shell, ref m_caprot);
1067 d.BodySetRotation(Body, ref m_caprot);
1068
1069 d.GeomSetBody(Shell, Body);
1070
1071 // The purpose of the AMotor here is to keep the avatar's physical
1072 // surrogate from rotating while moving
1073 Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero);
1074 d.JointAttach(Amotor, Body, IntPtr.Zero);
1075 d.JointSetAMotorMode(Amotor, dAMotorEuler);
1076 d.JointSetAMotorNumAxes(Amotor, 3);
1077 d.JointSetAMotorAxis(Amotor, 0, 0, 1, 0, 0);
1078 d.JointSetAMotorAxis(Amotor, 1, 0, 0, 1, 0);
1079 d.JointSetAMotorAxis(Amotor, 2, 0, 0, 0, 1);
1080 d.JointSetAMotorAngle(Amotor, 0, 0);
1081 d.JointSetAMotorAngle(Amotor, 1, 0);
1082 d.JointSetAMotorAngle(Amotor, 2, 0);
1083
1084 // These lowstops and high stops are effectively (no wiggle room)
1085 if (_parent_scene.IsAvCapsuleTilted)
1086 {
1087 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, -0.000000000001f);
1088 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0.000000000001f);
1089 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, -0.000000000001f);
1090 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.000000000001f);
1091 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0.000000000001f);
1092 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.000000000001f);
1093 }
1094 else
1095 {
1096 #region Documentation of capsule motor LowStop and HighStop parameters
1097 // Intentionally introduce some tilt into the capsule by setting
1098 // the motor stops to small epsilon values. This small tilt prevents
1099 // the capsule from falling into the terrain; a straight-up capsule
1100 // (with -0..0 motor stops) falls into the terrain for reasons yet
1101 // to be comprehended in their entirety.
1102 #endregion
1103 AlignAvatarTiltWithCurrentDirectionOfMovement(Vector3.Zero);
1104 d.JointSetAMotorParam(Amotor, (int)dParam.LowStop, 0.08f);
1105 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop3, -0f);
1106 d.JointSetAMotorParam(Amotor, (int)dParam.LoStop2, 0.08f);
1107 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop, 0.08f); // must be same as lowstop, else a different, spurious tilt is introduced
1108 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop3, 0f); // same as lowstop
1109 d.JointSetAMotorParam(Amotor, (int)dParam.HiStop2, 0.08f); // same as lowstop
1110 }
1111
1112 // Fudge factor is 1f by default, we're setting it to 0. We don't want it to Fudge or the
1113 // capped cyllinder will fall over
1114 d.JointSetAMotorParam(Amotor, (int)dParam.FudgeFactor, 0f);
1115 d.JointSetAMotorParam(Amotor, (int)dParam.FMax, tensor);
1116
1117 //d.Matrix3 bodyrotation = d.BodyGetRotation(Body);
1118 //d.QfromR(
1119 //d.Matrix3 checkrotation = new d.Matrix3(0.7071068,0.5, -0.7071068,
1120 //
1121 //m_log.Info("[PHYSICSAV]: Rotation: " + bodyrotation.M00 + " : " + bodyrotation.M01 + " : " + bodyrotation.M02 + " : " + bodyrotation.M10 + " : " + bodyrotation.M11 + " : " + bodyrotation.M12 + " : " + bodyrotation.M20 + " : " + bodyrotation.M21 + " : " + bodyrotation.M22);
1122 //standupStraight();
1123
1124 _parent_scene.geom_name_map[Shell] = Name;
1125 _parent_scene.actor_name_map[Shell] = this;
1126 }
1127
1128 /// <summary>
1140 /// Cleanup the things we use in the scene. 1129 /// Cleanup the things we use in the scene.
1141 /// </summary> 1130 /// </summary>
1142 internal void Destroy() 1131 internal void Destroy()
@@ -1148,7 +1137,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1148 /// <summary> 1137 /// <summary>
1149 /// Used internally to destroy the ODE structures associated with this character. 1138 /// Used internally to destroy the ODE structures associated with this character.
1150 /// </summary> 1139 /// </summary>
1151 private void DestroyOdeStructures() 1140 internal void DestroyOdeStructures()
1152 { 1141 {
1153 // destroy avatar capsule and related ODE data 1142 // destroy avatar capsule and related ODE data
1154 if (Amotor != IntPtr.Zero) 1143 if (Amotor != IntPtr.Zero)
@@ -1159,13 +1148,12 @@ namespace OpenSim.Region.Physics.OdePlugin
1159 } 1148 }
1160 1149
1161 //kill the Geometry 1150 //kill the Geometry
1162 _parent_scene.waitForSpaceUnlock(_parent_scene.space); 1151// _parent_scene.waitForSpaceUnlock(_parent_scene.space);
1163 1152
1164 if (Body != IntPtr.Zero) 1153 if (Body != IntPtr.Zero)
1165 { 1154 {
1166 //kill the body 1155 //kill the body
1167 d.BodyDestroy(Body); 1156 d.BodyDestroy(Body);
1168
1169 Body = IntPtr.Zero; 1157 Body = IntPtr.Zero;
1170 } 1158 }
1171 1159
@@ -1173,6 +1161,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1173 { 1161 {
1174 d.GeomDestroy(Shell); 1162 d.GeomDestroy(Shell);
1175 _parent_scene.geom_name_map.Remove(Shell); 1163 _parent_scene.geom_name_map.Remove(Shell);
1164 _parent_scene.actor_name_map.Remove(Shell);
1165
1176 Shell = IntPtr.Zero; 1166 Shell = IntPtr.Zero;
1177 } 1167 }
1178 } 1168 }
@@ -1261,7 +1251,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1261 // FIXME: This is not a good solution since it's subject to a race condition if a force is another 1251 // FIXME: This is not a good solution since it's subject to a race condition if a force is another
1262 // thread sets a new force while we're in this loop (since it could be obliterated by 1252 // thread sets a new force while we're in this loop (since it could be obliterated by
1263 // m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force. 1253 // m_taintForce = Vector3.Zero. Need to lock ProcessTaints() when we set a new tainted force.
1264 doForce(m_taintForce); 1254 d.BodyAddForce(Body, m_taintForce.X, m_taintForce.Y, m_taintForce.Z);
1265 } 1255 }
1266 1256
1267 m_taintForce = Vector3.Zero; 1257 m_taintForce = Vector3.Zero;
@@ -1277,15 +1267,13 @@ namespace OpenSim.Region.Physics.OdePlugin
1277 // Create avatar capsule and related ODE data 1267 // Create avatar capsule and related ODE data
1278 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) 1268 if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero))
1279 { 1269 {
1280 m_log.Warn("[PHYSICS]: re-creating the following avatar ODE data, even though it already exists - " 1270 m_log.Warn("[ODE CHARACTER]: re-creating the following avatar ODE data for " + Name + ", even though it already exists - "
1281 + (Shell!=IntPtr.Zero ? "Shell ":"") 1271 + (Shell!=IntPtr.Zero ? "Shell ":"")
1282 + (Body!=IntPtr.Zero ? "Body ":"") 1272 + (Body!=IntPtr.Zero ? "Body ":"")
1283 + (Amotor!=IntPtr.Zero ? "Amotor ":"")); 1273 + (Amotor!=IntPtr.Zero ? "Amotor ":""));
1284 } 1274 }
1285 AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z, m_tensor); 1275
1286 1276 CreateOdeStructures(_position.X, _position.Y, _position.Z, m_tensor);
1287 _parent_scene.geom_name_map[Shell] = m_name;
1288 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
1289 _parent_scene.AddCharacter(this); 1277 _parent_scene.AddCharacter(this);
1290 } 1278 }
1291 else 1279 else
@@ -1301,17 +1289,19 @@ namespace OpenSim.Region.Physics.OdePlugin
1301 { 1289 {
1302 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero) 1290 if (Shell != IntPtr.Zero && Body != IntPtr.Zero && Amotor != IntPtr.Zero)
1303 { 1291 {
1304// m_log.DebugFormat("[PHYSICS]: Changing capsule size"); 1292// m_log.DebugFormat(
1293// "[ODE CHARACTER]: Changing capsule size from {0} to {1} for {2}",
1294// CAPSULE_LENGTH, m_tainted_CAPSULE_LENGTH, Name);
1305 1295
1306 m_pidControllerActive = true; 1296 m_pidControllerActive = true;
1297
1307 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate() 1298 // no lock needed on _parent_scene.OdeLock because we are called from within the thread lock in OdePlugin's simulate()
1308 d.JointDestroy(Amotor); 1299 DestroyOdeStructures();
1300
1309 float prevCapsule = CAPSULE_LENGTH; 1301 float prevCapsule = CAPSULE_LENGTH;
1310 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH; 1302 CAPSULE_LENGTH = m_tainted_CAPSULE_LENGTH;
1311 //m_log.Info("[SIZE]: " + CAPSULE_LENGTH.ToString()); 1303
1312 d.BodyDestroy(Body); 1304 CreateOdeStructures(
1313 d.GeomDestroy(Shell);
1314 AvatarGeomAndBodyCreation(
1315 _position.X, 1305 _position.X,
1316 _position.Y, 1306 _position.Y,
1317 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor); 1307 _position.Z + (Math.Abs(CAPSULE_LENGTH - prevCapsule) * 2), m_tensor);
@@ -1319,13 +1309,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1319 // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't 1309 // As with Size, we reset velocity. However, this isn't strictly necessary since it doesn't
1320 // appear to stall initial region crossings when done here. Being done for consistency. 1310 // appear to stall initial region crossings when done here. Being done for consistency.
1321// Velocity = Vector3.Zero; 1311// Velocity = Vector3.Zero;
1322
1323 _parent_scene.geom_name_map[Shell] = m_name;
1324 _parent_scene.actor_name_map[Shell] = (PhysicsActor)this;
1325 } 1312 }
1326 else 1313 else
1327 { 1314 {
1328 m_log.Warn("[PHYSICS]: trying to change capsule size, but the following ODE data is missing - " 1315 m_log.Warn("[ODE CHARACTER]: trying to change capsule size for " + Name + ", but the following ODE data is missing - "
1329 + (Shell==IntPtr.Zero ? "Shell ":"") 1316 + (Shell==IntPtr.Zero ? "Shell ":"")
1330 + (Body==IntPtr.Zero ? "Body ":"") 1317 + (Body==IntPtr.Zero ? "Body ":"")
1331 + (Amotor==IntPtr.Zero ? "Amotor ":"")); 1318 + (Amotor==IntPtr.Zero ? "Amotor ":""));
diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
index f07cf46..af05a15 100644
--- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
+++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs
@@ -184,7 +184,6 @@ namespace OpenSim.Region.Physics.OdePlugin
184 private bool m_lastUpdateSent; 184 private bool m_lastUpdateSent;
185 185
186 public IntPtr Body = IntPtr.Zero; 186 public IntPtr Body = IntPtr.Zero;
187 public String Name { get; private set; }
188 private Vector3 _target_velocity; 187 private Vector3 _target_velocity;
189 private d.Mass pMass; 188 private d.Mass pMass;
190 189
@@ -273,7 +272,6 @@ namespace OpenSim.Region.Physics.OdePlugin
273 272
274 m_taintadd = true; 273 m_taintadd = true;
275 _parent_scene.AddPhysicsActorTaint(this); 274 _parent_scene.AddPhysicsActorTaint(this);
276 // don't do .add() here; old geoms get recycled with the same hash
277 } 275 }
278 276
279 public override int PhysicsActorType 277 public override int PhysicsActorType
@@ -857,7 +855,7 @@ namespace OpenSim.Region.Physics.OdePlugin
857 m_MeshToTriMeshMap[mesh] = _triMeshData; 855 m_MeshToTriMeshMap[mesh] = _triMeshData;
858 } 856 }
859 857
860 _parent_scene.waitForSpaceUnlock(m_targetSpace); 858// _parent_scene.waitForSpaceUnlock(m_targetSpace);
861 try 859 try
862 { 860 {
863 if (prim_geom == IntPtr.Zero) 861 if (prim_geom == IntPtr.Zero)
@@ -1380,7 +1378,7 @@ Console.WriteLine("CreateGeom:");
1380 { 1378 {
1381 if (((_size.X / 2f) > 0f)) 1379 if (((_size.X / 2f) > 0f))
1382 { 1380 {
1383 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1381// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1384 try 1382 try
1385 { 1383 {
1386//Console.WriteLine(" CreateGeom 1"); 1384//Console.WriteLine(" CreateGeom 1");
@@ -1394,7 +1392,7 @@ Console.WriteLine("CreateGeom:");
1394 } 1392 }
1395 else 1393 else
1396 { 1394 {
1397 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1395// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1398 try 1396 try
1399 { 1397 {
1400//Console.WriteLine(" CreateGeom 2"); 1398//Console.WriteLine(" CreateGeom 2");
@@ -1409,7 +1407,7 @@ Console.WriteLine("CreateGeom:");
1409 } 1407 }
1410 else 1408 else
1411 { 1409 {
1412 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1410// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1413 try 1411 try
1414 { 1412 {
1415//Console.WriteLine(" CreateGeom 3"); 1413//Console.WriteLine(" CreateGeom 3");
@@ -1424,7 +1422,7 @@ Console.WriteLine("CreateGeom:");
1424 } 1422 }
1425 else 1423 else
1426 { 1424 {
1427 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1425// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1428 try 1426 try
1429 { 1427 {
1430//Console.WriteLine(" CreateGeom 4"); 1428//Console.WriteLine(" CreateGeom 4");
@@ -1577,17 +1575,17 @@ Console.WriteLine(" JointCreateFixed");
1577 { 1575 {
1578 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); 1576 // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position);
1579 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); 1577 // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position);
1580 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1578// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1581 1579
1582 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace); 1580 IntPtr tempspace = _parent_scene.recalculateSpaceForGeom(prim_geom, _position, m_targetSpace);
1583 m_targetSpace = tempspace; 1581 m_targetSpace = tempspace;
1584 1582
1585 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1583// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1586 if (prim_geom != IntPtr.Zero) 1584 if (prim_geom != IntPtr.Zero)
1587 { 1585 {
1588 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); 1586 d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z);
1589 1587
1590 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1588// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1591 d.SpaceAdd(m_targetSpace, prim_geom); 1589 d.SpaceAdd(m_targetSpace, prim_geom);
1592 } 1590 }
1593 } 1591 }
@@ -1978,7 +1976,7 @@ Console.WriteLine(" JointCreateFixed");
1978 1976
1979 if (d.SpaceQuery(m_targetSpace, prim_geom)) 1977 if (d.SpaceQuery(m_targetSpace, prim_geom))
1980 { 1978 {
1981 _parent_scene.waitForSpaceUnlock(m_targetSpace); 1979// _parent_scene.waitForSpaceUnlock(m_targetSpace);
1982 d.SpaceRemove(m_targetSpace, prim_geom); 1980 d.SpaceRemove(m_targetSpace, prim_geom);
1983 } 1981 }
1984 1982
diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
index 43d852b..0456f56 100644
--- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
+++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs
@@ -188,8 +188,20 @@ namespace OpenSim.Region.Physics.OdePlugin
188 private d.NearCallback nearCallback; 188 private d.NearCallback nearCallback;
189 public d.TriCallback triCallback; 189 public d.TriCallback triCallback;
190 public d.TriArrayCallback triArrayCallback; 190 public d.TriArrayCallback triArrayCallback;
191
192 /// <summary>
193 /// Avatars in the physics scene.
194 /// </summary>
191 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>(); 195 private readonly HashSet<OdeCharacter> _characters = new HashSet<OdeCharacter>();
196
197 /// <summary>
198 /// Prims in the physics scene.
199 /// </summary>
192 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>(); 200 private readonly HashSet<OdePrim> _prims = new HashSet<OdePrim>();
201
202 /// <summary>
203 /// Prims in the physics scene that are subject to physics, not just collisions.
204 /// </summary>
193 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>(); 205 private readonly HashSet<OdePrim> _activeprims = new HashSet<OdePrim>();
194 206
195 /// <summary> 207 /// <summary>
@@ -215,7 +227,14 @@ namespace OpenSim.Region.Physics.OdePlugin
215 /// </remarks> 227 /// </remarks>
216 private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>(); 228 private readonly HashSet<OdePrim> _taintedPrimH = new HashSet<OdePrim>();
217 229
230 /// <summary>
231 /// Record a character that has taints to be processed.
232 /// </summary>
218 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>(); 233 private readonly HashSet<OdeCharacter> _taintedActors = new HashSet<OdeCharacter>();
234
235 /// <summary>
236 /// Keep record of contacts in the physics loop so that we can remove duplicates.
237 /// </summary>
219 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>(); 238 private readonly List<d.ContactGeom> _perloopContact = new List<d.ContactGeom>();
220 239
221 /// <summary> 240 /// <summary>
@@ -227,18 +246,58 @@ namespace OpenSim.Region.Physics.OdePlugin
227 /// A dictionary of collision event changes that are waiting to be processed. 246 /// A dictionary of collision event changes that are waiting to be processed.
228 /// </summary> 247 /// </summary>
229 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>(); 248 private readonly Dictionary<uint, PhysicsActor> _collisionEventPrimChanges = new Dictionary<uint, PhysicsActor>();
230 249
231 private readonly HashSet<OdeCharacter> _badCharacter = new HashSet<OdeCharacter>(); 250 /// <summary>
251 /// Maps a unique geometry id (a memory location) to a physics actor name.
252 /// </summary>
253 /// <remarks>
254 /// Only actors participating in collisions have geometries. This has to be maintained separately from
255 /// actor_name_map because terrain and water currently don't conceptually have a physics actor of their own
256 /// apart from the singleton PANull
257 /// </remarks>
232 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>(); 258 public Dictionary<IntPtr, String> geom_name_map = new Dictionary<IntPtr, String>();
259
260 /// <summary>
261 /// Maps a unique geometry id (a memory location) to a physics actor.
262 /// </summary>
263 /// <remarks>
264 /// Only actors participating in collisions have geometries.
265 /// </remarks>
233 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>(); 266 public Dictionary<IntPtr, PhysicsActor> actor_name_map = new Dictionary<IntPtr, PhysicsActor>();
267
268 /// <summary>
269 /// Defects list to remove characters that no longer have finite positions due to some other bug.
270 /// </summary>
271 /// <remarks>
272 /// Used repeatedly in Simulate() but initialized once here.
273 /// </remarks>
274 private readonly List<OdeCharacter> defects = new List<OdeCharacter>();
275
234 private bool m_NINJA_physics_joints_enabled = false; 276 private bool m_NINJA_physics_joints_enabled = false;
235 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>(); 277 //private Dictionary<String, IntPtr> jointpart_name_map = new Dictionary<String,IntPtr>();
236 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>(); 278 private readonly Dictionary<String, List<PhysicsJoint>> joints_connecting_actor = new Dictionary<String, List<PhysicsJoint>>();
237 private d.ContactGeom[] contacts; 279 private d.ContactGeom[] contacts;
238 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>(); // lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active 280
239 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene. 281 /// <summary>
240 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>(); // can lock for longer. accessed only by OdeScene. 282 /// Lock only briefly. accessed by external code (to request new joints) and by OdeScene.Simulate() to move those joints into pending/active
241 private readonly List<string> requestedJointsToBeDeleted = new List<string>(); // lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active 283 /// </summary>
284 private readonly List<PhysicsJoint> requestedJointsToBeCreated = new List<PhysicsJoint>();
285
286 /// <summary>
287 /// can lock for longer. accessed only by OdeScene.
288 /// </summary>
289 private readonly List<PhysicsJoint> pendingJoints = new List<PhysicsJoint>();
290
291 /// <summary>
292 /// can lock for longer. accessed only by OdeScene.
293 /// </summary>
294 private readonly List<PhysicsJoint> activeJoints = new List<PhysicsJoint>();
295
296 /// <summary>
297 /// lock only briefly. accessed by external code (to request deletion of joints) and by OdeScene.Simulate() to move those joints out of pending/active
298 /// </summary>
299 private readonly List<string> requestedJointsToBeDeleted = new List<string>();
300
242 private Object externalJointRequestsLock = new Object(); 301 private Object externalJointRequestsLock = new Object();
243 private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>(); 302 private readonly Dictionary<String, PhysicsJoint> SOPName_to_activeJoint = new Dictionary<String, PhysicsJoint>();
244 private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>(); 303 private readonly Dictionary<String, PhysicsJoint> SOPName_to_pendingJoint = new Dictionary<String, PhysicsJoint>();
@@ -318,8 +377,7 @@ namespace OpenSim.Region.Physics.OdePlugin
318 /// <param value="name">Name of the scene. Useful in debug messages.</param> 377 /// <param value="name">Name of the scene. Useful in debug messages.</param>
319 public OdeScene(string name) 378 public OdeScene(string name)
320 { 379 {
321 m_log 380 m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
322 = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType.ToString() + "." + name);
323 381
324 Name = name; 382 Name = name;
325 383
@@ -663,11 +721,11 @@ namespace OpenSim.Region.Physics.OdePlugin
663 } 721 }
664 } 722 }
665 723
666 internal void waitForSpaceUnlock(IntPtr space) 724// internal void waitForSpaceUnlock(IntPtr space)
667 { 725// {
668 //if (space != IntPtr.Zero) 726// //if (space != IntPtr.Zero)
669 //while (d.SpaceLockQuery(space)) { } // Wait and do nothing 727// //while (d.SpaceLockQuery(space)) { } // Wait and do nothing
670 } 728// }
671 729
672// /// <summary> 730// /// <summary>
673// /// Debug space message for printing the space that a prim/avatar is in. 731// /// Debug space message for printing the space that a prim/avatar is in.
@@ -710,7 +768,7 @@ namespace OpenSim.Region.Physics.OdePlugin
710 } 768 }
711 catch (AccessViolationException) 769 catch (AccessViolationException)
712 { 770 {
713 m_log.Warn("[PHYSICS]: Unable to collide test a space"); 771 m_log.Warn("[ODE SCENE]: Unable to collide test a space");
714 return; 772 return;
715 } 773 }
716 //Colliding a space or a geom with a space or a geom. so drill down 774 //Colliding a space or a geom with a space or a geom. so drill down
@@ -760,22 +818,19 @@ namespace OpenSim.Region.Physics.OdePlugin
760 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) 818 if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact))
761 return; 819 return;
762 820
763 lock (contacts) 821 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf);
764 { 822 if (count > contacts.Length)
765 count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); 823 m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
766 if (count > contacts.Length)
767 m_log.Error("[PHYSICS]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length);
768 }
769 } 824 }
770 catch (SEHException) 825 catch (SEHException)
771 { 826 {
772 m_log.Error( 827 m_log.Error(
773 "[PHYSICS]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim."); 828 "[ODE SCENE]: The Operating system shut down ODE because of corrupt memory. This could be a result of really irregular terrain. If this repeats continuously, restart using Basic Physics and terrain fill your terrain. Restarting the sim.");
774 base.TriggerPhysicsBasedRestart(); 829 base.TriggerPhysicsBasedRestart();
775 } 830 }
776 catch (Exception e) 831 catch (Exception e)
777 { 832 {
778 m_log.WarnFormat("[PHYSICS]: Unable to collide test an object: {0}", e.Message); 833 m_log.WarnFormat("[ODE SCENE]: Unable to collide test an object: {0}", e.Message);
779 return; 834 return;
780 } 835 }
781 836
@@ -1029,6 +1084,8 @@ namespace OpenSim.Region.Physics.OdePlugin
1029 1084
1030 if (!skipThisContact) 1085 if (!skipThisContact)
1031 { 1086 {
1087 _perloopContact.Add(curContact);
1088
1032 // If we're colliding against terrain 1089 // If we're colliding against terrain
1033 if (name1 == "Terrain" || name2 == "Terrain") 1090 if (name1 == "Terrain" || name2 == "Terrain")
1034 { 1091 {
@@ -1038,7 +1095,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1038 { 1095 {
1039 // Use the movement terrain contact 1096 // Use the movement terrain contact
1040 AvatarMovementTerrainContact.geom = curContact; 1097 AvatarMovementTerrainContact.geom = curContact;
1041 _perloopContact.Add(curContact); 1098
1042 if (m_global_contactcount < maxContactsbeforedeath) 1099 if (m_global_contactcount < maxContactsbeforedeath)
1043 { 1100 {
1044 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact); 1101 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementTerrainContact);
@@ -1051,7 +1108,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1051 { 1108 {
1052 // Use the non moving terrain contact 1109 // Use the non moving terrain contact
1053 TerrainContact.geom = curContact; 1110 TerrainContact.geom = curContact;
1054 _perloopContact.Add(curContact); 1111
1055 if (m_global_contactcount < maxContactsbeforedeath) 1112 if (m_global_contactcount < maxContactsbeforedeath)
1056 { 1113 {
1057 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact); 1114 joint = d.JointCreateContact(world, contactgroup, ref TerrainContact);
@@ -1077,7 +1134,6 @@ namespace OpenSim.Region.Physics.OdePlugin
1077 1134
1078 //m_log.DebugFormat("Material: {0}", material); 1135 //m_log.DebugFormat("Material: {0}", material);
1079 m_materialContacts[material, movintYN].geom = curContact; 1136 m_materialContacts[material, movintYN].geom = curContact;
1080 _perloopContact.Add(curContact);
1081 1137
1082 if (m_global_contactcount < maxContactsbeforedeath) 1138 if (m_global_contactcount < maxContactsbeforedeath)
1083 { 1139 {
@@ -1098,9 +1154,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1098 1154
1099 if (p2 is OdePrim) 1155 if (p2 is OdePrim)
1100 material = ((OdePrim)p2).m_material; 1156 material = ((OdePrim)p2).m_material;
1157
1101 //m_log.DebugFormat("Material: {0}", material); 1158 //m_log.DebugFormat("Material: {0}", material);
1102 m_materialContacts[material, movintYN].geom = curContact; 1159 m_materialContacts[material, movintYN].geom = curContact;
1103 _perloopContact.Add(curContact);
1104 1160
1105 if (m_global_contactcount < maxContactsbeforedeath) 1161 if (m_global_contactcount < maxContactsbeforedeath)
1106 { 1162 {
@@ -1133,8 +1189,9 @@ namespace OpenSim.Region.Physics.OdePlugin
1133 //contact.normal = new d.Vector3(0, 0, 1); 1189 //contact.normal = new d.Vector3(0, 0, 1);
1134 //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f); 1190 //contact.pos = new d.Vector3(0, 0, contact.pos.Z - 5f);
1135 } 1191 }
1192
1136 WaterContact.geom = curContact; 1193 WaterContact.geom = curContact;
1137 _perloopContact.Add(curContact); 1194
1138 if (m_global_contactcount < maxContactsbeforedeath) 1195 if (m_global_contactcount < maxContactsbeforedeath)
1139 { 1196 {
1140 joint = d.JointCreateContact(world, contactgroup, ref WaterContact); 1197 joint = d.JointCreateContact(world, contactgroup, ref WaterContact);
@@ -1152,7 +1209,7 @@ namespace OpenSim.Region.Physics.OdePlugin
1152 { 1209 {
1153 // Use the Movement prim contact 1210 // Use the Movement prim contact
1154 AvatarMovementprimContact.geom = curContact; 1211 AvatarMovementprimContact.geom = curContact;
1155 _perloopContact.Add(curContact); 1212
1156 if (m_global_contactcount < maxContactsbeforedeath) 1213 if (m_global_contactcount < maxContactsbeforedeath)
1157 { 1214 {
1158 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact); 1215 joint = d.JointCreateContact(world, contactgroup, ref AvatarMovementprimContact);
@@ -1182,13 +1239,11 @@ namespace OpenSim.Region.Physics.OdePlugin
1182 1239
1183 //m_log.DebugFormat("Material: {0}", material); 1240 //m_log.DebugFormat("Material: {0}", material);
1184 m_materialContacts[material, 0].geom = curContact; 1241 m_materialContacts[material, 0].geom = curContact;
1185 _perloopContact.Add(curContact);
1186 1242
1187 if (m_global_contactcount < maxContactsbeforedeath) 1243 if (m_global_contactcount < maxContactsbeforedeath)
1188 { 1244 {
1189 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]); 1245 joint = d.JointCreateContact(world, contactgroup, ref m_materialContacts[material, 0]);
1190 m_global_contactcount++; 1246 m_global_contactcount++;
1191
1192 } 1247 }
1193 } 1248 }
1194 } 1249 }
@@ -1217,69 +1272,65 @@ namespace OpenSim.Region.Physics.OdePlugin
1217 1272
1218 private bool checkDupe(d.ContactGeom contactGeom, int atype) 1273 private bool checkDupe(d.ContactGeom contactGeom, int atype)
1219 { 1274 {
1220 bool result = false;
1221 //return result;
1222 if (!m_filterCollisions) 1275 if (!m_filterCollisions)
1223 return false; 1276 return false;
1224 1277
1278 bool result = false;
1279
1225 ActorTypes at = (ActorTypes)atype; 1280 ActorTypes at = (ActorTypes)atype;
1226 lock (_perloopContact) 1281
1282 foreach (d.ContactGeom contact in _perloopContact)
1227 { 1283 {
1228 foreach (d.ContactGeom contact in _perloopContact) 1284 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2))
1285 //{
1286 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2)
1287 if (at == ActorTypes.Agent)
1229 { 1288 {
1230 //if ((contact.g1 == contactGeom.g1 && contact.g2 == contactGeom.g2)) 1289 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f)
1231 //{ 1290 && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f)
1232 // || (contact.g2 == contactGeom.g1 && contact.g1 == contactGeom.g2) 1291 && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f))
1233 if (at == ActorTypes.Agent) 1292 && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1234 { 1293 {
1235 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom) 1294 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f)
1236 { 1295 {
1237 1296 //contactGeom.depth *= .00005f;
1238 if (Math.Abs(contact.depth - contactGeom.depth) < 0.052f) 1297 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1239 { 1298 // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1240 //contactGeom.depth *= .00005f; 1299 result = true;
1241 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); 1300 break;
1242 // m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); 1301 }
1243 result = true; 1302// else
1244 break; 1303// {
1245 } 1304// //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1246 else 1305// }
1247 { 1306 }
1248 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth)); 1307// else
1249 } 1308// {
1250 } 1309// //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1251 else 1310// //int i = 0;
1252 { 1311// }
1253 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z)); 1312 }
1254 //int i = 0; 1313 else if (at == ActorTypes.Prim)
1255 } 1314 {
1256 } 1315 //d.AABB aabb1 = new d.AABB();
1257 else if (at == ActorTypes.Prim) 1316 //d.AABB aabb2 = new d.AABB();
1317
1318 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1319 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1320 //aabb1.
1321 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1258 { 1322 {
1259 //d.AABB aabb1 = new d.AABB(); 1323 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z)
1260 //d.AABB aabb2 = new d.AABB(); 1324 {
1261 1325 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1262 //d.GeomGetAABB(contactGeom.g2, out aabb2);
1263 //d.GeomGetAABB(contactGeom.g1, out aabb1);
1264 //aabb1.
1265 if (((Math.Abs(contactGeom.normal.X - contact.normal.X) < 1.026f) && (Math.Abs(contactGeom.normal.Y - contact.normal.Y) < 0.303f) && (Math.Abs(contactGeom.normal.Z - contact.normal.Z) < 0.065f)) && contactGeom.g1 != LandGeom && contactGeom.g2 != LandGeom)
1266 { 1326 {
1267 if (contactGeom.normal.X == contact.normal.X && contactGeom.normal.Y == contact.normal.Y && contactGeom.normal.Z == contact.normal.Z) 1327 result = true;
1268 { 1328 break;
1269 if (Math.Abs(contact.depth - contactGeom.depth) < 0.272f)
1270 {
1271 result = true;
1272 break;
1273 }
1274 }
1275 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1276 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1277 } 1329 }
1278 1330 }
1331 //m_log.DebugFormat("[Collsion]: Depth {0}", Math.Abs(contact.depth - contactGeom.depth));
1332 //m_log.DebugFormat("[Collision]: <{0},{1},{2}>", Math.Abs(contactGeom.normal.X - contact.normal.X), Math.Abs(contactGeom.normal.Y - contact.normal.Y), Math.Abs(contactGeom.normal.Z - contact.normal.Z));
1279 } 1333 }
1280
1281 //}
1282
1283 } 1334 }
1284 } 1335 }
1285 1336
@@ -1482,90 +1533,77 @@ namespace OpenSim.Region.Physics.OdePlugin
1482 { 1533 {
1483 _perloopContact.Clear(); 1534 _perloopContact.Clear();
1484 1535
1485 lock (_characters) 1536 foreach (OdeCharacter chr in _characters)
1486 { 1537 {
1487 foreach (OdeCharacter chr in _characters) 1538 // Reset the collision values to false
1539 // since we don't know if we're colliding yet
1540 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1541 continue;
1542
1543 chr.IsColliding = false;
1544 chr.CollidingGround = false;
1545 chr.CollidingObj = false;
1546
1547 // test the avatar's geometry for collision with the space
1548 // This will return near and the space that they are the closest to
1549 // And we'll run this again against the avatar and the space segment
1550 // This will return with a bunch of possible objects in the space segment
1551 // and we'll run it again on all of them.
1552 try
1488 { 1553 {
1489 // Reset the collision values to false 1554 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
1490 // since we don't know if we're colliding yet
1491
1492 // For some reason this can happen. Don't ask...
1493 //
1494 if (chr == null)
1495 continue;
1496
1497 if (chr.Shell == IntPtr.Zero || chr.Body == IntPtr.Zero)
1498 continue;
1499
1500 chr.IsColliding = false;
1501 chr.CollidingGround = false;
1502 chr.CollidingObj = false;
1503
1504 // test the avatar's geometry for collision with the space
1505 // This will return near and the space that they are the closest to
1506 // And we'll run this again against the avatar and the space segment
1507 // This will return with a bunch of possible objects in the space segment
1508 // and we'll run it again on all of them.
1509 try
1510 {
1511 d.SpaceCollide2(space, chr.Shell, IntPtr.Zero, nearCallback);
1512 }
1513 catch (AccessViolationException)
1514 {
1515 m_log.Warn("[PHYSICS]: Unable to space collide");
1516 }
1517 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1518 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1519 //{
1520 //chr.Position.Z = terrainheight + 10.0f;
1521 //forcedZ = true;
1522 //}
1523 } 1555 }
1556 catch (AccessViolationException)
1557 {
1558 m_log.WarnFormat("[ODE SCENE]: Unable to space collide {0}", Name);
1559 }
1560
1561 //float terrainheight = GetTerrainHeightAtXY(chr.Position.X, chr.Position.Y);
1562 //if (chr.Position.Z + (chr.Velocity.Z * timeStep) < terrainheight + 10)
1563 //{
1564 //chr.Position.Z = terrainheight + 10.0f;
1565 //forcedZ = true;
1566 //}
1524 } 1567 }
1525 1568
1526 lock (_activeprims) 1569 List<OdePrim> removeprims = null;
1570 foreach (OdePrim chr in _activeprims)
1527 { 1571 {
1528 List<OdePrim> removeprims = null; 1572 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled))
1529 foreach (OdePrim chr in _activeprims)
1530 { 1573 {
1531 if (chr.Body != IntPtr.Zero && d.BodyIsEnabled(chr.Body) && (!chr.m_disabled)) 1574 try
1532 { 1575 {
1533 try 1576 lock (chr)
1534 { 1577 {
1535 lock (chr) 1578 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false)
1536 { 1579 {
1537 if (space != IntPtr.Zero && chr.prim_geom != IntPtr.Zero && chr.m_taintremove == false) 1580 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback);
1538 { 1581 }
1539 d.SpaceCollide2(space, chr.prim_geom, IntPtr.Zero, nearCallback); 1582 else
1540 } 1583 {
1541 else 1584 if (removeprims == null)
1542 { 1585 {
1543 if (removeprims == null) 1586 removeprims = new List<OdePrim>();
1544 {
1545 removeprims = new List<OdePrim>();
1546 }
1547 removeprims.Add(chr);
1548 m_log.Debug("[PHYSICS]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!");
1549 } 1587 }
1588 removeprims.Add(chr);
1589 m_log.Debug("[ODE SCENE]: unable to collide test active prim against space. The space was zero, the geom was zero or it was in the process of being removed. Removed it from the active prim list. This needs to be fixed!");
1550 } 1590 }
1551 } 1591 }
1552 catch (AccessViolationException)
1553 {
1554 m_log.Warn("[PHYSICS]: Unable to space collide");
1555 }
1556 } 1592 }
1557 } 1593 catch (AccessViolationException)
1558
1559 if (removeprims != null)
1560 {
1561 foreach (OdePrim chr in removeprims)
1562 { 1594 {
1563 _activeprims.Remove(chr); 1595 m_log.Warn("[ODE SCENE]: Unable to space collide");
1564 } 1596 }
1565 } 1597 }
1566 } 1598 }
1567 1599
1568 _perloopContact.Clear(); 1600 if (removeprims != null)
1601 {
1602 foreach (OdePrim chr in removeprims)
1603 {
1604 _activeprims.Remove(chr);
1605 }
1606 }
1569 } 1607 }
1570 1608
1571 #endregion 1609 #endregion
@@ -1685,35 +1723,29 @@ namespace OpenSim.Region.Physics.OdePlugin
1685 1723
1686 internal void AddCharacter(OdeCharacter chr) 1724 internal void AddCharacter(OdeCharacter chr)
1687 { 1725 {
1688 lock (_characters) 1726 if (!_characters.Contains(chr))
1689 { 1727 {
1690 if (!_characters.Contains(chr)) 1728 _characters.Add(chr);
1691 {
1692 _characters.Add(chr);
1693 if (chr.bad)
1694 m_log.DebugFormat("[PHYSICS] Added BAD actor {0} to characters list", chr.m_uuid);
1695 }
1696 }
1697 }
1698 1729
1699 internal void RemoveCharacter(OdeCharacter chr) 1730 if (chr.bad)
1700 { 1731 m_log.ErrorFormat("[ODE SCENE]: Added BAD actor {0} to characters list", chr.m_uuid);
1701 lock (_characters) 1732 }
1733 else
1702 { 1734 {
1703 if (_characters.Contains(chr)) 1735 m_log.ErrorFormat(
1704 { 1736 "[ODE SCENE]: Tried to add character {0} {1} but they are already in the set!",
1705 _characters.Remove(chr); 1737 chr.Name, chr.LocalID);
1706 }
1707 } 1738 }
1708 } 1739 }
1709 1740
1710 internal void BadCharacter(OdeCharacter chr) 1741 internal void RemoveCharacter(OdeCharacter chr)
1711 { 1742 {
1712 lock (_badCharacter) 1743 if (_characters.Contains(chr))
1713 { 1744 _characters.Remove(chr);
1714 if (!_badCharacter.Contains(chr)) 1745 else
1715 _badCharacter.Add(chr); 1746 m_log.ErrorFormat(
1716 } 1747 "[ODE SCENE]: Tried to remove character {0} {1} but they are not in the list!",
1748 chr.Name, chr.LocalID);
1717 } 1749 }
1718 1750
1719 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation, 1751 private PhysicsActor AddPrim(String name, Vector3 position, Vector3 size, Quaternion rotation,
@@ -1742,13 +1774,10 @@ namespace OpenSim.Region.Physics.OdePlugin
1742 internal void ActivatePrim(OdePrim prim) 1774 internal void ActivatePrim(OdePrim prim)
1743 { 1775 {
1744 // adds active prim.. (ones that should be iterated over in collisions_optimized 1776 // adds active prim.. (ones that should be iterated over in collisions_optimized
1745 lock (_activeprims) 1777 if (!_activeprims.Contains(prim))
1746 { 1778 _activeprims.Add(prim);
1747 if (!_activeprims.Contains(prim)) 1779 //else
1748 _activeprims.Add(prim); 1780 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1749 //else
1750 // m_log.Warn("[PHYSICS]: Double Entry in _activeprims detected, potential crash immenent");
1751 }
1752 } 1781 }
1753 1782
1754 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position, 1783 public override PhysicsActor AddPrimShape(string primName, PrimitiveBaseShape pbs, Vector3 position,
@@ -2027,7 +2056,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2027 //m_log.Debug("RemoveAllJointsConnectedToActor: start"); 2056 //m_log.Debug("RemoveAllJointsConnectedToActor: start");
2028 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null) 2057 if (actor.SOPName != null && joints_connecting_actor.ContainsKey(actor.SOPName) && joints_connecting_actor[actor.SOPName] != null)
2029 { 2058 {
2030
2031 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>(); 2059 List<PhysicsJoint> jointsToRemove = new List<PhysicsJoint>();
2032 //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism) 2060 //TODO: merge these 2 loops (originally it was needed to avoid altering a list being iterated over, but it is no longer needed due to the joint request queue mechanism)
2033 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName]) 2061 foreach (PhysicsJoint j in joints_connecting_actor[actor.SOPName])
@@ -2122,8 +2150,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2122 /// <param name="prim"></param> 2150 /// <param name="prim"></param>
2123 internal void DeactivatePrim(OdePrim prim) 2151 internal void DeactivatePrim(OdePrim prim)
2124 { 2152 {
2125 lock (_activeprims) 2153 _activeprims.Remove(prim);
2126 _activeprims.Remove(prim);
2127 } 2154 }
2128 2155
2129 public override void RemovePrim(PhysicsActor prim) 2156 public override void RemovePrim(PhysicsActor prim)
@@ -2138,7 +2165,6 @@ namespace OpenSim.Region.Physics.OdePlugin
2138 2165
2139 p.setPrimForRemoval(); 2166 p.setPrimForRemoval();
2140 AddPhysicsActorTaint(prim); 2167 AddPhysicsActorTaint(prim);
2141 //RemovePrimThreadLocked(p);
2142 } 2168 }
2143 } 2169 }
2144 } 2170 }
@@ -2206,7 +2232,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2206 //m_log.Warn(prim.prim_geom); 2232 //m_log.Warn(prim.prim_geom);
2207 2233
2208 if (!prim.RemoveGeom()) 2234 if (!prim.RemoveGeom())
2209 m_log.Warn("[PHYSICS]: Unable to remove prim from physics scene"); 2235 m_log.Warn("[ODE SCENE]: Unable to remove prim from physics scene");
2210 2236
2211 lock (_prims) 2237 lock (_prims)
2212 _prims.Remove(prim); 2238 _prims.Remove(prim);
@@ -2293,12 +2319,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2293 { 2319 {
2294 if (d.GeomIsSpace(currentspace)) 2320 if (d.GeomIsSpace(currentspace))
2295 { 2321 {
2296 waitForSpaceUnlock(currentspace); 2322// waitForSpaceUnlock(currentspace);
2297 d.SpaceRemove(currentspace, geom); 2323 d.SpaceRemove(currentspace, geom);
2298 } 2324 }
2299 else 2325 else
2300 { 2326 {
2301 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + currentspace + 2327 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" + currentspace +
2302 " Geom:" + geom); 2328 " Geom:" + geom);
2303 } 2329 }
2304 } 2330 }
@@ -2309,12 +2335,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2309 { 2335 {
2310 if (d.GeomIsSpace(currentspace)) 2336 if (d.GeomIsSpace(currentspace))
2311 { 2337 {
2312 waitForSpaceUnlock(sGeomIsIn); 2338// waitForSpaceUnlock(sGeomIsIn);
2313 d.SpaceRemove(sGeomIsIn, geom); 2339 d.SpaceRemove(sGeomIsIn, geom);
2314 } 2340 }
2315 else 2341 else
2316 { 2342 {
2317 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2343 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2318 sGeomIsIn + " Geom:" + geom); 2344 sGeomIsIn + " Geom:" + geom);
2319 } 2345 }
2320 } 2346 }
@@ -2327,8 +2353,8 @@ namespace OpenSim.Region.Physics.OdePlugin
2327 { 2353 {
2328 if (d.GeomIsSpace(currentspace)) 2354 if (d.GeomIsSpace(currentspace))
2329 { 2355 {
2330 waitForSpaceUnlock(currentspace); 2356// waitForSpaceUnlock(currentspace);
2331 waitForSpaceUnlock(space); 2357// waitForSpaceUnlock(space);
2332 d.SpaceRemove(space, currentspace); 2358 d.SpaceRemove(space, currentspace);
2333 // free up memory used by the space. 2359 // free up memory used by the space.
2334 2360
@@ -2337,7 +2363,7 @@ namespace OpenSim.Region.Physics.OdePlugin
2337 } 2363 }
2338 else 2364 else
2339 { 2365 {
2340 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2366 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2341 currentspace + " Geom:" + geom); 2367 currentspace + " Geom:" + geom);
2342 } 2368 }
2343 } 2369 }
@@ -2352,12 +2378,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2352 { 2378 {
2353 if (d.GeomIsSpace(currentspace)) 2379 if (d.GeomIsSpace(currentspace))
2354 { 2380 {
2355 waitForSpaceUnlock(currentspace); 2381// waitForSpaceUnlock(currentspace);
2356 d.SpaceRemove(currentspace, geom); 2382 d.SpaceRemove(currentspace, geom);
2357 } 2383 }
2358 else 2384 else
2359 { 2385 {
2360 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2386 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2361 currentspace + " Geom:" + geom); 2387 currentspace + " Geom:" + geom);
2362 } 2388 }
2363 } 2389 }
@@ -2368,12 +2394,12 @@ namespace OpenSim.Region.Physics.OdePlugin
2368 { 2394 {
2369 if (d.GeomIsSpace(sGeomIsIn)) 2395 if (d.GeomIsSpace(sGeomIsIn))
2370 { 2396 {
2371 waitForSpaceUnlock(sGeomIsIn); 2397// waitForSpaceUnlock(sGeomIsIn);
2372 d.SpaceRemove(sGeomIsIn, geom); 2398 d.SpaceRemove(sGeomIsIn, geom);
2373 } 2399 }
2374 else 2400 else
2375 { 2401 {
2376 m_log.Info("[Physics]: Invalid Scene passed to 'recalculatespace':" + 2402 m_log.Info("[ODE SCENE]: Invalid Scene passed to 'recalculatespace':" +
2377 sGeomIsIn + " Geom:" + geom); 2403 sGeomIsIn + " Geom:" + geom);
2378 } 2404 }
2379 } 2405 }
@@ -2407,9 +2433,10 @@ namespace OpenSim.Region.Physics.OdePlugin
2407 // creating a new space for prim and inserting it into main space. 2433 // creating a new space for prim and inserting it into main space.
2408 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero); 2434 staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY] = d.HashSpaceCreate(IntPtr.Zero);
2409 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space); 2435 d.GeomSetCategoryBits(staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY], (int)CollisionCategories.Space);
2410 waitForSpaceUnlock(space); 2436// waitForSpaceUnlock(space);
2411 d.SpaceSetSublevel(space, 1); 2437 d.SpaceSetSublevel(space, 1);
2412 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]); 2438 d.SpaceAdd(space, staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]);
2439
2413 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY]; 2440 return staticPrimspace[iprimspaceArrItemX, iprimspaceArrItemY];
2414 } 2441 }
2415 2442
@@ -2584,15 +2611,17 @@ namespace OpenSim.Region.Physics.OdePlugin
2584 2611
2585 /// <summary> 2612 /// <summary>
2586 /// Called after our prim properties are set Scale, position etc. 2613 /// Called after our prim properties are set Scale, position etc.
2614 /// </summary>
2615 /// <remarks>
2587 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex 2616 /// We use this event queue like method to keep changes to the physical scene occuring in the threadlocked mutex
2588 /// This assures us that we have no race conditions 2617 /// This assures us that we have no race conditions
2589 /// </summary> 2618 /// </remarks>
2590 /// <param name="prim"></param> 2619 /// <param name="actor"></param>
2591 public override void AddPhysicsActorTaint(PhysicsActor prim) 2620 public override void AddPhysicsActorTaint(PhysicsActor actor)
2592 { 2621 {
2593 if (prim is OdePrim) 2622 if (actor is OdePrim)
2594 { 2623 {
2595 OdePrim taintedprim = ((OdePrim) prim); 2624 OdePrim taintedprim = ((OdePrim)actor);
2596 lock (_taintedPrimLock) 2625 lock (_taintedPrimLock)
2597 { 2626 {
2598 if (!(_taintedPrimH.Contains(taintedprim))) 2627 if (!(_taintedPrimH.Contains(taintedprim)))
@@ -2604,18 +2633,17 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2604 _taintedPrimL.Add(taintedprim); // List for ordered readout 2633 _taintedPrimL.Add(taintedprim); // List for ordered readout
2605 } 2634 }
2606 } 2635 }
2607 return;
2608 } 2636 }
2609 else if (prim is OdeCharacter) 2637 else if (actor is OdeCharacter)
2610 { 2638 {
2611 OdeCharacter taintedchar = ((OdeCharacter)prim); 2639 OdeCharacter taintedchar = ((OdeCharacter)actor);
2612 lock (_taintedActors) 2640 lock (_taintedActors)
2613 { 2641 {
2614 if (!(_taintedActors.Contains(taintedchar))) 2642 if (!(_taintedActors.Contains(taintedchar)))
2615 { 2643 {
2616 _taintedActors.Add(taintedchar); 2644 _taintedActors.Add(taintedchar);
2617 if (taintedchar.bad) 2645 if (taintedchar.bad)
2618 m_log.DebugFormat("[PHYSICS]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid); 2646 m_log.DebugFormat("[ODE SCENE]: Added BAD actor {0} to tainted actors", taintedchar.m_uuid);
2619 } 2647 }
2620 } 2648 }
2621 } 2649 }
@@ -2711,29 +2739,18 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2711 { 2739 {
2712 try 2740 try
2713 { 2741 {
2714 // Insert, remove Characters
2715 bool processedtaints = false;
2716
2717 lock (_taintedActors) 2742 lock (_taintedActors)
2718 { 2743 {
2719 if (_taintedActors.Count > 0) 2744 if (_taintedActors.Count > 0)
2720 { 2745 {
2721 foreach (OdeCharacter character in _taintedActors) 2746 foreach (OdeCharacter character in _taintedActors)
2722 {
2723 character.ProcessTaints(); 2747 character.ProcessTaints();
2724 2748
2725 processedtaints = true; 2749 if (_taintedActors.Count > 0)
2726 //character.m_collisionscore = 0;
2727 }
2728
2729 if (processedtaints)
2730 _taintedActors.Clear(); 2750 _taintedActors.Clear();
2731 } 2751 }
2732 } 2752 }
2733 2753
2734 // Modify other objects in the scene.
2735 processedtaints = false;
2736
2737 lock (_taintedPrimLock) 2754 lock (_taintedPrimLock)
2738 { 2755 {
2739 foreach (OdePrim prim in _taintedPrimL) 2756 foreach (OdePrim prim in _taintedPrimL)
@@ -2749,7 +2766,6 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2749 prim.ProcessTaints(); 2766 prim.ProcessTaints();
2750 } 2767 }
2751 2768
2752 processedtaints = true;
2753 prim.m_collisionscore = 0; 2769 prim.m_collisionscore = 0;
2754 2770
2755 // This loop can block up the Heartbeat for a very long time on large regions. 2771 // This loop can block up the Heartbeat for a very long time on large regions.
@@ -2762,7 +2778,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2762 if (SupportsNINJAJoints) 2778 if (SupportsNINJAJoints)
2763 SimulatePendingNINJAJoints(); 2779 SimulatePendingNINJAJoints();
2764 2780
2765 if (processedtaints) 2781 if (_taintedPrimL.Count > 0)
2766 { 2782 {
2767//Console.WriteLine("Simulate calls Clear of _taintedPrim list"); 2783//Console.WriteLine("Simulate calls Clear of _taintedPrim list");
2768 _taintedPrimH.Clear(); 2784 _taintedPrimH.Clear();
@@ -2771,31 +2787,25 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2771 } 2787 }
2772 2788
2773 // Move characters 2789 // Move characters
2774 lock (_characters) 2790 foreach (OdeCharacter actor in _characters)
2791 actor.Move(defects);
2792
2793 if (defects.Count != 0)
2775 { 2794 {
2776 List<OdeCharacter> defects = new List<OdeCharacter>(); 2795 foreach (OdeCharacter actor in defects)
2777 foreach (OdeCharacter actor in _characters)
2778 {
2779 if (actor != null)
2780 actor.Move(defects);
2781 }
2782 if (0 != defects.Count)
2783 { 2796 {
2784 foreach (OdeCharacter defect in defects) 2797 RemoveCharacter(actor);
2785 { 2798 actor.DestroyOdeStructures();
2786 RemoveCharacter(defect);
2787 }
2788 } 2799 }
2800
2801 defects.Clear();
2789 } 2802 }
2790 2803
2791 // Move other active objects 2804 // Move other active objects
2792 lock (_activeprims) 2805 foreach (OdePrim prim in _activeprims)
2793 { 2806 {
2794 foreach (OdePrim prim in _activeprims) 2807 prim.m_collisionscore = 0;
2795 { 2808 prim.Move(timeStep);
2796 prim.m_collisionscore = 0;
2797 prim.Move(timeStep);
2798 }
2799 } 2809 }
2800 2810
2801 //if ((framecount % m_randomizeWater) == 0) 2811 //if ((framecount % m_randomizeWater) == 0)
@@ -2836,53 +2846,41 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
2836 } 2846 }
2837 catch (Exception e) 2847 catch (Exception e)
2838 { 2848 {
2839 m_log.ErrorFormat("[PHYSICS]: {0}, {1}, {2}", e.Message, e.TargetSite, e); 2849 m_log.ErrorFormat("[ODE SCENE]: {0}, {1}, {2}", e.Message, e.TargetSite, e);
2840 } 2850 }
2841 2851
2842 timeLeft -= ODE_STEPSIZE; 2852 timeLeft -= ODE_STEPSIZE;
2843 } 2853 }
2844 2854
2845 lock (_characters) 2855 foreach (OdeCharacter actor in _characters)
2846 { 2856 {
2847 foreach (OdeCharacter actor in _characters) 2857 if (actor.bad)
2848 { 2858 m_log.WarnFormat("[ODE SCENE]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
2849 if (actor != null)
2850 {
2851 if (actor.bad)
2852 m_log.WarnFormat("[PHYSICS]: BAD Actor {0} in _characters list was not removed?", actor.m_uuid);
2853 2859
2854 actor.UpdatePositionAndVelocity(); 2860 actor.UpdatePositionAndVelocity(defects);
2855 }
2856 }
2857 } 2861 }
2858 2862
2859 lock (_badCharacter) 2863 if (defects.Count != 0)
2860 { 2864 {
2861 if (_badCharacter.Count > 0) 2865 foreach (OdeCharacter actor in defects)
2862 { 2866 {
2863 foreach (OdeCharacter chr in _badCharacter) 2867 RemoveCharacter(actor);
2864 { 2868 actor.DestroyOdeStructures();
2865 RemoveCharacter(chr);
2866 }
2867
2868 _badCharacter.Clear();
2869 } 2869 }
2870
2871 defects.Clear();
2870 } 2872 }
2871 2873
2872 lock (_activeprims) 2874 //if (timeStep < 0.2f)
2875
2876 foreach (OdePrim prim in _activeprims)
2873 { 2877 {
2874 //if (timeStep < 0.2f) 2878 if (prim.IsPhysical && (d.BodyIsEnabled(prim.Body) || !prim._zeroFlag))
2875 { 2879 {
2876 foreach (OdePrim prim in _activeprims) 2880 prim.UpdatePositionAndVelocity();
2877 {
2878 if (prim.IsPhysical && (d.BodyIsEnabled(prim.Body) || !prim._zeroFlag))
2879 {
2880 prim.UpdatePositionAndVelocity();
2881 2881
2882 if (SupportsNINJAJoints) 2882 if (SupportsNINJAJoints)
2883 SimulateActorPendingJoints(prim); 2883 SimulateActorPendingJoints(prim);
2884 }
2885 }
2886 } 2884 }
2887 } 2885 }
2888 2886
@@ -3417,7 +3415,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3417 { 3415 {
3418 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x])) 3416 if (Single.IsNaN(resultarr2[y, x]) || Single.IsInfinity(resultarr2[y, x]))
3419 { 3417 {
3420 m_log.Warn("[PHYSICS]: Non finite heightfield element detected. Setting it to 0"); 3418 m_log.Warn("[ODE SCENE]: Non finite heightfield element detected. Setting it to 0");
3421 resultarr2[y, x] = 0; 3419 resultarr2[y, x] = 0;
3422 } 3420 }
3423 returnarr[i] = resultarr2[y, x]; 3421 returnarr[i] = resultarr2[y, x];
@@ -3448,7 +3446,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3448 private void SetTerrain(float[] heightMap, Vector3 pOffset) 3446 private void SetTerrain(float[] heightMap, Vector3 pOffset)
3449 { 3447 {
3450 int startTime = Util.EnvironmentTickCount(); 3448 int startTime = Util.EnvironmentTickCount();
3451 m_log.DebugFormat("[PHYSICS]: Setting terrain for {0}", Name); 3449 m_log.DebugFormat("[ODE SCENE]: Setting terrain for {0}", Name);
3452 3450
3453 // this._heightmap[i] = (double)heightMap[i]; 3451 // this._heightmap[i] = (double)heightMap[i];
3454 // dbm (danx0r) -- creating a buffer zone of one extra sample all around 3452 // dbm (danx0r) -- creating a buffer zone of one extra sample all around
@@ -3573,7 +3571,7 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3573 } 3571 }
3574 3572
3575 m_log.DebugFormat( 3573 m_log.DebugFormat(
3576 "[PHYSICS]: Setting terrain for {0} took {1}ms", Name, Util.EnvironmentTickCountSubtract(startTime)); 3574 "[ODE SCENE]: Setting terrain for {0} took {1}ms", Name, Util.EnvironmentTickCountSubtract(startTime));
3577 } 3575 }
3578 3576
3579 public override void DeleteTerrain() 3577 public override void DeleteTerrain()
@@ -3590,64 +3588,64 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3590 return true; 3588 return true;
3591 } 3589 }
3592 3590
3593 public override void UnCombine(PhysicsScene pScene) 3591// public override void UnCombine(PhysicsScene pScene)
3594 { 3592// {
3595 IntPtr localGround = IntPtr.Zero; 3593// IntPtr localGround = IntPtr.Zero;
3596// float[] localHeightfield; 3594//// float[] localHeightfield;
3597 bool proceed = false; 3595// bool proceed = false;
3598 List<IntPtr> geomDestroyList = new List<IntPtr>(); 3596// List<IntPtr> geomDestroyList = new List<IntPtr>();
3599 3597//
3600 lock (OdeLock) 3598// lock (OdeLock)
3601 { 3599// {
3602 if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround)) 3600// if (RegionTerrain.TryGetValue(Vector3.Zero, out localGround))
3603 { 3601// {
3604 foreach (IntPtr geom in TerrainHeightFieldHeights.Keys) 3602// foreach (IntPtr geom in TerrainHeightFieldHeights.Keys)
3605 { 3603// {
3606 if (geom == localGround) 3604// if (geom == localGround)
3607 { 3605// {
3608// localHeightfield = TerrainHeightFieldHeights[geom]; 3606//// localHeightfield = TerrainHeightFieldHeights[geom];
3609 proceed = true; 3607// proceed = true;
3610 } 3608// }
3611 else 3609// else
3612 { 3610// {
3613 geomDestroyList.Add(geom); 3611// geomDestroyList.Add(geom);
3614 } 3612// }
3615 } 3613// }
3616 3614//
3617 if (proceed) 3615// if (proceed)
3618 { 3616// {
3619 m_worldOffset = Vector3.Zero; 3617// m_worldOffset = Vector3.Zero;
3620 WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize); 3618// WorldExtents = new Vector2((int)Constants.RegionSize, (int)Constants.RegionSize);
3621 m_parentScene = null; 3619// m_parentScene = null;
3622 3620//
3623 foreach (IntPtr g in geomDestroyList) 3621// foreach (IntPtr g in geomDestroyList)
3624 { 3622// {
3625 // removingHeightField needs to be done or the garbage collector will 3623// // removingHeightField needs to be done or the garbage collector will
3626 // collect the terrain data before we tell ODE to destroy it causing 3624// // collect the terrain data before we tell ODE to destroy it causing
3627 // memory corruption 3625// // memory corruption
3628 if (TerrainHeightFieldHeights.ContainsKey(g)) 3626// if (TerrainHeightFieldHeights.ContainsKey(g))
3629 { 3627// {
3630// float[] removingHeightField = TerrainHeightFieldHeights[g]; 3628//// float[] removingHeightField = TerrainHeightFieldHeights[g];
3631 TerrainHeightFieldHeights.Remove(g); 3629// TerrainHeightFieldHeights.Remove(g);
3632 3630//
3633 if (RegionTerrain.ContainsKey(g)) 3631// if (RegionTerrain.ContainsKey(g))
3634 { 3632// {
3635 RegionTerrain.Remove(g); 3633// RegionTerrain.Remove(g);
3636 } 3634// }
3637 3635//
3638 d.GeomDestroy(g); 3636// d.GeomDestroy(g);
3639 //removingHeightField = new float[0]; 3637// //removingHeightField = new float[0];
3640 } 3638// }
3641 } 3639// }
3642 3640//
3643 } 3641// }
3644 else 3642// else
3645 { 3643// {
3646 m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data."); 3644// m_log.Warn("[PHYSICS]: Couldn't proceed with UnCombine. Region has inconsistant data.");
3647 } 3645// }
3648 } 3646// }
3649 } 3647// }
3650 } 3648// }
3651 3649
3652 public override void SetWaterLevel(float baseheight) 3650 public override void SetWaterLevel(float baseheight)
3653 { 3651 {
@@ -3894,30 +3892,28 @@ Console.WriteLine("AddPhysicsActorTaint to " + taintedprim.Name);
3894 } 3892 }
3895 } 3893 }
3896 ds.SetColor(1.0f, 0.0f, 0.0f); 3894 ds.SetColor(1.0f, 0.0f, 0.0f);
3897 lock (_characters) 3895
3896 foreach (OdeCharacter chr in _characters)
3898 { 3897 {
3899 foreach (OdeCharacter chr in _characters) 3898 if (chr.Shell != IntPtr.Zero)
3900 { 3899 {
3901 if (chr.Shell != IntPtr.Zero) 3900 IntPtr body = d.GeomGetBody(chr.Shell);
3902 {
3903 IntPtr body = d.GeomGetBody(chr.Shell);
3904 3901
3905 d.Vector3 pos; 3902 d.Vector3 pos;
3906 d.GeomCopyPosition(chr.Shell, out pos); 3903 d.GeomCopyPosition(chr.Shell, out pos);
3907 //d.BodyCopyPosition(body, out pos); 3904 //d.BodyCopyPosition(body, out pos);
3908 3905
3909 d.Matrix3 R; 3906 d.Matrix3 R;
3910 d.GeomCopyRotation(chr.Shell, out R); 3907 d.GeomCopyRotation(chr.Shell, out R);
3911 //d.BodyCopyRotation(body, out R); 3908 //d.BodyCopyRotation(body, out R);
3912 3909
3913 ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f); 3910 ds.DrawCapsule(ref pos, ref R, chr.Size.Z, 0.35f);
3914 d.Vector3 sides = new d.Vector3(); 3911 d.Vector3 sides = new d.Vector3();
3915 sides.X = 0.5f; 3912 sides.X = 0.5f;
3916 sides.Y = 0.5f; 3913 sides.Y = 0.5f;
3917 sides.Z = 0.5f; 3914 sides.Z = 0.5f;
3918 3915
3919 ds.DrawBox(ref pos, ref R, ref sides); 3916 ds.DrawBox(ref pos, ref R, ref sides);
3920 }
3921 } 3917 }
3922 } 3918 }
3923 } 3919 }
diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
index 1413535..e4a3ba0 100644
--- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
+++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs
@@ -759,33 +759,33 @@ namespace OpenSim.Region.RegionCombinerModule
759 { 759 {
760 } 760 }
761 761
762 /// <summary> 762// /// <summary>
763 /// TODO: 763// /// TODO:
764 /// </summary> 764// /// </summary>
765 /// <param name="rdata"></param> 765// /// <param name="rdata"></param>
766 public void UnCombineRegion(RegionData rdata) 766// public void UnCombineRegion(RegionData rdata)
767 { 767// {
768 lock (m_regions) 768// lock (m_regions)
769 { 769// {
770 if (m_regions.ContainsKey(rdata.RegionId)) 770// if (m_regions.ContainsKey(rdata.RegionId))
771 { 771// {
772 // uncombine root region and virtual regions 772// // uncombine root region and virtual regions
773 } 773// }
774 else 774// else
775 { 775// {
776 foreach (RegionConnections r in m_regions.Values) 776// foreach (RegionConnections r in m_regions.Values)
777 { 777// {
778 foreach (RegionData rd in r.ConnectedRegions) 778// foreach (RegionData rd in r.ConnectedRegions)
779 { 779// {
780 if (rd.RegionId == rdata.RegionId) 780// if (rd.RegionId == rdata.RegionId)
781 { 781// {
782 // uncombine virtual region 782// // uncombine virtual region
783 } 783// }
784 } 784// }
785 } 785// }
786 } 786// }
787 } 787// }
788 } 788// }
789 789
790 // Create a set of infinite borders around the whole aabb of the combined island. 790 // Create a set of infinite borders around the whole aabb of the combined island.
791 private void AdjustLargeRegionBounds() 791 private void AdjustLargeRegionBounds()
diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs
index 2cae02d..888b072 100644
--- a/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs
+++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServiceConnector.cs
@@ -87,12 +87,26 @@ namespace OpenSim.Services.Connectors
87 public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion) 87 public bool DoHelloNeighbourCall(GridRegion region, RegionInfo thisRegion)
88 { 88 {
89 string uri = region.ServerURI + "region/" + thisRegion.RegionID + "/"; 89 string uri = region.ServerURI + "region/" + thisRegion.RegionID + "/";
90 //m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri); 90// m_log.Debug(" >>> DoHelloNeighbourCall <<< " + uri);
91 91
92 WebRequest HelloNeighbourRequest = WebRequest.Create(uri); 92 WebRequest helloNeighbourRequest;
93 HelloNeighbourRequest.Method = "POST"; 93
94 HelloNeighbourRequest.ContentType = "application/json"; 94 try
95 HelloNeighbourRequest.Timeout = 10000; 95 {
96 helloNeighbourRequest = WebRequest.Create(uri);
97 }
98 catch (Exception e)
99 {
100 m_log.WarnFormat(
101 "[NEIGHBOUR SERVICE CONNCTOR]: Unable to parse uri {0} to send HelloNeighbour from {1} to {2}. Exception {3}{4}",
102 uri, thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
103
104 return false;
105 }
106
107 helloNeighbourRequest.Method = "POST";
108 helloNeighbourRequest.ContentType = "application/json";
109 helloNeighbourRequest.Timeout = 10000;
96 110
97 // Fill it in 111 // Fill it in
98 OSDMap args = null; 112 OSDMap args = null;
@@ -102,38 +116,48 @@ namespace OpenSim.Services.Connectors
102 } 116 }
103 catch (Exception e) 117 catch (Exception e)
104 { 118 {
105 m_log.Debug("[REST COMMS]: PackRegionInfoData failed with exception: " + e.Message); 119 m_log.WarnFormat(
120 "[NEIGHBOUR SERVICE CONNCTOR]: PackRegionInfoData failed for HelloNeighbour from {0} to {1}. Exception {2}{3}",
121 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
122
106 return false; 123 return false;
107 } 124 }
125
108 // Add the regionhandle of the destination region 126 // Add the regionhandle of the destination region
109 args["destination_handle"] = OSD.FromString(region.RegionHandle.ToString()); 127 args["destination_handle"] = OSD.FromString(region.RegionHandle.ToString());
110 128
111 string strBuffer = ""; 129 string strBuffer = "";
112 byte[] buffer = new byte[1]; 130 byte[] buffer = new byte[1];
131
113 try 132 try
114 { 133 {
115 strBuffer = OSDParser.SerializeJsonString(args); 134 strBuffer = OSDParser.SerializeJsonString(args);
116 UTF8Encoding str = new UTF8Encoding(); 135 UTF8Encoding str = new UTF8Encoding();
117 buffer = str.GetBytes(strBuffer); 136 buffer = str.GetBytes(strBuffer);
118
119 } 137 }
120 catch (Exception e) 138 catch (Exception e)
121 { 139 {
122 m_log.WarnFormat("[REST COMMS]: Exception thrown on serialization of HelloNeighbour: {0}", e.Message); 140 m_log.WarnFormat(
141 "[NEIGHBOUR SERVICE CONNCTOR]: Exception thrown on serialization of HelloNeighbour from {0} to {1}. Exception {2}{3}",
142 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
143
123 return false; 144 return false;
124 } 145 }
125 146
126 Stream os = null; 147 Stream os = null;
127 try 148 try
128 { // send the Post 149 { // send the Post
129 HelloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send 150 helloNeighbourRequest.ContentLength = buffer.Length; //Count bytes to send
130 os = HelloNeighbourRequest.GetRequestStream(); 151 os = helloNeighbourRequest.GetRequestStream();
131 os.Write(buffer, 0, strBuffer.Length); //Send it 152 os.Write(buffer, 0, strBuffer.Length); //Send it
132 //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri); 153 //m_log.InfoFormat("[REST COMMS]: Posted HelloNeighbour request to remote sim {0}", uri);
133 } 154 }
134 catch (Exception ex) 155 catch (Exception e)
135 { 156 {
136 m_log.InfoFormat("[REST COMMS]: Unable to send HelloNeighbour to {0}: {1}", region.RegionName, ex.Message); 157 m_log.WarnFormat(
158 "[NEIGHBOUR SERVICE CONNCTOR]: Unable to send HelloNeighbour from {0} to {1}. Exception {2}{3}",
159 thisRegion.RegionName, region.RegionName, e.Message, e.StackTrace);
160
137 return false; 161 return false;
138 } 162 }
139 finally 163 finally
@@ -148,10 +172,12 @@ namespace OpenSim.Services.Connectors
148 StreamReader sr = null; 172 StreamReader sr = null;
149 try 173 try
150 { 174 {
151 WebResponse webResponse = HelloNeighbourRequest.GetResponse(); 175 WebResponse webResponse = helloNeighbourRequest.GetResponse();
152 if (webResponse == null) 176 if (webResponse == null)
153 { 177 {
154 m_log.Info("[REST COMMS]: Null reply on DoHelloNeighbourCall post"); 178 m_log.DebugFormat(
179 "[REST COMMS]: Null reply on DoHelloNeighbourCall post from {0} to {1}",
180 thisRegion.RegionName, region.RegionName);
155 } 181 }
156 182
157 sr = new StreamReader(webResponse.GetResponseStream()); 183 sr = new StreamReader(webResponse.GetResponseStream());
@@ -160,9 +186,12 @@ namespace OpenSim.Services.Connectors
160 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply); 186 //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply);
161 187
162 } 188 }
163 catch (Exception ex) 189 catch (Exception e)
164 { 190 {
165 m_log.InfoFormat("[REST COMMS]: exception on reply of DoHelloNeighbourCall {0}", ex.Message); 191 m_log.WarnFormat(
192 "[NEIGHBOUR SERVICE CONNCTOR]: Exception on reply of DoHelloNeighbourCall from {0} back to {1}. Exception {2}{3}",
193 region.RegionName, thisRegion.RegionName, e.Message, e.StackTrace);
194
166 return false; 195 return false;
167 } 196 }
168 finally 197 finally
@@ -172,8 +201,6 @@ namespace OpenSim.Services.Connectors
172 } 201 }
173 202
174 return true; 203 return true;
175
176 } 204 }
177
178 } 205 }
179} 206} \ No newline at end of file
diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
index d8089ac..9573e21 100644
--- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
+++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs
@@ -334,7 +334,9 @@ namespace OpenSim.Services.Connectors.SimianGrid
334 // Make the remote storage request 334 // Make the remote storage request
335 try 335 try
336 { 336 {
337 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl); 337 // Simian does not require the asset ID to be in the URL because it's in the post data.
338 // By appending it to the URL also, we allow caching proxies (squid) to invalidate asset URLs
339 HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(m_serverUrl + asset.FullID.ToString());
338 340
339 HttpWebResponse response = MultipartForm.Post(request, postParameters); 341 HttpWebResponse response = MultipartForm.Post(request, postParameters);
340 using (Stream responseStream = response.GetResponseStream()) 342 using (Stream responseStream = response.GetResponseStream())
diff --git a/OpenSim/Tests/ConfigurationLoaderTest.cs b/OpenSim/Tests/ConfigurationLoaderTest.cs
index c777acc..067264d 100644
--- a/OpenSim/Tests/ConfigurationLoaderTest.cs
+++ b/OpenSim/Tests/ConfigurationLoaderTest.cs
@@ -109,11 +109,13 @@ namespace OpenSim.Tests
109 // Prepare call to ConfigurationLoader.LoadConfigSettings() 109 // Prepare call to ConfigurationLoader.LoadConfigSettings()
110 ConfigurationLoader cl = new ConfigurationLoader(); 110 ConfigurationLoader cl = new ConfigurationLoader();
111 IConfigSource argvSource = new IniConfigSource(); 111 IConfigSource argvSource = new IniConfigSource();
112 EnvConfigSource envConfigSource = new EnvConfigSource();
112 argvSource.AddConfig("Startup").Set("inifile", mainIniFile); 113 argvSource.AddConfig("Startup").Set("inifile", mainIniFile);
113 ConfigSettings configSettings; 114 ConfigSettings configSettings;
114 NetworkServersInfo networkInfo; 115 NetworkServersInfo networkInfo;
115 116
116 OpenSimConfigSource source = cl.LoadConfigSettings(argvSource, out configSettings, out networkInfo); 117 OpenSimConfigSource source = cl.LoadConfigSettings(argvSource, envConfigSource,
118 out configSettings, out networkInfo);
117 119
118 // Remove default config 120 // Remove default config
119 config = source.Source.Configs["Startup"]; 121 config = source.Source.Configs["Startup"];
diff --git a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
index 7084ab4..0a6d5d2 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/GrabbingBehaviour.cs
@@ -41,6 +41,8 @@ namespace pCampBot
41 /// </remarks> 41 /// </remarks>
42 public class GrabbingBehaviour : IBehaviour 42 public class GrabbingBehaviour : IBehaviour
43 { 43 {
44 public string Name { get { return "Grabbing"; } }
45
44 public void Action(Bot bot) 46 public void Action(Bot bot)
45 { 47 {
46 Dictionary<UUID, Primitive> objects = bot.Objects; 48 Dictionary<UUID, Primitive> objects = bot.Objects;
diff --git a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
index 3ce08bf..f782bb5 100644
--- a/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Behaviours/PhysicsBehaviour.cs
@@ -42,6 +42,8 @@ namespace pCampBot
42 /// </remarks> 42 /// </remarks>
43 public class PhysicsBehaviour : IBehaviour 43 public class PhysicsBehaviour : IBehaviour
44 { 44 {
45 public string Name { get { return "Physics"; } }
46
45 private string[] talkarray; 47 private string[] talkarray;
46 48
47 public PhysicsBehaviour() 49 public PhysicsBehaviour()
diff --git a/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs b/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
new file mode 100644
index 0000000..fc2ed2c
--- /dev/null
+++ b/OpenSim/Tools/pCampBot/Behaviours/TeleportBehaviour.cs
@@ -0,0 +1,75 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Linq;
31using System.Reflection;
32using log4net;
33using OpenMetaverse;
34using pCampBot.Interfaces;
35
36namespace pCampBot
37{
38 /// <summary>
39 /// Teleport to a random region on the grid.
40 /// </summary>
41 public class TeleportBehaviour : IBehaviour
42 {
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 public string Name { get { return "Teleport"; } }
46
47 public void Action(Bot bot)
48 {
49 Random rng = bot.Manager.Rng;
50 GridRegion[] knownRegions;
51
52 lock (bot.Manager.RegionsKnown)
53 {
54 if (bot.Manager.RegionsKnown.Count == 0)
55 {
56 m_log.DebugFormat(
57 "[TELEPORT BEHAVIOUR]: Ignoring teleport action for {0} since no regions are known yet", bot.Name);
58 return;
59 }
60
61 knownRegions = bot.Manager.RegionsKnown.Values.ToArray();
62 }
63
64 Simulator sourceRegion = bot.Client.Network.CurrentSim;
65 GridRegion destRegion = knownRegions[rng.Next(knownRegions.Length)];
66 Vector3 destPosition = new Vector3(rng.Next(255), rng.Next(255), 50);
67
68 m_log.DebugFormat(
69 "[TELEPORT BEHAVIOUR]: Teleporting {0} from {1} {2} to {3} {4}",
70 bot.Name, sourceRegion.Name, bot.Client.Self.SimPosition, destRegion.Name, destPosition);
71
72 bot.Client.Self.Teleport(destRegion.RegionHandle, destPosition);
73 }
74 }
75} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/Bot.cs b/OpenSim/Tools/pCampBot/Bot.cs
index 7f941a4..7a73e3f 100644
--- a/OpenSim/Tools/pCampBot/Bot.cs
+++ b/OpenSim/Tools/pCampBot/Bot.cs
@@ -49,8 +49,15 @@ namespace pCampBot
49 49
50 public delegate void AnEvent(Bot callbot, EventType someevent); // event delegate for bot events 50 public delegate void AnEvent(Bot callbot, EventType someevent); // event delegate for bot events
51 51
52 public BotManager BotManager { get; private set; } 52 /// <summary>
53 private IConfig startupConfig; // bot config, passed from BotManager 53 /// Bot manager.
54 /// </summary>
55 public BotManager Manager { get; private set; }
56
57 /// <summary>
58 /// Bot config, passed from BotManager.
59 /// </summary>
60 private IConfig startupConfig;
54 61
55 /// <summary> 62 /// <summary>
56 /// Behaviours implemented by this bot. 63 /// Behaviours implemented by this bot.
@@ -132,7 +139,7 @@ namespace pCampBot
132 Password = password; 139 Password = password;
133 LoginUri = loginUri; 140 LoginUri = loginUri;
134 141
135 BotManager = bm; 142 Manager = bm;
136 startupConfig = bm.Config; 143 startupConfig = bm.Config;
137 readconfig(); 144 readconfig();
138 145
@@ -218,7 +225,19 @@ namespace pCampBot
218 { 225 {
219 MakeDefaultAppearance(wear); 226 MakeDefaultAppearance(wear);
220 } 227 }
228
221 Client.Self.Jump(true); 229 Client.Self.Jump(true);
230
231 // Extract nearby region information.
232 Client.Grid.GridRegion += Manager.Grid_GridRegion;
233 uint xUint, yUint;
234 Utils.LongToUInts(Client.Network.CurrentSim.Handle, out xUint, out yUint);
235 ushort minX, minY, maxX, maxY;
236 minX = (ushort)Math.Min(0, xUint - 5);
237 minY = (ushort)Math.Min(0, yUint - 5);
238 maxX = (ushort)(xUint + 5);
239 maxY = (ushort)(yUint + 5);
240 Client.Grid.RequestMapBlocks(GridLayerType.Terrain, minX, minY, maxX, maxY, false);
222 } 241 }
223 else 242 else
224 { 243 {
@@ -472,13 +491,13 @@ namespace pCampBot
472 491
473 private void GetTexture(UUID textureID) 492 private void GetTexture(UUID textureID)
474 { 493 {
475 lock (BotManager.AssetsReceived) 494 lock (Manager.AssetsReceived)
476 { 495 {
477 // Don't request assets more than once. 496 // Don't request assets more than once.
478 if (BotManager.AssetsReceived.ContainsKey(textureID)) 497 if (Manager.AssetsReceived.ContainsKey(textureID))
479 return; 498 return;
480 499
481 BotManager.AssetsReceived[textureID] = false; 500 Manager.AssetsReceived[textureID] = false;
482 Client.Assets.RequestImage(textureID, ImageType.Normal, Asset_TextureCallback_Texture); 501 Client.Assets.RequestImage(textureID, ImageType.Normal, Asset_TextureCallback_Texture);
483 } 502 }
484 } 503 }
@@ -490,8 +509,8 @@ namespace pCampBot
490 509
491 public void Asset_ReceivedCallback(AssetDownload transfer, Asset asset) 510 public void Asset_ReceivedCallback(AssetDownload transfer, Asset asset)
492 { 511 {
493 lock (BotManager.AssetsReceived) 512 lock (Manager.AssetsReceived)
494 BotManager.AssetsReceived[asset.AssetID] = true; 513 Manager.AssetsReceived[asset.AssetID] = true;
495 514
496// if (wear == "save") 515// if (wear == "save")
497// { 516// {
diff --git a/OpenSim/Tools/pCampBot/BotManager.cs b/OpenSim/Tools/pCampBot/BotManager.cs
index f5dd5e0..29cb1ba 100644
--- a/OpenSim/Tools/pCampBot/BotManager.cs
+++ b/OpenSim/Tools/pCampBot/BotManager.cs
@@ -27,6 +27,7 @@
27 27
28using System; 28using System;
29using System.Collections.Generic; 29using System.Collections.Generic;
30using System.Linq;
30using System.Reflection; 31using System.Reflection;
31using System.Threading; 32using System.Threading;
32using OpenMetaverse; 33using OpenMetaverse;
@@ -48,9 +49,24 @@ namespace pCampBot
48 { 49 {
49 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 50 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
50 51
52 /// <summary>
53 /// Command console
54 /// </summary>
51 protected CommandConsole m_console; 55 protected CommandConsole m_console;
56
57 /// <summary>
58 /// Created bots, whether active or inactive.
59 /// </summary>
52 protected List<Bot> m_lBot; 60 protected List<Bot> m_lBot;
53 protected Random somthing = new Random(Environment.TickCount); 61
62 /// <summary>
63 /// Random number generator.
64 /// </summary>
65 public Random Rng { get; private set; }
66
67 /// <summary>
68 /// Overall configuration.
69 /// </summary>
54 public IConfig Config { get; private set; } 70 public IConfig Config { get; private set; }
55 71
56 /// <summary> 72 /// <summary>
@@ -59,11 +75,18 @@ namespace pCampBot
59 public Dictionary<UUID, bool> AssetsReceived { get; private set; } 75 public Dictionary<UUID, bool> AssetsReceived { get; private set; }
60 76
61 /// <summary> 77 /// <summary>
78 /// The regions that we know about.
79 /// </summary>
80 public Dictionary<ulong, GridRegion> RegionsKnown { get; private set; }
81
82 /// <summary>
62 /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data 83 /// Constructor Creates MainConsole.Instance to take commands and provide the place to write data
63 /// </summary> 84 /// </summary>
64 public BotManager() 85 public BotManager()
65 { 86 {
87 Rng = new Random(Environment.TickCount);
66 AssetsReceived = new Dictionary<UUID, bool>(); 88 AssetsReceived = new Dictionary<UUID, bool>();
89 RegionsKnown = new Dictionary<ulong, GridRegion>();
67 90
68 m_console = CreateConsole(); 91 m_console = CreateConsole();
69 MainConsole.Instance = m_console; 92 MainConsole.Instance = m_console;
@@ -93,8 +116,13 @@ namespace pCampBot
93 "Shutdown bots and exit", 116 "Shutdown bots and exit",
94 HandleShutdown); 117 HandleShutdown);
95 118
96 m_console.Commands.AddCommand("bot", false, "show status", 119 m_console.Commands.AddCommand("bot", false, "show regions",
97 "show status", 120 "show regions",
121 "Show regions known to bots",
122 HandleShowRegions);
123
124 m_console.Commands.AddCommand("bot", false, "show bots",
125 "show bots",
98 "Shows the status of all bots", 126 "Shows the status of all bots",
99 HandleShowStatus); 127 HandleShowStatus);
100 128
@@ -123,19 +151,26 @@ namespace pCampBot
123 Array.ForEach<string>( 151 Array.ForEach<string>(
124 cs.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b)); 152 cs.GetString("behaviours", "p").Split(new char[] { ',' }), b => behaviourSwitches.Add(b));
125 153
154 List<IBehaviour> behaviours = new List<IBehaviour>();
155
156 // Hard-coded for now
157 if (behaviourSwitches.Contains("p"))
158 behaviours.Add(new PhysicsBehaviour());
159
160 if (behaviourSwitches.Contains("g"))
161 behaviours.Add(new GrabbingBehaviour());
162
163 if (behaviourSwitches.Contains("t"))
164 behaviours.Add(new TeleportBehaviour());
165
166 MainConsole.Instance.OutputFormat(
167 "[BOT MANAGER]: Bots configured for behaviours {0}",
168 string.Join(",", behaviours.ConvertAll<string>(b => b.Name).ToArray()));
169
126 for (int i = 0; i < botcount; i++) 170 for (int i = 0; i < botcount; i++)
127 { 171 {
128 string lastName = string.Format("{0}_{1}", lastNameStem, i); 172 string lastName = string.Format("{0}_{1}", lastNameStem, i);
129 173
130 List<IBehaviour> behaviours = new List<IBehaviour>();
131
132 // Hard-coded for now
133 if (behaviourSwitches.Contains("p"))
134 behaviours.Add(new PhysicsBehaviour());
135
136 if (behaviourSwitches.Contains("g"))
137 behaviours.Add(new GrabbingBehaviour());
138
139 StartBot(this, behaviours, firstName, lastName, password, loginUri); 174 StartBot(this, behaviours, firstName, lastName, password, loginUri);
140 } 175 }
141 } 176 }
@@ -240,17 +275,33 @@ namespace pCampBot
240 }); 275 });
241 } 276 }
242 277
278 private void HandleShowRegions(string module, string[] cmd)
279 {
280 string outputFormat = "{0,-30} {1, -20} {2, -5} {3, -5}";
281 MainConsole.Instance.OutputFormat(outputFormat, "Name", "Handle", "X", "Y");
282
283 lock (RegionsKnown)
284 {
285 foreach (GridRegion region in RegionsKnown.Values)
286 {
287 MainConsole.Instance.OutputFormat(
288 outputFormat, region.Name, region.RegionHandle, region.X, region.Y);
289 }
290 }
291 }
292
243 private void HandleShowStatus(string module, string[] cmd) 293 private void HandleShowStatus(string module, string[] cmd)
244 { 294 {
245 string outputFormat = "{0,-30} {1,-14}"; 295 string outputFormat = "{0,-30} {1, -30} {2,-14}";
246 MainConsole.Instance.OutputFormat(outputFormat, "Name", "Status"); 296 MainConsole.Instance.OutputFormat(outputFormat, "Name", "Region", "Status");
247 297
248 lock (m_lBot) 298 lock (m_lBot)
249 { 299 {
250 foreach (Bot pb in m_lBot) 300 foreach (Bot pb in m_lBot)
251 { 301 {
252 MainConsole.Instance.OutputFormat( 302 MainConsole.Instance.OutputFormat(
253 outputFormat, pb.Name, (pb.IsConnected ? "Connected" : "Disconnected")); 303 outputFormat,
304 pb.Name, pb.Client.Network.CurrentSim.Name, pb.IsConnected ? "Connected" : "Disconnected");
254 } 305 }
255 } 306 }
256 } 307 }
@@ -274,5 +325,24 @@ namespace pCampBot
274// if (newbots > 0) 325// if (newbots > 0)
275// addbots(newbots); 326// addbots(newbots);
276// } 327// }
328
329 internal void Grid_GridRegion(object o, GridRegionEventArgs args)
330 {
331 lock (RegionsKnown)
332 {
333 GridRegion newRegion = args.Region;
334
335 if (RegionsKnown.ContainsKey(newRegion.RegionHandle))
336 {
337 return;
338 }
339 else
340 {
341 m_log.DebugFormat(
342 "[BOT MANAGER]: Adding {0} {1} to known regions", newRegion.Name, newRegion.RegionHandle);
343 RegionsKnown[newRegion.RegionHandle] = newRegion;
344 }
345 }
346 }
277 } 347 }
278} 348}
diff --git a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
index d4ae0f0..912216f 100644
--- a/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
+++ b/OpenSim/Tools/pCampBot/Interfaces/IBehaviour.cs
@@ -31,6 +31,15 @@ namespace pCampBot.Interfaces
31{ 31{
32 public interface IBehaviour 32 public interface IBehaviour
33 { 33 {
34 /// <summary>
35 /// Name of this behaviour.
36 /// </summary>
37 string Name { get; }
38
39 /// <summary>
40 /// Action to take when this behaviour is invoked.
41 /// </summary>
42 /// <param name="bot"></param>
34 void Action(Bot bot); 43 void Action(Bot bot);
35 } 44 }
36} \ No newline at end of file 45} \ No newline at end of file
diff --git a/OpenSim/Tools/pCampBot/pCampBot.cs b/OpenSim/Tools/pCampBot/pCampBot.cs
index 4d3b06d..e7288d5 100644
--- a/OpenSim/Tools/pCampBot/pCampBot.cs
+++ b/OpenSim/Tools/pCampBot/pCampBot.cs
@@ -111,7 +111,7 @@ namespace pCampBot
111 " -firstname first name for the bots\n" + 111 " -firstname first name for the bots\n" +
112 " -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" + 112 " -lastname lastname for the bots. Each lastname will have _<bot-number> appended, e.g. Ima Bot_0\n" +
113 " -password password for the bots\n" + 113 " -password password for the bots\n" +
114 " -b, behaviours behaviours for bots. Current options p (physics), g (grab). Comma separated, e.g. p,g. Default is p", 114 " -b, behaviours behaviours for bots. Current options p (physics), g (grab), t (teleport). Comma separated, e.g. p,g. Default is p",
115 " -wear set appearance folder to load from (default: no)\n" + 115 " -wear set appearance folder to load from (default: no)\n" +
116 " -h, -help show this message" 116 " -h, -help show this message"
117 ); 117 );