diff --git a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
index cfb1605001..bb8825b118 100644
--- a/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
+++ b/OpenSim/Framework/Servers/HttpServer/WebsocketServerHandler.cs
@@ -535,6 +535,8 @@ namespace OpenSim.Framework.Servers.HttpServer
///
public void Close(string message)
{
+ if (_networkContext == null)
+ return;
if (_networkContext.Stream != null)
{
if (_networkContext.Stream.CanWrite)
diff --git a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
index 191bccf812..6ef8815026 100644
--- a/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
+++ b/OpenSim/Region/ClientStack/Linden/Caps/SimulatorFeaturesModule.cs
@@ -59,6 +59,8 @@ namespace OpenSim.Region.ClientStack.Linden
// private static readonly ILog m_log =
// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+ public event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
+
private Scene m_scene;
///
@@ -94,6 +96,8 @@ namespace OpenSim.Region.ClientStack.Linden
{
m_scene = s;
m_scene.EventManager.OnRegisterCaps += RegisterCaps;
+
+ m_scene.RegisterModuleInterface(this);
}
public void RemoveRegion(Scene s)
@@ -156,7 +160,7 @@ namespace OpenSim.Region.ClientStack.Linden
IRequestHandler reqHandler
= new RestHTTPHandler(
"GET", "/CAPS/" + UUID.Random(),
- HandleSimulatorFeaturesRequest, "SimulatorFeatures", agentID.ToString());
+ x => { return HandleSimulatorFeaturesRequest(x, agentID); }, "SimulatorFeatures", agentID.ToString());
caps.RegisterHandler("SimulatorFeatures", reqHandler);
}
@@ -185,18 +189,33 @@ namespace OpenSim.Region.ClientStack.Linden
return new OSDMap(m_features);
}
- private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod)
+ private OSDMap DeepCopy()
+ {
+ // This isn't the cheapest way of doing this but the rate
+ // of occurrence is low (on sim entry only) and it's a sure
+ // way to get a true deep copy.
+ OSD copy = OSDParser.DeserializeLLSDXml(OSDParser.SerializeLLSDXmlString(m_features));
+
+ return (OSDMap)copy;
+ }
+
+ private Hashtable HandleSimulatorFeaturesRequest(Hashtable mDhttpMethod, UUID agentID)
{
// m_log.DebugFormat("[SIMULATOR FEATURES MODULE]: SimulatorFeatures request");
+ OSDMap copy = DeepCopy();
+
+ SimulatorFeaturesRequestDelegate handlerOnSimulatorFeaturesRequest = OnSimulatorFeaturesRequest;
+ if (handlerOnSimulatorFeaturesRequest != null)
+ handlerOnSimulatorFeaturesRequest(agentID, ref copy);
+
//Send back data
Hashtable responsedata = new Hashtable();
responsedata["int_response_code"] = 200;
responsedata["content_type"] = "text/plain";
responsedata["keepalive"] = false;
- lock (m_features)
- responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(m_features);
+ responsedata["str_response_string"] = OSDParser.SerializeLLSDXmlString(copy);
return responsedata;
}
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
index d1ad74fae6..b67c0dfff1 100644
--- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
+++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs
@@ -42,7 +42,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction
public class AssetTransactionModule : INonSharedRegionModule,
IAgentAssetTransactions
{
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
protected Scene m_Scene;
private bool m_dumpAssetsToFile = false;
diff --git a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
index d36f65acf3..37131b9a53 100644
--- a/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/DynamicAttributes/DAExampleModule.cs
@@ -44,7 +44,7 @@ namespace OpenSim.Region.Framework.DynamicAttributes.DAExampleModule
[Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DAExampleModule")]
public class DAExampleModule : INonSharedRegionModule
{
- private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
+// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
private static readonly bool ENABLED = false; // enable for testing
diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
index fb74cc6d72..f3436d1c3c 100644
--- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/BinaryLoggingModule.cs
@@ -57,7 +57,7 @@ namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging
try
{
IConfig statConfig = source.Configs["Statistics.Binary"];
- if (statConfig.Contains("enabled") && statConfig.GetBoolean("enabled"))
+ if (statConfig != null && statConfig.Contains("enabled") && statConfig.GetBoolean("enabled"))
{
if (statConfig.Contains("collect_region_stats"))
{
diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
index 385f5ad7f1..cbffca7016 100644
--- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs
@@ -111,13 +111,15 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC
m_rpcPending = new Dictionary();
m_rpcPendingResponses = new Dictionary();
m_pendingSRDResponses = new Dictionary();
-
- try
- {
- m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
- }
- catch (Exception)
+ if (config.Configs["XMLRPC"] != null)
{
+ try
+ {
+ m_remoteDataPort = config.Configs["XMLRPC"].GetInt("XmlRpcPort", m_remoteDataPort);
+ }
+ catch (Exception)
+ {
+ }
}
}
diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
index cc7885a7a0..b40d24fa72 100644
--- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs
@@ -31,6 +31,16 @@ using OpenMetaverse;
namespace OpenSim.Region.Framework.Interfaces
{
+ // these could be expanded at some point to provide more type information
+ // for now value accounts for all base types
+ public enum JsonStoreNodeType
+ {
+ Undefined = 0,
+ Object = 1,
+ Array = 2,
+ Value = 3
+ }
+
public delegate void TakeValueCallback(string s);
public interface IJsonStoreModule
@@ -38,13 +48,18 @@ namespace OpenSim.Region.Framework.Interfaces
bool AttachObjectStore(UUID objectID);
bool CreateStore(string value, ref UUID result);
bool DestroyStore(UUID storeID);
+
+ JsonStoreNodeType GetPathType(UUID storeID, string path);
bool TestStore(UUID storeID);
bool TestPath(UUID storeID, string path, bool useJson);
+
bool SetValue(UUID storeID, string path, string value, bool useJson);
bool RemoveValue(UUID storeID, string path);
bool GetValue(UUID storeID, string path, bool useJson, out string value);
void TakeValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
void ReadValue(UUID storeID, string path, bool useJson, TakeValueCallback cback);
+
+ int GetArrayLength(UUID storeID, string path);
}
}
diff --git a/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs b/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs
index 8cef14e932..6effcc1d5c 100644
--- a/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISimulatorFeaturesModule.cs
@@ -26,18 +26,22 @@
*/
using System;
+using OpenMetaverse;
using OpenMetaverse.StructuredData;
namespace OpenSim.Region.Framework.Interfaces
{
+ public delegate void SimulatorFeaturesRequestDelegate(UUID agentID, ref OSDMap features);
+
///
/// Add remove or retrieve Simulator Features that will be given to a viewer via the SimulatorFeatures capability.
///
public interface ISimulatorFeaturesModule
{
+ event SimulatorFeaturesRequestDelegate OnSimulatorFeaturesRequest;
void AddFeature(string name, OSD value);
bool RemoveFeature(string name);
bool TryGetFeature(string name, out OSD value);
OSDMap GetFeatures();
}
-}
\ No newline at end of file
+}
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index 9ee15204ef..59d01489d0 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -790,6 +790,19 @@ namespace OpenSim.Region.Framework.Scenes
/// The object being removed from the scene
public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
+ ///
+ /// Triggered when an object is placed into the physical scene (PhysicsActor created).
+ ///
+ public event Action OnObjectAddedToPhysicalScene;
+ ///
+ /// Triggered when an object is removed from the physical scene (PhysicsActor destroyed).
+ ///
+ ///
+ /// Note: this is triggered just before the PhysicsActor is removed from the
+ /// physics engine so the receiver can do any necessary cleanup before its destruction.
+ ///
+ public event Action OnObjectRemovedFromPhysicalScene;
+
///
/// Triggered when an object is removed from the scene.
///
@@ -1516,6 +1529,48 @@ namespace OpenSim.Region.Framework.Scenes
}
}
+ public void TriggerObjectAddedToPhysicalScene(SceneObjectPart obj)
+ {
+ Action handler = OnObjectAddedToPhysicalScene;
+ if (handler != null)
+ {
+ foreach (Action d in handler.GetInvocationList())
+ {
+ try
+ {
+ d(obj);
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat(
+ "[EVENT MANAGER]: Delegate for TriggerObjectAddedToPhysicalScene failed - continuing. {0} {1}",
+ e.Message, e.StackTrace);
+ }
+ }
+ }
+ }
+
+ public void TriggerObjectRemovedFromPhysicalScene(SceneObjectPart obj)
+ {
+ Action handler = OnObjectRemovedFromPhysicalScene;
+ if (handler != null)
+ {
+ foreach (Action d in handler.GetInvocationList())
+ {
+ try
+ {
+ d(obj);
+ }
+ catch (Exception e)
+ {
+ m_log.ErrorFormat(
+ "[EVENT MANAGER]: Delegate for TriggerObjectRemovedFromPhysicalScene failed - continuing. {0} {1}",
+ e.Message, e.StackTrace);
+ }
+ }
+ }
+ }
+
public void TriggerShutdown()
{
Action handlerShutdown = OnShutdown;
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
index 9b2997326c..cce8b21b6e 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs
@@ -4316,6 +4316,7 @@ namespace OpenSim.Region.Framework.Scenes
}
PhysActor = pa;
+ ParentGroup.Scene.EventManager.TriggerObjectAddedToPhysicalScene(this);
}
///
@@ -4328,6 +4329,7 @@ namespace OpenSim.Region.Framework.Scenes
///
public void RemoveFromPhysics()
{
+ ParentGroup.Scene.EventManager.TriggerObjectRemovedFromPhysicalScene(this);
ParentGroup.Scene.PhysicsScene.RemovePrim(PhysActor);
PhysActor = null;
}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
index 82a4da7857..ca3989a668 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs
@@ -68,14 +68,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
protected List m_TakeStore;
protected List m_ReadStore;
- // add separators for quoted paths
- protected static Regex m_ParsePassOne = new Regex("{[^}]+}");
-
- // add separators for array references
- protected static Regex m_ParsePassTwo = new Regex("(\\[[0-9]+\\]|\\[\\+\\])");
+ // add separators for quoted paths and array references
+ protected static Regex m_ParsePassOne = new Regex("({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])");
// add quotes to bare identifiers which are limited to alphabetic characters
- protected static Regex m_ParsePassThree = new Regex("\\.([a-zA-Z]+)");
+ protected static Regex m_ParsePassThree = new Regex("(?();
m_ReadStore = new List();
}
-
+
public JsonStore(string value) : this()
{
+ // This is going to throw an exception if the value is not
+ // a valid JSON chunk. Calling routines should catch the
+ // exception and handle it appropriately
if (String.IsNullOrEmpty(value))
ValueStore = new OSDMap();
else
ValueStore = OSDParser.DeserializeJson(value);
}
+
+ // -----------------------------------------------------------------
+ ///
+ ///
+ ///
+ // -----------------------------------------------------------------
+ public JsonStoreNodeType PathType(string expr)
+ {
+ Stack path;
+ if (! ParsePathExpression(expr,out path))
+ return JsonStoreNodeType.Undefined;
+
+ OSD result = ProcessPathExpression(ValueStore,path);
+ if (result == null)
+ return JsonStoreNodeType.Undefined;
+
+ if (result is OSDMap)
+ return JsonStoreNodeType.Object;
+
+ if (result is OSDArray)
+ return JsonStoreNodeType.Array;
+
+ if (OSDBaseType(result.Type))
+ return JsonStoreNodeType.Value;
+
+ return JsonStoreNodeType.Undefined;
+ }
+
// -----------------------------------------------------------------
///
///
@@ -162,6 +190,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
return false;
}
+ // -----------------------------------------------------------------
+ ///
+ ///
+ ///
+ // -----------------------------------------------------------------
+ public int ArrayLength(string expr)
+ {
+ Stack path;
+ if (! ParsePathExpression(expr,out path))
+ return -1;
+
+ OSD result = ProcessPathExpression(ValueStore,path);
+ if (result != null && result.Type == OSDType.Array)
+ {
+ OSDArray arr = result as OSDArray;
+ return arr.Count;
+ }
+
+ return -1;
+ }
+
// -----------------------------------------------------------------
///
///
@@ -462,11 +511,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
// add front and rear separators
expr = "." + expr + ".";
- // add separators for quoted exprs
- expr = m_ParsePassOne.Replace(expr,".$0.",-1,0);
-
- // add separators for array references
- expr = m_ParsePassTwo.Replace(expr,".$0.",-1,0);
+ // add separators for quoted exprs and array references
+ expr = m_ParsePassOne.Replace(expr,".$1.",-1,0);
// add quotes to bare identifier
expr = m_ParsePassThree.Replace(expr,".{$1}",-1,0);
@@ -574,14 +620,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
// The path pointed to an intermediate hash structure
if (result.Type == OSDType.Map)
{
- value = OSDParser.SerializeJsonString(result as OSDMap);
+ value = OSDParser.SerializeJsonString(result as OSDMap,true);
return true;
}
// The path pointed to an intermediate hash structure
if (result.Type == OSDType.Array)
{
- value = OSDParser.SerializeJsonString(result as OSDArray);
+ value = OSDParser.SerializeJsonString(result as OSDArray,true);
return true;
}
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
index f1ce856995..fb350683a6 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs
@@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
}
catch (Exception e)
{
- m_log.Error(string.Format("[JsonStore]: Unable to initialize store from {0}", value), e);
+ m_log.ErrorFormat("[JsonStore]: Unable to initialize store from {0}", value);
return false;
}
@@ -265,6 +265,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
return m_JsonValueStore.ContainsKey(storeID);
}
+ // -----------------------------------------------------------------
+ ///
+ ///
+ ///
+ // -----------------------------------------------------------------
+ public JsonStoreNodeType GetPathType(UUID storeID, string path)
+ {
+ if (! m_enabled) return JsonStoreNodeType.Undefined;
+
+ JsonStore map = null;
+ lock (m_JsonValueStore)
+ {
+ if (! m_JsonValueStore.TryGetValue(storeID,out map))
+ {
+ m_log.InfoFormat("[JsonStore] Missing store {0}",storeID);
+ return JsonStoreNodeType.Undefined;
+ }
+ }
+
+ try
+ {
+ lock (map)
+ return map.PathType(path);
+ }
+ catch (Exception e)
+ {
+ m_log.Error(string.Format("[JsonStore]: Path test failed for {0} in {1}", path, storeID), e);
+ }
+
+ return JsonStoreNodeType.Undefined;
+ }
+
// -----------------------------------------------------------------
///
///
@@ -370,6 +402,37 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
return false;
}
+ // -----------------------------------------------------------------
+ ///
+ ///
+ ///
+ // -----------------------------------------------------------------
+ public int GetArrayLength(UUID storeID, string path)
+ {
+ if (! m_enabled) return -1;
+
+ JsonStore map = null;
+ lock (m_JsonValueStore)
+ {
+ if (! m_JsonValueStore.TryGetValue(storeID,out map))
+ return -1;
+ }
+
+ try
+ {
+ lock (map)
+ {
+ return map.ArrayLength(path);
+ }
+ }
+ catch (Exception e)
+ {
+ m_log.Error("[JsonStore]: unable to retrieve value", e);
+ }
+
+ return -1;
+ }
+
// -----------------------------------------------------------------
///
///
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
index e4363046e0..ef08c05b9c 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs
@@ -167,7 +167,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
try
{
m_comms.RegisterScriptInvocations(this);
-
+ m_comms.RegisterConstants(this);
+
// m_comms.RegisterScriptInvocation(this, "JsonCreateStore");
// m_comms.RegisterScriptInvocation(this, "JsonAttachObjectStore");
// m_comms.RegisterScriptInvocation(this, "JsonDestroyStore");
@@ -214,6 +215,22 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
#endregion
+#region ScriptConstantsInterface
+
+ [ScriptConstant]
+ public static readonly int JSON_TYPE_UNDEF = (int)JsonStoreNodeType.Undefined;
+
+ [ScriptConstant]
+ public static readonly int JSON_TYPE_OBJECT = (int)JsonStoreNodeType.Object;
+
+ [ScriptConstant]
+ public static readonly int JSON_TYPE_ARRAY = (int)JsonStoreNodeType.Array;
+
+ [ScriptConstant]
+ public static readonly int JSON_TYPE_VALUE = (int)JsonStoreNodeType.Value;
+
+#endregion
+
#region ScriptInvocationInteface
// -----------------------------------------------------------------
///
@@ -318,6 +335,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
///
///
// -----------------------------------------------------------------
+ [ScriptInvocation]
+ public int JsonGetPathType(UUID hostID, UUID scriptID, UUID storeID, string path)
+ {
+ return (int)m_store.GetPathType(storeID,path);
+ }
+
[ScriptInvocation]
public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path)
{
@@ -342,7 +365,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
}
[ScriptInvocation]
- public int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
+ public int JsonSetJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value)
{
return m_store.SetValue(storeID,path,value,true) ? 1 : 0;
}
@@ -358,6 +381,17 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
return m_store.RemoveValue(storeID,path) ? 1 : 0;
}
+ // -----------------------------------------------------------------
+ ///
+ ///
+ ///
+ // -----------------------------------------------------------------
+ [ScriptInvocation]
+ public int JsonGetArrayLength(UUID hostID, UUID scriptID, UUID storeID, string path)
+ {
+ return m_store.GetArrayLength(storeID,path);
+ }
+
// -----------------------------------------------------------------
///
///
@@ -372,7 +406,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore
}
[ScriptInvocation]
- public string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path)
+ public string JsonGetJson(UUID hostID, UUID scriptID, UUID storeID, string path)
{
string value = String.Empty;
m_store.GetValue(storeID,path,true, out value);
diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
index 717484c906..3d9ad163a2 100644
--- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/Tests/JsonStoreScriptModuleTests.cs
@@ -53,6 +53,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
private Scene m_scene;
private MockScriptEngine m_engine;
private ScriptModuleCommsModule m_smcm;
+ private JsonStoreScriptModule m_jssm;
[TestFixtureSetUp]
public void FixtureInit()
@@ -82,10 +83,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
m_engine = new MockScriptEngine();
m_smcm = new ScriptModuleCommsModule();
JsonStoreModule jsm = new JsonStoreModule();
- JsonStoreScriptModule jssm = new JsonStoreScriptModule();
+ m_jssm = new JsonStoreScriptModule();
m_scene = new SceneHelpers().SetupScene();
- SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, jssm);
+ SceneHelpers.SetupSceneModules(m_scene, configSource, m_engine, m_smcm, jsm, m_jssm);
try
{
@@ -115,8 +116,35 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
- UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
- Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
+ // Test blank store
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+ Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
+ }
+
+ // Test single element store
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
+ Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
+ }
+
+ // Test with an integer value
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 42.15 }");
+ Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Hello");
+ Assert.That(value, Is.EqualTo("42.15"));
+ }
+
+ // Test with an array as the root node
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "[ 'one', 'two', 'three' ]");
+ Assert.That(storeId, Is.Not.EqualTo(UUID.Zero));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "[1]");
+ Assert.That(value, Is.EqualTo("two"));
+ }
}
[Test]
@@ -181,7 +209,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
}
[Test]
- public void TestJsonGetValueJson()
+ public void TestJsonGetJson()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
@@ -189,26 +217,26 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Two' } }");
{
- string value = (string)InvokeOp("JsonGetValueJson", storeId, "Hello.World");
+ string value = (string)InvokeOp("JsonGetJson", storeId, "Hello.World");
Assert.That(value, Is.EqualTo("'Two'"));
}
// Test get of path section instead of leaf
{
- string value = (string)InvokeOp("JsonGetValueJson", storeId, "Hello");
+ string value = (string)InvokeOp("JsonGetJson", storeId, "Hello");
Assert.That(value, Is.EqualTo("{\"World\":\"Two\"}"));
}
// Test get of non-existing value
{
- string fakeValueGet = (string)InvokeOp("JsonGetValueJson", storeId, "foo");
+ string fakeValueGet = (string)InvokeOp("JsonGetJson", storeId, "foo");
Assert.That(fakeValueGet, Is.EqualTo(""));
}
// Test get from non-existing store
{
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
- string fakeStoreValueGet = (string)InvokeOp("JsonGetValueJson", fakeStoreId, "Hello");
+ string fakeStoreValueGet = (string)InvokeOp("JsonGetJson", fakeStoreId, "Hello");
Assert.That(fakeStoreValueGet, Is.EqualTo(""));
}
}
@@ -242,88 +270,236 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
- UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
-
- int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
- Assert.That(returnValue, Is.EqualTo(1));
-
- int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
- Assert.That(result, Is.EqualTo(0));
-
- string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
- Assert.That(returnValue2, Is.EqualTo(""));
-
- // Test remove of non-existing value
- int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Hello");
- Assert.That(fakeValueRemove, Is.EqualTo(0));
-
- // Test get from non-existing store
- UUID fakeStoreId = TestHelpers.ParseTail(0x500);
- int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello");
- Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
- }
-
- [Test]
- public void TestJsonTestPath()
- {
- TestHelpers.InMethod();
-// TestHelpers.EnableLogging();
-
- UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
-
+ // Test remove of node in object pointing to a string
{
- int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World");
- Assert.That(result, Is.EqualTo(1));
- }
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
+
+ int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
+ Assert.That(returnValue, Is.EqualTo(1));
- // Test for path which does not resolve to a value.
- {
int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
Assert.That(result, Is.EqualTo(0));
+
+ string returnValue2 = (string)InvokeOp("JsonGetValue", storeId, "Hello");
+ Assert.That(returnValue2, Is.EqualTo(""));
+ }
+
+ // Test remove of node in object pointing to another object
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'Wally' } }");
+
+ int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello");
+ Assert.That(returnValue, Is.EqualTo(1));
+
+ int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
+ Assert.That(result, Is.EqualTo(0));
+
+ string returnValue2 = (string)InvokeOp("JsonGetJson", storeId, "Hello");
+ Assert.That(returnValue2, Is.EqualTo(""));
+ }
+
+ // Test remove of node in an array
+ {
+ UUID storeId
+ = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : [ 'value1', 'value2' ] }");
+
+ int returnValue = (int)InvokeOp( "JsonRemoveValue", storeId, "Hello[0]");
+ Assert.That(returnValue, Is.EqualTo(1));
+
+ int result = (int)InvokeOp("JsonTestPath", storeId, "Hello[0]");
+ Assert.That(result, Is.EqualTo(1));
+
+ result = (int)InvokeOp("JsonTestPath", storeId, "Hello[1]");
+ Assert.That(result, Is.EqualTo(0));
+
+ string stringReturnValue = (string)InvokeOp("JsonGetValue", storeId, "Hello[0]");
+ Assert.That(stringReturnValue, Is.EqualTo("value2"));
+
+ stringReturnValue = (string)InvokeOp("JsonGetJson", storeId, "Hello[1]");
+ Assert.That(stringReturnValue, Is.EqualTo(""));
+ }
+
+ // Test remove of non-existing value
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : 'World' }");
+
+ int fakeValueRemove = (int)InvokeOp("JsonRemoveValue", storeId, "Cheese");
+ Assert.That(fakeValueRemove, Is.EqualTo(0));
}
{
- int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo");
- Assert.That(result2, Is.EqualTo(0));
- }
-
- // Test with fake store
- {
+ // Test get from non-existing store
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
- int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello");
+ int fakeStoreValueRemove = (int)InvokeOp("JsonRemoveValue", fakeStoreId, "Hello");
Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
}
}
+// [Test]
+// public void TestJsonTestPath()
+// {
+// TestHelpers.InMethod();
+//// TestHelpers.EnableLogging();
+//
+// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
+//
+// {
+// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello.World");
+// Assert.That(result, Is.EqualTo(1));
+// }
+//
+// // Test for path which does not resolve to a value.
+// {
+// int result = (int)InvokeOp("JsonTestPath", storeId, "Hello");
+// Assert.That(result, Is.EqualTo(0));
+// }
+//
+// {
+// int result2 = (int)InvokeOp("JsonTestPath", storeId, "foo");
+// Assert.That(result2, Is.EqualTo(0));
+// }
+//
+// // Test with fake store
+// {
+// UUID fakeStoreId = TestHelpers.ParseTail(0x500);
+// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPath", fakeStoreId, "Hello");
+// Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
+// }
+// }
+
+// [Test]
+// public void TestJsonTestPathJson()
+// {
+// TestHelpers.InMethod();
+//// TestHelpers.EnableLogging();
+//
+// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
+//
+// {
+// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World");
+// Assert.That(result, Is.EqualTo(1));
+// }
+//
+// // Test for path which does not resolve to a value.
+// {
+// int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello");
+// Assert.That(result, Is.EqualTo(1));
+// }
+//
+// {
+// int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo");
+// Assert.That(result2, Is.EqualTo(0));
+// }
+//
+// // Test with fake store
+// {
+// UUID fakeStoreId = TestHelpers.ParseTail(0x500);
+// int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello");
+// Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
+// }
+// }
+
[Test]
- public void TestJsonTestPathJson()
+ public void TestGetArrayLength()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
- UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : 'One' } }");
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
{
- int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello.World");
- Assert.That(result, Is.EqualTo(1));
+ int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello.World");
+ Assert.That(result, Is.EqualTo(2));
}
- // Test for path which does not resolve to a value.
+ // Test path which is not an array
{
- int result = (int)InvokeOp("JsonTestPathJson", storeId, "Hello");
- Assert.That(result, Is.EqualTo(1));
+ int result = (int)InvokeOp("JsonGetArrayLength", storeId, "Hello");
+ Assert.That(result, Is.EqualTo(-1));
}
+ // Test fake path
{
- int result2 = (int)InvokeOp("JsonTestPathJson", storeId, "foo");
- Assert.That(result2, Is.EqualTo(0));
+ int result = (int)InvokeOp("JsonGetArrayLength", storeId, "foo");
+ Assert.That(result, Is.EqualTo(-1));
}
- // Test with fake store
+ // Test fake store
{
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
- int fakeStoreValueRemove = (int)InvokeOp("JsonTestPathJson", fakeStoreId, "Hello");
- Assert.That(fakeStoreValueRemove, Is.EqualTo(0));
+ int result = (int)InvokeOp("JsonGetArrayLength", fakeStoreId, "Hello.World");
+ Assert.That(result, Is.EqualTo(-1));
+ }
+ }
+
+ [Test]
+ public void TestJsonGetPathType()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ 'Hello' : { 'World' : [ 'one', 2 ] } }");
+
+ {
+ int result = (int)InvokeOp("JsonGetPathType", storeId, ".");
+ Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT));
+ }
+
+ {
+ int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello");
+ Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_OBJECT));
+ }
+
+ {
+ int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World");
+ Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_ARRAY));
+ }
+
+ {
+ int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[0]");
+ Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE));
+ }
+
+ {
+ int result = (int)InvokeOp("JsonGetPathType", storeId, "Hello.World[1]");
+ Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_VALUE));
+ }
+
+ // Test for non-existant path
+ {
+ int result = (int)InvokeOp("JsonGetPathType", storeId, "foo");
+ Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
+ }
+
+ // Test for non-existant store
+ {
+ UUID fakeStoreId = TestHelpers.ParseTail(0x500);
+ int result = (int)InvokeOp("JsonGetPathType", fakeStoreId, ".");
+ Assert.That(result, Is.EqualTo(JsonStoreScriptModule.JSON_TYPE_UNDEF));
+ }
+ }
+
+ [Test]
+ public void TestJsonList2Path()
+ {
+ TestHelpers.InMethod();
+// TestHelpers.EnableLogging();
+
+ // Invoking these methods directly since I just couldn't get comms module invocation to work for some reason
+ // - some confusion with the methods that take a params object[] invocation.
+ {
+ string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo" });
+ Assert.That(result, Is.EqualTo("{foo}"));
+ }
+
+ {
+ string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", "bar" });
+ Assert.That(result, Is.EqualTo("{foo}.{bar}"));
+ }
+
+ {
+ string result = m_jssm.JsonList2Path(UUID.Zero, UUID.Zero, new object[] { "foo", 1, "bar" });
+ Assert.That(result, Is.EqualTo("{foo}.[1].{bar}"));
}
}
@@ -334,7 +510,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
// TestHelpers.EnableLogging();
{
- UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun", "Times");
Assert.That(result, Is.EqualTo(1));
@@ -343,9 +519,155 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
Assert.That(value, Is.EqualTo("Times"));
}
+ // Test setting a key containing periods with delineation
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun.Circus}", "Times");
+ Assert.That(result, Is.EqualTo(1));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun.Circus}");
+ Assert.That(value, Is.EqualTo("Times"));
+ }
+
+ // *** Test [] ***
+
+ // Test setting a key containing unbalanced ] without delineation. Expecting failure
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "Fun]Circus", "Times");
+ Assert.That(result, Is.EqualTo(0));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Fun]Circus");
+ Assert.That(value, Is.EqualTo(""));
+ }
+
+ // Test setting a key containing unbalanced [ without delineation. Expecting failure
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[Circus", "Times");
+ Assert.That(result, Is.EqualTo(0));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[Circus");
+ Assert.That(value, Is.EqualTo(""));
+ }
+
+ // Test setting a key containing unbalanced [] without delineation. Expecting failure
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "Fun[]Circus", "Times");
+ Assert.That(result, Is.EqualTo(0));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Fun[]Circus");
+ Assert.That(value, Is.EqualTo(""));
+ }
+
+ // Test setting a key containing unbalanced ] with delineation
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun]Circus}", "Times");
+ Assert.That(result, Is.EqualTo(1));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun]Circus}");
+ Assert.That(value, Is.EqualTo("Times"));
+ }
+
+ // Test setting a key containing unbalanced [ with delineation
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[Circus}", "Times");
+ Assert.That(result, Is.EqualTo(1));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[Circus}");
+ Assert.That(value, Is.EqualTo("Times"));
+ }
+
+ // Test setting a key containing empty balanced [] with delineation
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[]Circus}", "Times");
+ Assert.That(result, Is.EqualTo(1));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[]Circus}");
+ Assert.That(value, Is.EqualTo("Times"));
+ }
+
+// // Commented out as this currently unexpectedly fails.
+// // Test setting a key containing brackets around an integer with delineation
+// {
+// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+//
+// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun[0]Circus}", "Times");
+// Assert.That(result, Is.EqualTo(1));
+//
+// string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun[0]Circus}");
+// Assert.That(value, Is.EqualTo("Times"));
+// }
+
+ // *** Test {} ***
+
+ // Test setting a key containing unbalanced } without delineation. Expecting failure (?)
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "Fun}Circus", "Times");
+ Assert.That(result, Is.EqualTo(0));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus");
+ Assert.That(value, Is.EqualTo(""));
+ }
+
+ // Test setting a key containing unbalanced { without delineation. Expecting failure (?)
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "Fun{Circus", "Times");
+ Assert.That(result, Is.EqualTo(0));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Fun}Circus");
+ Assert.That(value, Is.EqualTo(""));
+ }
+
+// // Commented out as this currently unexpectedly fails.
+// // Test setting a key containing unbalanced }
+// {
+// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+//
+// int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun}Circus}", "Times");
+// Assert.That(result, Is.EqualTo(0));
+// }
+
+ // Test setting a key containing unbalanced { with delineation
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Circus}", "Times");
+ Assert.That(result, Is.EqualTo(1));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Circus}");
+ Assert.That(value, Is.EqualTo("Times"));
+ }
+
+ // Test setting a key containing balanced {} with delineation. This should fail.
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
+
+ int result = (int)InvokeOp("JsonSetValue", storeId, "{Fun{Filled}Circus}", "Times");
+ Assert.That(result, Is.EqualTo(0));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "{Fun{Filled}Circus}");
+ Assert.That(value, Is.EqualTo(""));
+ }
+
// Test setting to location that does not exist. This should fail.
{
- UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{}");
int result = (int)InvokeOp("JsonSetValue", storeId, "Fun.Circus", "Times");
Assert.That(result, Is.EqualTo(0));
@@ -363,27 +685,27 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
}
[Test]
- public void TestJsonSetValueJson()
+ public void TestJsonSetJson()
{
TestHelpers.InMethod();
// TestHelpers.EnableLogging();
// Single quoted token case
-// {
-// UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
-//
-// int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "'Times'");
-// Assert.That(result, Is.EqualTo(1));
-//
-// string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
-// Assert.That(value, Is.EqualTo("Times"));
-// }
+ {
+ UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
+
+ int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "'Times'");
+ Assert.That(result, Is.EqualTo(1));
+
+ string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
+ Assert.That(value, Is.EqualTo("Times"));
+ }
// Sub-tree case
{
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
- int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "{ 'Filled' : 'Times' }");
+ int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "{ 'Filled' : 'Times' }");
Assert.That(result, Is.EqualTo(1));
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Filled");
@@ -394,7 +716,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
{
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
- int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun", "Times");
+ int result = (int)InvokeOp("JsonSetJson", storeId, "Fun", "Times");
Assert.That(result, Is.EqualTo(0));
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun");
@@ -405,7 +727,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
{
UUID storeId = (UUID)InvokeOp("JsonCreateStore", "{ }");
- int result = (int)InvokeOp("JsonSetValueJson", storeId, "Fun.Circus", "'Times'");
+ int result = (int)InvokeOp("JsonSetJson", storeId, "Fun.Circus", "'Times'");
Assert.That(result, Is.EqualTo(0));
string value = (string)InvokeOp("JsonGetValue", storeId, "Fun.Circus");
@@ -415,7 +737,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore.Tests
// Test with fake store
{
UUID fakeStoreId = TestHelpers.ParseTail(0x500);
- int fakeStoreValueSet = (int)InvokeOp("JsonSetValueJson", fakeStoreId, "Hello", "'World'");
+ int fakeStoreValueSet = (int)InvokeOp("JsonSetJson", fakeStoreId, "Hello", "'World'");
Assert.That(fakeStoreValueSet, Is.EqualTo(0));
}
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
index 7ab86d245e..3f83ef0ed2 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSApiTemplate.cs
@@ -225,9 +225,10 @@ public enum CollisionFlags : uint
CF_DISABLE_VISUALIZE_OBJECT = 1 << 5,
CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6,
// Following used by BulletSim to control collisions and updates
- BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10,
- BS_FLOATS_ON_WATER = 1 << 11,
- BS_VEHICLE_COLLISIONS = 1 << 12,
+ BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, // return collision events from unmanaged to managed
+ BS_FLOATS_ON_WATER = 1 << 11, // the object should float at water level
+ BS_VEHICLE_COLLISIONS = 1 << 12, // return collisions for vehicle ground checking
+ BS_RETURN_ROOT_COMPOUND_SHAPE = 1 << 13, // return the pos/rot of the root shape in a compound shape
BS_NONE = 0,
BS_ALL = 0xFFFFFFFF
};
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
index f781aeaa06..8dca7c65d5 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs
@@ -83,7 +83,7 @@ public sealed class BSCharacter : BSPhysObject
_velocity = OMV.Vector3.Zero;
_buoyancy = ComputeBuoyancyFromFlying(isFlying);
Friction = BSParam.AvatarStandingFriction;
- Density = BSParam.AvatarDensity;
+ Density = BSParam.AvatarDensity / BSParam.DensityScaleFactor;
// Old versions of ScenePresence passed only the height. If width and/or depth are zero,
// replace with the default values.
@@ -231,6 +231,15 @@ public sealed class BSCharacter : BSPhysObject
PhysicsScene.PE.SetFriction(PhysBody, Friction);
}
}
+ else
+ {
+ if (Flying)
+ {
+ // Flying and not collising and velocity nearly zero.
+ ZeroMotion(true /* inTaintTime */);
+ }
+ }
+
DetailLog("{0},BSCharacter.MoveMotor,taint,stopping,target={1},colliding={2}", LocalID, _velocityMotor.TargetValue, IsColliding);
}
else
@@ -274,7 +283,7 @@ public sealed class BSCharacter : BSPhysObject
// This test is done if moving forward, not flying and is colliding with something.
// DetailLog("{0},BSCharacter.WalkUpStairs,IsColliding={1},flying={2},targSpeed={3},collisions={4}",
// LocalID, IsColliding, Flying, TargetSpeed, CollisionsLastTick.Count);
- if (IsColliding && !Flying && TargetSpeed > 0.1f /* && ForwardSpeed < 0.1f */)
+ if (IsColliding && !Flying && TargetVelocitySpeed > 0.1f /* && ForwardSpeed < 0.1f */)
{
// The range near the character's feet where we will consider stairs
float nearFeetHeightMin = RawPosition.Z - (Size.Z / 2f) + 0.05f;
@@ -869,7 +878,7 @@ public sealed class BSCharacter : BSPhysObject
* Math.Min(Size.X, Size.Y) / 2
* Size.Y / 2f // plus the volume of the capsule end caps
);
- _mass = Density * _avatarVolume;
+ _mass = Density * BSParam.DensityScaleFactor * _avatarVolume;
}
// The physics engine says that properties have updated. Update same and inform
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
index e35311ff11..4ece1eb496 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs
@@ -127,6 +127,8 @@ public abstract class BSLinkset
m_children = new HashSet();
LinksetMass = parent.RawMass;
Rebuilding = false;
+
+ parent.ClearDisplacement();
}
// Link to a linkset where the child knows the parent.
@@ -280,6 +282,7 @@ public abstract class BSLinkset
return mass;
}
+ // Computes linkset's center of mass in world coordinates.
protected virtual OMV.Vector3 ComputeLinksetCenterOfMass()
{
OMV.Vector3 com;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
index 36bae9bba4..4ce58c7d75 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs
@@ -93,7 +93,8 @@ public sealed class BSLinksetCompound : BSLinkset
{
private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]";
- public BSLinksetCompound(BSScene scene, BSPrimLinkable parent) : base(scene, parent)
+ public BSLinksetCompound(BSScene scene, BSPrimLinkable parent)
+ : base(scene, parent)
{
}
@@ -217,59 +218,45 @@ public sealed class BSLinksetCompound : BSLinkset
// and that is caused by us updating the object.
if ((whichUpdated & ~(UpdatedProperties.Position | UpdatedProperties.Orientation)) == 0)
{
- // Gather the child info. It might not be there if the linkset is in transition.
- BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo;
- if (lsi != null)
- {
- // Since the child moved or rotationed, it needs a new relative position within the linkset
- BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, OMV.Vector3.Zero);
- updated.LinksetInfo = newLsi;
-
// Find the physical instance of the child
- if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
+ if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape))
+ {
+ // It is possible that the linkset is still under construction and the child is not yet
+ // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
+ // build the whole thing with the new position or rotation.
+ // The index must be checked because Bullet references the child array but does no validity
+ // checking of the child index passed.
+ int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
+ if (updated.LinksetChildIndex < numLinksetChildren)
{
- // It is possible that the linkset is still under construction and the child is not yet
- // inserted into the compound shape. A rebuild of the linkset in a pre-step action will
- // build the whole thing with the new position or rotation.
- // The index must be checked because Bullet references the child array but does no validity
- // checking of the child index passed.
- int numLinksetChildren = PhysicsScene.PE.GetNumberOfCompoundChildren(LinksetRoot.PhysShape);
- if (lsi.Index < numLinksetChildren)
+ BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, updated.LinksetChildIndex);
+ if (linksetChildShape.HasPhysicalShape)
{
- BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index);
- if (linksetChildShape.HasPhysicalShape)
- {
- // Found the child shape within the compound shape
- PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index,
- newLsi.OffsetFromCenterOfMass,
- newLsi.OffsetRot,
- true /* shouldRecalculateLocalAabb */);
- updatedChild = true;
- DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}",
- updated.LocalID, whichUpdated, newLsi);
- }
- else // DEBUG DEBUG
- { // DEBUG DEBUG
- DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
- updated.LocalID, linksetChildShape);
- } // DEBUG DEBUG
+ // Found the child shape within the compound shape
+ PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, updated.LinksetChildIndex,
+ updated.RawPosition - LinksetRoot.RawPosition,
+ updated.RawOrientation * OMV.Quaternion.Inverse(LinksetRoot.RawOrientation),
+ true /* shouldRecalculateLocalAabb */);
+ updatedChild = true;
+ DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},pos={2},rot={3}",
+ updated.LocalID, whichUpdated, updated.RawPosition, updated.RawOrientation);
}
else // DEBUG DEBUG
{ // DEBUG DEBUG
- // the child is not yet in the compound shape. This is non-fatal.
- DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
- updated.LocalID, numLinksetChildren, lsi.Index);
+ DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}",
+ updated.LocalID, linksetChildShape);
} // DEBUG DEBUG
}
else // DEBUG DEBUG
{ // DEBUG DEBUG
- DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
+ // the child is not yet in the compound shape. This is non-fatal.
+ DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,childNotInCompoundShape,numChildren={1},index={2}",
+ updated.LocalID, numLinksetChildren, updated.LinksetChildIndex);
} // DEBUG DEBUG
}
else // DEBUG DEBUG
{ // DEBUG DEBUG
- DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}",
- updated.LocalID, LinksetRoot.PhysShape);
+ DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID);
} // DEBUG DEBUG
if (!updatedChild)
@@ -379,6 +366,8 @@ public sealed class BSLinksetCompound : BSLinkset
// Safe to call even if the child is not really in the linkset.
protected override void RemoveChildFromLinkset(BSPrimLinkable child)
{
+ child.ClearDisplacement();
+
if (m_children.Remove(child))
{
DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}",
@@ -424,30 +413,31 @@ public sealed class BSLinksetCompound : BSLinkset
// The center of mass for the linkset is the geometric center of the group.
// Compute a displacement for each component so it is relative to the center-of-mass.
// Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass
- OMV.Vector3 centerOfMass;
- OMV.Vector3 centerDisplacement = OMV.Vector3.Zero;
- if (disableCOM) // DEBUG DEBUG
- { // DEBUG DEBUG
- centerOfMass = LinksetRoot.RawPosition; // DEBUG DEBUG
- // LinksetRoot.PositionDisplacement = OMV.Vector3.Zero;
- } // DEBUG DEBUG
- else
+ OMV.Vector3 centerOfMassW = LinksetRoot.RawPosition;
+ if (!disableCOM) // DEBUG DEBUG
{
- centerOfMass = ComputeLinksetCenterOfMass();
- // 'centerDisplacement' is the value to *add* to all the shape offsets
- centerDisplacement = LinksetRoot.RawPosition - centerOfMass;
-
- // Since we're displacing the center of the shape, we need to move the body in the world
- // LinksetRoot.PositionDisplacement = centerDisplacement;
-
- // This causes the root prim position to be set properly based on the new PositionDisplacement
- LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
- // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
- PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0, -centerDisplacement, OMV.Quaternion.Identity, false);
- DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
- LinksetRoot.LocalID, centerOfMass, LinksetRoot.RawPosition, centerDisplacement);
+ // Compute a center-of-mass in world coordinates.
+ centerOfMassW = ComputeLinksetCenterOfMass();
}
+ OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation);
+
+ // 'centerDisplacement' is the value to subtract from children to give physical offset position
+ OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation;
+ LinksetRoot.SetEffectiveCenterOfMassW(centerDisplacement);
+
+ // This causes the physical position of the root prim to be offset to accomodate for the displacements
+ LinksetRoot.ForcePosition = LinksetRoot.RawPosition;
+
+ // Update the local transform for the root child shape so it is offset from the <0,0,0> which is COM
+ PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, 0 /* childIndex */,
+ -centerDisplacement,
+ OMV.Quaternion.Identity, // LinksetRoot.RawOrientation,
+ false /* shouldRecalculateLocalAabb (is done later after linkset built) */);
+
+ DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,com={1},rootPos={2},centerDisp={3}",
+ LinksetRoot.LocalID, centerOfMassW, LinksetRoot.RawPosition, centerDisplacement);
+
DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}",
LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren);
@@ -455,38 +445,33 @@ public sealed class BSLinksetCompound : BSLinkset
int memberIndex = 1;
ForEachMember(delegate(BSPrimLinkable cPrim)
{
- if (!IsRoot(cPrim))
+ if (IsRoot(cPrim))
{
- // Compute the displacement of the child from the root of the linkset.
- // This info is saved in the child prim so the relationship does not
- // change over time and the new child position can be computed
- // when the linkset is being disassembled (the linkset may have moved).
- BSLinksetCompoundInfo lci = cPrim.LinksetInfo as BSLinksetCompoundInfo;
- if (lci == null)
- {
- lci = new BSLinksetCompoundInfo(memberIndex, LinksetRoot, cPrim, centerDisplacement);
- cPrim.LinksetInfo = lci;
- DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,creatingRelPos,lci={1}", cPrim.LocalID, lci);
- }
-
- DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},lci={3}",
- LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, lci);
+ cPrim.LinksetChildIndex = 0;
+ }
+ else
+ {
+ cPrim.LinksetChildIndex = memberIndex;
if (cPrim.PhysShape.isNativeShape)
{
// A native shape is turned into a hull collision shape because native
// shapes are not shared so we have to hullify it so it will be tracked
// and freed at the correct time. This also solves the scaling problem
- // (native shapes scaled but hull/meshes are assumed to not be).
+ // (native shapes scale but hull/meshes are assumed to not be).
// TODO: decide of the native shape can just be used in the compound shape.
// Use call to CreateGeomNonSpecial().
BulletShape saveShape = cPrim.PhysShape;
cPrim.PhysShape.Clear(); // Don't let the create free the child's shape
- // PhysicsScene.Shapes.CreateGeomNonSpecial(true, cPrim, null);
PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null);
BulletShape newShape = cPrim.PhysShape;
cPrim.PhysShape = saveShape;
- PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
+
+ OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
+ OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
+ PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
+ DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
+ LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, newShape, offsetPos, offsetRot);
}
else
{
@@ -498,9 +483,13 @@ public sealed class BSLinksetCompound : BSLinkset
PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}",
LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape);
}
- PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, lci.OffsetFromCenterOfMass, lci.OffsetRot);
+ OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement;
+ OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation;
+ PhysicsScene.PE.AddChildShapeToCompoundShape(LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
+ DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addNonNative,indx={1},rShape={2},cShape={3},offPos={4},offRot={5}",
+ LinksetRoot.LocalID, memberIndex, LinksetRoot.PhysShape, cPrim.PhysShape, offsetPos, offsetRot);
+
}
- lci.Index = memberIndex;
memberIndex++;
}
return false; // 'false' says to move onto the next child in the list
@@ -509,12 +498,16 @@ public sealed class BSLinksetCompound : BSLinkset
// With all of the linkset packed into the root prim, it has the mass of everyone.
LinksetMass = ComputeLinksetMass();
LinksetRoot.UpdatePhysicalMassProperties(LinksetMass, true);
+
+ // Enable the physical position updator to return the position and rotation of the root shape
+ PhysicsScene.PE.AddToCollisionFlags(LinksetRoot.PhysBody, CollisionFlags.BS_RETURN_ROOT_COMPOUND_SHAPE);
}
finally
{
Rebuilding = false;
}
+ // See that the Aabb surrounds the new shape
PhysicsScene.PE.RecalculateCompoundShapeLocalAabb(LinksetRoot.PhysShape);
}
}
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
index 3e0b4bca12..329169f79e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSParam.cs
@@ -49,6 +49,7 @@ public static class BSParam
public static float MaxLinearVelocity { get; private set; }
public static float MaxAngularVelocity { get; private set; }
public static float MaxAddForceMagnitude { get; private set; }
+ public static float DensityScaleFactor { get; private set; }
public static float LinearDamping { get; private set; }
public static float AngularDamping { get; private set; }
@@ -281,29 +282,35 @@ public static class BSParam
new ParameterDefn("MinObjectMass", "Minimum object mass (0.0001)",
0.0001f,
(s,cf,p,v) => { MinimumObjectMass = cf.GetFloat(p, v); },
- (s) => { return (float)MinimumObjectMass; },
+ (s) => { return MinimumObjectMass; },
(s,p,l,v) => { MinimumObjectMass = v; } ),
new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)",
10000.01f,
(s,cf,p,v) => { MaximumObjectMass = cf.GetFloat(p, v); },
- (s) => { return (float)MaximumObjectMass; },
+ (s) => { return MaximumObjectMass; },
(s,p,l,v) => { MaximumObjectMass = v; } ),
new ParameterDefn("MaxLinearVelocity", "Maximum velocity magnitude that can be assigned to an object",
1000.0f,
(s,cf,p,v) => { MaxLinearVelocity = cf.GetFloat(p, v); },
- (s) => { return (float)MaxLinearVelocity; },
+ (s) => { return MaxLinearVelocity; },
(s,p,l,v) => { MaxLinearVelocity = v; } ),
new ParameterDefn("MaxAngularVelocity", "Maximum rotational velocity magnitude that can be assigned to an object",
1000.0f,
(s,cf,p,v) => { MaxAngularVelocity = cf.GetFloat(p, v); },
- (s) => { return (float)MaxAngularVelocity; },
+ (s) => { return MaxAngularVelocity; },
(s,p,l,v) => { MaxAngularVelocity = v; } ),
// LL documentation says thie number should be 20f for llApplyImpulse and 200f for llRezObject
new ParameterDefn("MaxAddForceMagnitude", "Maximum force that can be applied by llApplyImpulse (SL says 20f)",
20000.0f,
(s,cf,p,v) => { MaxAddForceMagnitude = cf.GetFloat(p, v); },
- (s) => { return (float)MaxAddForceMagnitude; },
+ (s) => { return MaxAddForceMagnitude; },
(s,p,l,v) => { MaxAddForceMagnitude = v; } ),
+ // Density is passed around as 100kg/m3. This scales that to 1kg/m3.
+ new ParameterDefn("DensityScaleFactor", "Conversion for simulator/viewer density (100kg/m3) to physical density (1kg/m3)",
+ 0.01f,
+ (s,cf,p,v) => { DensityScaleFactor = cf.GetFloat(p, v); },
+ (s) => { return DensityScaleFactor; },
+ (s,p,l,v) => { DensityScaleFactor = v; } ),
new ParameterDefn("PID_D", "Derivitive factor for motion smoothing",
2200f,
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
index de69fa0699..f953c1e085 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs
@@ -99,6 +99,9 @@ public abstract class BSPhysObject : PhysicsActor
CollisionAccumulation = 0;
ColliderIsMoving = false;
CollisionScore = 0;
+
+ // All axis free.
+ LockedAxis = LockedAxisFree;
}
// Tell the object to clean up.
@@ -136,6 +139,7 @@ public abstract class BSPhysObject : PhysicsActor
// The objects base shape information. Null if not a prim type shape.
public PrimitiveBaseShape BaseShape { get; protected set; }
+
// Some types of objects have preferred physical representations.
// Returns SHAPE_UNKNOWN if there is no preference.
public virtual BSPhysicsShapeType PreferredPhysicalShape
@@ -150,15 +154,17 @@ public abstract class BSPhysObject : PhysicsActor
public EntityProperties LastEntityProperties { get; set; }
public virtual OMV.Vector3 Scale { get; set; }
- public abstract bool IsSolid { get; }
- public abstract bool IsStatic { get; }
- public abstract bool IsSelected { get; }
// It can be confusing for an actor to know if it should move or update an object
// depeneding on the setting of 'selected', 'physical, ...
// This flag is the true test -- if true, the object is being acted on in the physical world
public abstract bool IsPhysicallyActive { get; }
+ // Detailed state of the object.
+ public abstract bool IsSolid { get; }
+ public abstract bool IsStatic { get; }
+ public abstract bool IsSelected { get; }
+
// Materialness
public MaterialAttributes.Material Material { get; private set; }
public override void SetMaterial(int material)
@@ -169,7 +175,8 @@ public abstract class BSPhysObject : PhysicsActor
MaterialAttributes matAttrib = BSMaterials.GetAttributes(Material, false);
Friction = matAttrib.friction;
Restitution = matAttrib.restitution;
- Density = matAttrib.density;
+ Density = matAttrib.density / BSParam.DensityScaleFactor;
+ DetailLog("{0},{1}.SetMaterial,Mat={2},frict={3},rest={4},den={5}", LocalID, TypeName, Material, Friction, Restitution, Density);
}
// Stop all physical motion.
@@ -185,14 +192,6 @@ public abstract class BSPhysObject : PhysicsActor
public abstract OMV.Quaternion RawOrientation { get; set; }
public abstract OMV.Quaternion ForceOrientation { get; set; }
- public virtual float TargetSpeed
- {
- get
- {
- OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
- return characterOrientedVelocity.X;
- }
- }
public abstract OMV.Vector3 RawVelocity { get; set; }
public abstract OMV.Vector3 ForceVelocity { get; set; }
@@ -202,6 +201,7 @@ public abstract class BSPhysObject : PhysicsActor
public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; }
+ // The current velocity forward
public virtual float ForwardSpeed
{
get
@@ -210,6 +210,22 @@ public abstract class BSPhysObject : PhysicsActor
return characterOrientedVelocity.X;
}
}
+ // The forward speed we are trying to achieve (TargetVelocity)
+ public virtual float TargetVelocitySpeed
+ {
+ get
+ {
+ OMV.Vector3 characterOrientedVelocity = TargetVelocity * OMV.Quaternion.Inverse(OMV.Quaternion.Normalize(RawOrientation));
+ return characterOrientedVelocity.X;
+ }
+ }
+
+ // The user can optionally set the center of mass. The user's setting will override any
+ // computed center-of-mass (like in linksets).
+ public OMV.Vector3? UserSetCenterOfMass { get; set; }
+
+ public OMV.Vector3 LockedAxis { get; set; } // zero means locked. one means free.
+ public readonly OMV.Vector3 LockedAxisFree = new OMV.Vector3(1f, 1f, 1f); // All axis are free
#region Collisions
@@ -407,9 +423,7 @@ public abstract class BSPhysObject : PhysicsActor
{
// Clean out any existing action
UnRegisterPreStepAction(op, id);
-
RegisteredPrestepActions[identifier] = actn;
-
PhysicsScene.BeforeStep += actn;
}
DetailLog("{0},BSPhysObject.RegisterPreStepAction,id={1}", LocalID, identifier);
@@ -455,9 +469,7 @@ public abstract class BSPhysObject : PhysicsActor
{
// Clean out any existing action
UnRegisterPostStepAction(op, id);
-
RegisteredPoststepActions[identifier] = actn;
-
PhysicsScene.AfterStep += actn;
}
DetailLog("{0},BSPhysObject.RegisterPostStepAction,id={1}", LocalID, identifier);
@@ -494,7 +506,58 @@ public abstract class BSPhysObject : PhysicsActor
}
DetailLog("{0},BSPhysObject.UnRegisterAllPostStepActions,", LocalID);
}
-
+
+ // When an update to the physical properties happens, this event is fired to let
+ // different actors to modify the update before it is passed around
+ public delegate void PreUpdatePropertyAction(ref EntityProperties entprop);
+ public event PreUpdatePropertyAction OnPreUpdateProperty;
+ protected void TriggerPreUpdatePropertyAction(ref EntityProperties entprop)
+ {
+ PreUpdatePropertyAction actions = OnPreUpdateProperty;
+ if (actions != null)
+ actions(ref entprop);
+ }
+
+ private Dictionary RegisteredPreUpdatePropertyActions = new Dictionary();
+ public void RegisterPreUpdatePropertyAction(string identifier, PreUpdatePropertyAction actn)
+ {
+ lock (RegisteredPreUpdatePropertyActions)
+ {
+ // Clean out any existing action
+ UnRegisterPreUpdatePropertyAction(identifier);
+ RegisteredPreUpdatePropertyActions[identifier] = actn;
+ OnPreUpdateProperty += actn;
+ }
+ DetailLog("{0},BSPhysObject.RegisterPreUpdatePropertyAction,id={1}", LocalID, identifier);
+ }
+ public bool UnRegisterPreUpdatePropertyAction(string identifier)
+ {
+ bool removed = false;
+ lock (RegisteredPreUpdatePropertyActions)
+ {
+ if (RegisteredPreUpdatePropertyActions.ContainsKey(identifier))
+ {
+ OnPreUpdateProperty -= RegisteredPreUpdatePropertyActions[identifier];
+ RegisteredPreUpdatePropertyActions.Remove(identifier);
+ removed = true;
+ }
+ }
+ DetailLog("{0},BSPhysObject.UnRegisterPreUpdatePropertyAction,id={1},removed={2}", LocalID, identifier, removed);
+ return removed;
+ }
+ public void UnRegisterAllPreUpdatePropertyActions()
+ {
+ lock (RegisteredPreUpdatePropertyActions)
+ {
+ foreach (KeyValuePair kvp in RegisteredPreUpdatePropertyActions)
+ {
+ OnPreUpdateProperty -= kvp.Value;
+ }
+ RegisteredPreUpdatePropertyActions.Clear();
+ }
+ DetailLog("{0},BSPhysObject.UnRegisterAllPreUpdatePropertyAction,", LocalID);
+ }
+
#endregion // Per Simulation Step actions
// High performance detailed logging routine used by the physical objects.
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
index cf7aa0fea4..0323b0d39f 100644
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs
@@ -242,6 +242,45 @@ public class BSPrim : BSPhysObject
public override void LockAngularMotion(OMV.Vector3 axis)
{
DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis);
+
+ OMV.Vector3 locking = new OMV.Vector3(1f, 1f, 1f);
+ if (axis.X != 1) locking.X = 0f;
+ if (axis.Y != 1) locking.Y = 0f;
+ if (axis.Z != 1) locking.Z = 0f;
+ LockedAxis = locking;
+
+ /* Not implemented yet
+ if (LockedAxis != LockedAxisFree)
+ {
+ // Something is locked so start the thingy that keeps that axis from changing
+ RegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion", delegate(ref EntityProperties entprop)
+ {
+ if (LockedAxis != LockedAxisFree)
+ {
+ if (IsPhysicallyActive)
+ {
+ // Bullet can lock axis but it only works for global axis.
+ // Check if this prim is aligned on global axis and use Bullet's
+ // system if so.
+
+ ForceOrientation = entprop.Rotation;
+ ForceRotationalVelocity = entprop.RotationalVelocity;
+ }
+ }
+ else
+ {
+ UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion");
+ }
+
+ });
+ }
+ else
+ {
+ // Everything seems unlocked
+ UnRegisterPreUpdatePropertyAction("BSPrim.LockAngularMotion");
+ }
+ */
+
return;
}
@@ -311,7 +350,8 @@ public class BSPrim : BSPhysObject
float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(RawPosition);
OMV.Vector3 upForce = OMV.Vector3.Zero;
- if (RawPosition.Z < terrainHeight)
+ float approxSize = Math.Max(Size.X, Math.Max(Size.Y, Size.Z));
+ if ((RawPosition.Z + approxSize / 2f) < terrainHeight)
{
DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, RawPosition, terrainHeight);
float targetHeight = terrainHeight + (Size.Z / 2f);
@@ -442,7 +482,7 @@ public class BSPrim : BSPhysObject
RegisterPreStepAction("BSPrim.setForce", LocalID,
delegate(float timeStep)
{
- if (!IsPhysicallyActive)
+ if (!IsPhysicallyActive || _force == OMV.Vector3.Zero)
{
UnRegisterPreStepAction("BSPrim.setForce", LocalID);
return;
@@ -576,6 +616,8 @@ public class BSPrim : BSPhysObject
}
}
}
+ // The simulator/viewer keep density as 100kg/m3.
+ // Remember to use BSParam.DensityScaleFactor to create the physical density.
public override float Density
{
get { return base.Density; }
@@ -647,7 +689,7 @@ public class BSPrim : BSPhysObject
RegisterPreStepAction("BSPrim.setTorque", LocalID,
delegate(float timeStep)
{
- if (!IsPhysicallyActive)
+ if (!IsPhysicallyActive || _torque == OMV.Vector3.Zero)
{
UnRegisterPreStepAction("BSPrim.setTorque", LocalID);
return;
@@ -1569,7 +1611,8 @@ public class BSPrim : BSPhysObject
profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f;
volume *= (profileEnd - profileBegin);
- returnMass = Density * volume;
+ returnMass = Density * BSParam.DensityScaleFactor * volume;
+ DetailLog("{0},BSPrim.CalculateMass,den={1},vol={2},mass={3}", LocalID, Density, volume, returnMass);
returnMass = Util.Clamp(returnMass, BSParam.MinimumObjectMass, BSParam.MaximumObjectMass);
@@ -1607,6 +1650,8 @@ public class BSPrim : BSPhysObject
// the world that things have changed.
public override void UpdateProperties(EntityProperties entprop)
{
+ TriggerPreUpdatePropertyAction(ref entprop);
+
// A temporary kludge to suppress the rotational effects introduced on vehicles by Bullet
// TODO: handle physics introduced by Bullet with computed vehicle physics.
if (VehicleController.IsActive)
@@ -1619,7 +1664,11 @@ public class BSPrim : BSPhysObject
// Assign directly to the local variables so the normal set actions do not happen
_position = entprop.Position;
_orientation = entprop.Rotation;
- _velocity = entprop.Velocity;
+ // _velocity = entprop.Velocity;
+ // DEBUG DEBUG DEBUG -- smooth velocity changes a bit. The simulator seems to be
+ // very sensitive to velocity changes.
+ if (!entprop.Velocity.ApproxEquals(_velocity, 0.1f))
+ _velocity = entprop.Velocity;
_acceleration = entprop.Acceleration;
_rotationalVelocity = entprop.RotationalVelocity;
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
index 64013086af..f1c3b5c1bb 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimDisplaced.cs
@@ -44,72 +44,107 @@ namespace OpenSim.Region.Physics.BulletSPlugin
{
public class BSPrimDisplaced : BSPrim
{
- // 'Position' and 'Orientation' is what the simulator thinks the positions of the prim is.
- // Because Bullet needs the zero coordinate to be the center of mass of the linkset,
- // sometimes it is necessary to displace the position the physics engine thinks
- // the position is. PositionDisplacement must be added and removed from the
- // position as the simulator position is stored and fetched from the physics
- // engine. Similar to OrientationDisplacement.
+ // The purpose of this module is to do any mapping between what the simulator thinks
+ // the prim position and orientation is and what the physical position/orientation.
+ // This difference happens because Bullet assumes the center-of-mass is the <0,0,0>
+ // of the prim/linkset. The simulator tracks the location of the prim/linkset by
+ // the location of the root prim. So, if center-of-mass is anywhere but the origin
+ // of the root prim, the physical origin is displaced from the simulator origin.
+ //
+ // This routine works by capturing the Force* setting of position/orientation/... and
+ // adjusting the simulator values (being set) into the physical values.
+ // The conversion is also done in the opposite direction (physical origin -> simulator origin).
+ //
+ // The updateParameter call is also captured and the values from the physics engine
+ // are converted into simulator origin values before being passed to the base
+ // class.
+
public virtual OMV.Vector3 PositionDisplacement { get; set; }
public virtual OMV.Quaternion OrientationDisplacement { get; set; }
- public virtual OMV.Vector3 CenterOfMassLocation { get; set; }
- public virtual OMV.Vector3 GeometricCenterLocation { get; set; }
public BSPrimDisplaced(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical)
: base(localID, primName, parent_scene, pos, size, rotation, pbs, pisPhysical)
{
- CenterOfMassLocation = RawPosition;
- GeometricCenterLocation = RawPosition;
+ ClearDisplacement();
+ }
+
+ public void ClearDisplacement()
+ {
+ PositionDisplacement = OMV.Vector3.Zero;
+ OrientationDisplacement = OMV.Quaternion.Identity;
+ }
+
+ // Set this sets and computes the displacement from the passed prim to the center-of-mass.
+ // A user set value for center-of-mass overrides whatever might be passed in here.
+ // The displacement is in local coordinates (relative to root prim in linkset oriented coordinates).
+ public virtual void SetEffectiveCenterOfMassW(Vector3 centerOfMassDisplacement)
+ {
+ Vector3 comDisp;
+ if (UserSetCenterOfMass.HasValue)
+ comDisp = (OMV.Vector3)UserSetCenterOfMass;
+ else
+ comDisp = centerOfMassDisplacement;
+
+ if (comDisp == Vector3.Zero)
+ {
+ // If there is no diplacement. Things get reset.
+ PositionDisplacement = OMV.Vector3.Zero;
+ OrientationDisplacement = OMV.Quaternion.Identity;
+ }
+ else
+ {
+ // Remember the displacement from root as well as the origional rotation of the
+ // new center-of-mass.
+ PositionDisplacement = comDisp;
+ OrientationDisplacement = OMV.Quaternion.Identity;
+ }
}
public override Vector3 ForcePosition
{
- get
- {
- return base.ForcePosition;
- }
+ get { return base.ForcePosition; }
set
{
- base.ForcePosition = value;
- CenterOfMassLocation = RawPosition;
- GeometricCenterLocation = RawPosition;
+ if (PositionDisplacement != OMV.Vector3.Zero)
+ base.ForcePosition = value - (PositionDisplacement * RawOrientation);
+ else
+ base.ForcePosition = value;
}
}
public override Quaternion ForceOrientation
{
- get
- {
- return base.ForceOrientation;
- }
+ get { return base.ForceOrientation; }
set
{
base.ForceOrientation = value;
}
}
+ // TODO: decide if this is the right place for these variables.
+ // Somehow incorporate the optional settability by the user.
// Is this used?
public override OMV.Vector3 CenterOfMass
{
- get { return CenterOfMassLocation; }
+ get { return RawPosition; }
}
// Is this used?
public override OMV.Vector3 GeometricCenter
{
- get { return GeometricCenterLocation; }
+ get { return RawPosition; }
}
-
public override void UpdateProperties(EntityProperties entprop)
{
// Undo any center-of-mass displacement that might have been done.
- if (PositionDisplacement != OMV.Vector3.Zero)
+ if (PositionDisplacement != OMV.Vector3.Zero || OrientationDisplacement != OMV.Quaternion.Identity)
{
// Correct for any rotation around the center-of-mass
// TODO!!!
- entprop.Position -= PositionDisplacement;
+ entprop.Position = entprop.Position + (PositionDisplacement * entprop.Rotation);
+ // entprop.Rotation = something;
}
base.UpdateProperties(entprop);
diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
index 989856201e..d65d40798e 100755
--- a/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
+++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrimLinkable.cs
@@ -38,6 +38,9 @@ namespace OpenSim.Region.Physics.BulletSPlugin
public class BSPrimLinkable : BSPrimDisplaced
{
public BSLinkset Linkset { get; set; }
+ // The index of this child prim.
+ public int LinksetChildIndex { get; set; }
+
public BSLinksetInfo LinksetInfo { get; set; }
public BSPrimLinkable(uint localID, String primName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size,
@@ -90,7 +93,6 @@ public class BSPrimLinkable : BSPrimDisplaced
DetailLog("{0},BSPrimLinkset.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ",
LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren);
return;
- base.delink();
}
// When simulator changes position, this might be moving a child of the linkset.
@@ -133,7 +135,8 @@ public class BSPrimLinkable : BSPrimDisplaced
// When going from non-physical to physical, this re-enables the constraints that
// had been automatically disabled when the mass was set to zero.
// For compound based linksets, this enables and disables interactions of the children.
- Linkset.Refresh(this);
+ if (Linkset != null) // null can happen during initialization
+ Linkset.Refresh(this);
}
protected override void MakeDynamic(bool makeStatic)
diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
index f68612c15e..35ae44c315 100644
--- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptInstance.cs
@@ -52,7 +52,12 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
{
bool Cancel();
void Abort();
- bool Wait(TimeSpan t);
+
+ ///
+ /// Wait for the work item to complete.
+ ///
+ /// The number of milliseconds to wait. Must be >= -1 (Timeout.Infinite).
+ bool Wait(int t);
}
///
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index be6ac0a746..96f650e8a4 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -4479,6 +4479,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
}
}
}
+
if (pushAllowed)
{
float distance = (PusheePos - m_host.AbsolutePosition).Length();
@@ -4507,17 +4508,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
applied_linear_impulse *= scaling_factor;
}
+
if (pusheeIsAvatar)
{
if (pusheeav != null)
{
- if (pusheeav.PhysicsActor != null)
+ PhysicsActor pa = pusheeav.PhysicsActor;
+
+ if (pa != null)
{
if (local != 0)
{
applied_linear_impulse *= m_host.GetWorldRotation();
}
- pusheeav.PhysicsActor.AddForce(applied_linear_impulse, true);
+
+ pa.AddForce(applied_linear_impulse, true);
}
}
}
diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
index 669cc3761c..bf19a42868 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs
@@ -595,7 +595,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
if (!m_coopTermination)
{
// If we're not co-operative terminating then try and wait for the event to complete before stopping
- if (workItem.Wait(new TimeSpan((long)timeout * 100000)))
+ if (workItem.Wait(timeout))
return true;
}
else
@@ -610,7 +610,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance
// For now, we will wait forever since the event should always cleanly terminate once LSL loop
// checking is implemented. May want to allow a shorter timeout option later.
- if (workItem.Wait(TimeSpan.MaxValue))
+ if (workItem.Wait(Timeout.Infinite))
{
if (DebugLevel >= 1)
m_log.DebugFormat(
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
index 2ac5c315af..8dd7677d7f 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XWorkItem.cs
@@ -57,8 +57,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine
wr.Abort();
}
- public bool Wait(TimeSpan t)
+ public bool Wait(int t)
{
+ // We use the integer version of WaitAll because the current version of SmartThreadPool has a bug with the
+ // TimeSpan version. The number of milliseconds in TimeSpan is an int64 so when STP casts it down to an
+ // int (32-bit) we can end up with bad values. This occurs on Windows though curious not on Mono 2.10.8
+ // (or very likely other versions of Mono at least up until 3.0.3).
return SmartThreadPool.WaitAll(new IWorkItemResult[] {wr}, t, false);
}
}
diff --git a/bin/Ionic.Zip.dll b/bin/Ionic.Zip.dll
index 95fa928855..e37f1bdea5 100755
Binary files a/bin/Ionic.Zip.dll and b/bin/Ionic.Zip.dll differ
diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll
index 4dd2f3880d..e7a8a41ec0 100755
Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ
diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so
index cb8742af34..4bf23a6496 100755
Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ
diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll
index c9f5814f9d..63ac1a91aa 100755
Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ
diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so
index 19fc7bfdae..422681e423 100755
Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ