diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index bed9a498ec..3f7a7730ed 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -331,7 +331,7 @@ namespace OpenSim /// /// /// - public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene) + public List CreateRegion(RegionInfo regionInfo, bool portadd_flag, out IScene scene) { return CreateRegion(regionInfo, portadd_flag, false, out scene); } @@ -341,7 +341,7 @@ namespace OpenSim /// /// /// - public IClientNetworkServer CreateRegion(RegionInfo regionInfo, out IScene scene) + public List CreateRegion(RegionInfo regionInfo, out IScene scene) { return CreateRegion(regionInfo, false, true, out scene); } @@ -353,7 +353,7 @@ namespace OpenSim /// /// /// - public IClientNetworkServer CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene) + public List CreateRegion(RegionInfo regionInfo, bool portadd_flag, bool do_post_init, out IScene mscene) { int port = regionInfo.InternalEndPoint.Port; @@ -378,8 +378,8 @@ namespace OpenSim Util.XmlRpcCommand(proxyUrl, "AddPort", port, port + proxyOffset, regionInfo.ExternalHostName); } - IClientNetworkServer clientServer; - Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServer); + List clientServers; + Scene scene = SetupScene(regionInfo, proxyOffset, Config, out clientServers); m_log.Info("[MODULES]: Loading Region's modules (old style)"); @@ -483,8 +483,11 @@ namespace OpenSim if (m_autoCreateClientStack) { - m_clientServers.Add(clientServer); - clientServer.Start(); + foreach (IClientNetworkServer clientserver in clientServers) + { + m_clientServers.Add(clientserver); + clientserver.Start(); + } } if (scene.SnmpService != null) @@ -504,7 +507,7 @@ namespace OpenSim scene.Start(); scene.StartScripts(); - return clientServer; + return clientServers; } /// @@ -725,7 +728,7 @@ namespace OpenSim /// /// /// - protected Scene SetupScene(RegionInfo regionInfo, out IClientNetworkServer clientServer) + protected Scene SetupScene(RegionInfo regionInfo, out List clientServer) { return SetupScene(regionInfo, 0, null, out clientServer); } @@ -739,19 +742,20 @@ namespace OpenSim /// /// protected Scene SetupScene( - RegionInfo regionInfo, int proxyOffset, IConfigSource configSource, out IClientNetworkServer clientServer) + RegionInfo regionInfo, int proxyOffset, IConfigSource configSource, out List clientServer) { + List clientNetworkServers = null; + AgentCircuitManager circuitManager = new AgentCircuitManager(); IPAddress listenIP = regionInfo.InternalEndPoint.Address; //if (!IPAddress.TryParse(regionInfo.InternalEndPoint, out listenIP)) // listenIP = IPAddress.Parse("0.0.0.0"); uint port = (uint) regionInfo.InternalEndPoint.Port; - + IClientNetworkServer clientNetworkServer; if (m_autoCreateClientStack) { - clientServer - = m_clientStackManager.CreateServer( + clientNetworkServers = m_clientStackManager.CreateServers( listenIP, ref port, proxyOffset, regionInfo.m_allow_alternate_ports, configSource, circuitManager); } @@ -766,9 +770,12 @@ namespace OpenSim if (m_autoCreateClientStack) { - clientServer.AddScene(scene); + foreach (IClientNetworkServer clientnetserver in clientNetworkServers) + { + clientnetserver.AddScene(scene); + } } - + clientServer = clientNetworkServers; scene.LoadWorldMap(); scene.PhysicsScene = GetPhysicsScene(scene.RegionInfo.RegionName); diff --git a/OpenSim/Region/ClientStack/ClientStackManager.cs b/OpenSim/Region/ClientStack/ClientStackManager.cs index 84ea0b34db..299aabd787 100644 --- a/OpenSim/Region/ClientStack/ClientStackManager.cs +++ b/OpenSim/Region/ClientStack/ClientStackManager.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections.Generic; using System.Net; using System.Reflection; using log4net; @@ -38,39 +39,53 @@ namespace OpenSim.Region.ClientStack { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private Type plugin; - private Assembly pluginAssembly; + private List plugin = new List(); + private List pluginAssembly = new List(); - public ClientStackManager(string dllName) + public ClientStackManager(string pDllName) { - m_log.Info("[CLIENTSTACK]: Attempting to load " + dllName); - - try + List clientstacks = new List(); + if (pDllName.Contains(",")) { - plugin = null; - pluginAssembly = Assembly.LoadFrom(dllName); + clientstacks = new List(pDllName.Split(',')); + } + else + { + clientstacks.Add(pDllName); + } + foreach (string dllName in clientstacks) + { + m_log.Info("[CLIENTSTACK]: Attempting to load " + dllName); - foreach (Type pluginType in pluginAssembly.GetTypes()) + try { - if (pluginType.IsPublic) - { - Type typeInterface = pluginType.GetInterface("IClientNetworkServer", true); + //plugin = null; + Assembly itemAssembly = Assembly.LoadFrom(dllName); + pluginAssembly.Add(itemAssembly); - if (typeInterface != null) + foreach (Type pluginType in itemAssembly.GetTypes()) + { + if (pluginType.IsPublic) { - m_log.Info("[CLIENTSTACK]: Added IClientNetworkServer Interface"); - plugin = pluginType; - return; + Type typeInterface = pluginType.GetInterface("IClientNetworkServer", true); + + if (typeInterface != null) + { + m_log.Info("[CLIENTSTACK]: Added IClientNetworkServer Interface"); + plugin.Add(pluginType); + break; + } } } } - } catch (ReflectionTypeLoadException e) - { - foreach (Exception e2 in e.LoaderExceptions) + catch (ReflectionTypeLoadException e) { - m_log.Error(e2.ToString()); + foreach (Exception e2 in e.LoaderExceptions) + { + m_log.Error(e2.ToString()); + } + throw e; } - throw e; } } @@ -84,11 +99,11 @@ namespace OpenSim.Region.ClientStack /// /// /// - public IClientNetworkServer CreateServer( + public List CreateServers( IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, AgentCircuitManager authenticateClass) { - return CreateServer( + return CreateServers( _listenIP, ref port, proxyPortOffset, allow_alternate_port, null, authenticateClass); } @@ -105,20 +120,24 @@ namespace OpenSim.Region.ClientStack /// /// /// - public IClientNetworkServer CreateServer( + public List CreateServers( IPAddress _listenIP, ref uint port, int proxyPortOffset, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager authenticateClass) { + List servers = new List(); if (plugin != null) { - IClientNetworkServer server = - (IClientNetworkServer)Activator.CreateInstance(pluginAssembly.GetType(plugin.ToString())); - - server.Initialise( - _listenIP, ref port, proxyPortOffset, allow_alternate_port, - configSource, authenticateClass); - - return server; + for (int i = 0; i < plugin.Count; i++) + { + IClientNetworkServer server = + (IClientNetworkServer) Activator.CreateInstance(pluginAssembly[i].GetType(plugin[i].ToString())); + + server.Initialise( + _listenIP, ref port, proxyPortOffset, allow_alternate_port, + configSource, authenticateClass); + servers.Add(server); + } + return servers; } m_log.Error("[CLIENTSTACK]: Couldn't initialize a new server"); diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index a0f1e8c560..730643d52a 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -790,32 +790,43 @@ namespace OpenSim.Region.CoreModules.Asset { UuidGatherer gatherer = new UuidGatherer(m_AssetService); + HashSet uniqueUuids = new HashSet(); Dictionary assets = new Dictionary(); + foreach (Scene s in m_Scenes) { StampRegionStatusFile(s.RegionInfo.RegionID); s.ForEachSOG(delegate(SceneObjectGroup e) - { + { gatherer.GatherAssetUuids(e, assets); + + foreach (UUID assetID in assets.Keys) + { + uniqueUuids.Add(assetID); + + string filename = GetFileName(assetID.ToString()); + + if (File.Exists(filename)) + { + File.SetLastAccessTime(filename, DateTime.Now); + } + else if (storeUncached) + { + AssetBase cachedAsset = m_AssetService.Get(assetID.ToString()); + if (cachedAsset == null && assets[assetID] != AssetType.Unknown) + m_log.DebugFormat( + "[FLOTSAM ASSET CACHE]: Could not find asset {0}, type {1} referenced by object {2} at {3} in scene {4} when pre-caching all scene assets", + assetID, assets[assetID], e.Name, e.AbsolutePosition, s.Name); + } + } + + assets.Clear(); }); } - foreach (UUID assetID in assets.Keys) - { - string filename = GetFileName(assetID.ToString()); - if (File.Exists(filename)) - { - File.SetLastAccessTime(filename, DateTime.Now); - } - else if (storeUncached) - { - m_AssetService.Get(assetID.ToString()); - } - } - - return assets.Keys.Count; + return uniqueUuids.Count; } /// diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index 5836eb99ce..b61062f2ce 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -75,7 +75,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage public void Close() { } public void PostInitialise() { } - /// /// /// @@ -136,7 +135,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage /// public void AddRegion(Scene scene) { - if (! m_enabled) + if (!m_enabled) return; // Every shared region module has to maintain an indepedent list of @@ -209,6 +208,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage using (Image mapTile = tileGenerator.CreateMapTile()) { + // XXX: The MapImageModule will return a null if the user has chosen not to create map tiles and there + // is no static map tile. + if (mapTile == null) + return; + using (MemoryStream stream = new MemoryStream()) { mapTile.Save(stream, ImageFormat.Jpeg); diff --git a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs index d412efcfce..e7065dcd27 100644 --- a/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/LegacyMap/MapImageModule.cs @@ -113,7 +113,6 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap //t = System.Environment.TickCount - t; //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); - if (drawPrimVolume) { DrawObjectVolume(m_scene, mapbmp); @@ -121,7 +120,7 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap } else { - mapbmp = fetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); + mapbmp = FetchTexture(m_scene.RegionInfo.RegionSettings.TerrainImageID); } return mapbmp; } @@ -232,11 +231,19 @@ namespace OpenSim.Region.CoreModules.World.LegacyMap // } // } - private Bitmap fetchTexture(UUID id) + private Bitmap FetchTexture(UUID id) { AssetBase asset = m_scene.AssetService.Get(id.ToString()); - m_log.DebugFormat("[MAPTILE]: Fetched static texture {0}, found: {1}", id, asset != null); - if (asset == null) return null; + + if (asset != null) + { + m_log.DebugFormat("[MAPTILE]: Static map image texture {0} found for {1}", id, m_scene.Name); + } + else + { + m_log.WarnFormat("[MAPTILE]: Static map image texture {0} not found for {1}", id, m_scene.Name); + return null; + } ManagedImage managedImage; Image image; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 6005f0748e..c3524651aa 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2517,7 +2517,7 @@ namespace OpenSim.Region.Framework.Scenes ParentPart = m_scene.GetSceneObjectPart(m_requestedSitTargetID); ParentID = m_requestedSitTargetID; - + m_AngularVelocity = Vector3.Zero; Velocity = Vector3.Zero; RemoveFromPhysicalScene(); @@ -2533,7 +2533,8 @@ namespace OpenSim.Region.Framework.Scenes public void HandleAgentSitOnGround() { -// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick. +// m_updateCount = 0; // Kill animation update burst so that the SIT_G.. will stick.. + m_AngularVelocity = Vector3.Zero; Animator.TrySetMovementAnimation("SIT_GROUND_CONSTRAINED"); SitGround = true; RemoveFromPhysicalScene(); diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 2279e628b2..b09ae39c4a 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -127,7 +127,10 @@ namespace OpenSim.Region.Framework.Scenes /// within this object). /// /// The scene object for which to gather assets - /// The assets gathered + /// + /// A dictionary which is populated with the asset UUIDs gathered and the type of that asset. + /// For assets where the type is not clear (e.g. UUIDs extracted from LSL and notecards), the type is Unknown. + /// public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary assetUuids) { // m_log.DebugFormat( @@ -257,8 +260,9 @@ namespace OpenSim.Region.Framework.Scenes UUID uuid = new UUID(uuidMatch.Value); // m_log.DebugFormat("[ARCHIVER]: Recording {0} in text", uuid); - // Assume AssetIDs embedded are textures. - assetUuids[uuid] = AssetType.Texture; + // Embedded asset references (if not false positives) could be for many types of asset, so we will + // label these as unknown. + assetUuids[uuid] = AssetType.Unknown; } } } diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs index 34894badf7..0b7b31bd32 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStore.cs @@ -68,7 +68,41 @@ 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 quotes to bare identifiers which are limited to alphabetic characters + protected static Regex m_ParsePassThree = new Regex("\\.([a-zA-Z]+)"); + + // remove extra separator characters + protected static Regex m_ParsePassFour = new Regex("\\.+"); + + // expression used to validate the full path, this is canonical representation + protected static Regex m_ValidatePath = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$"); + + // expression used to match path components + protected static Regex m_PathComponent = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)"); + + // extract the internals of an array reference + protected static Regex m_SimpleArrayPattern = new Regex("\\[([0-9]+)\\]"); + protected static Regex m_ArrayPattern = new Regex("\\[([0-9]+|\\+)\\]"); + + // extract the internals of a has reference + protected static Regex m_HashPattern = new Regex("{([^}]+)}"); + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + public static string CanonicalPathExpression(string path) + { + return PathExpressionToKey(ParsePathExpression(path)); + } + // ----------------------------------------------------------------- /// /// @@ -224,9 +258,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore if (result == null) return false; - Regex aPattern = new Regex("\\[([0-9]+|\\+)\\]"); - MatchCollection amatches = aPattern.Matches(pkey,0); - + // Check for and extract array references + MatchCollection amatches = m_ArrayPattern.Matches(pkey,0); if (amatches.Count > 0) { if (result.Type != OSDType.Array) @@ -263,9 +296,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore return false; } - Regex hPattern = new Regex("{([^}]+)}"); - MatchCollection hmatches = hPattern.Matches(pkey,0); - + // Check for and extract hash references + MatchCollection hmatches = m_HashPattern.Matches(pkey,0); if (hmatches.Count > 0) { Match match = hmatches[0]; @@ -340,26 +372,21 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore path = "." + path + "."; // add separators for quoted paths - Regex pass1 = new Regex("{[^}]+}"); - path = pass1.Replace(path,".$0.",-1,0); + path = m_ParsePassOne.Replace(path,".$0.",-1,0); // add separators for array references - Regex pass2 = new Regex("(\\[[0-9]+\\]|\\[\\+\\])"); - path = pass2.Replace(path,".$0.",-1,0); + path = m_ParsePassTwo.Replace(path,".$0.",-1,0); // add quotes to bare identifier - Regex pass3 = new Regex("\\.([a-zA-Z]+)"); - path = pass3.Replace(path,".{$1}",-1,0); + path = m_ParsePassThree.Replace(path,".{$1}",-1,0); // remove extra separators - Regex pass4 = new Regex("\\.+"); - path = pass4.Replace(path,".",-1,0); + path = m_ParsePassFour.Replace(path,".",-1,0); - Regex validate = new Regex("^\\.(({[^}]+}|\\[[0-9]+\\]|\\[\\+\\])\\.)+$"); - if (validate.IsMatch(path)) + // validate the results (catches extra quote characters for example) + if (m_ValidatePath.IsMatch(path)) { - Regex parser = new Regex("\\.({[^}]+}|\\[[0-9]+\\]|\\[\\+\\]+)"); - MatchCollection matches = parser.Matches(path,0); + MatchCollection matches = m_PathComponent.Matches(path,0); foreach (Match match in matches) m_path.Push(match.Groups[1].Value); } @@ -385,9 +412,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore return null; // ---------- Check for an array index ---------- - Regex aPattern = new Regex("\\[([0-9]+)\\]"); - MatchCollection amatches = aPattern.Matches(pkey,0); - + MatchCollection amatches = m_SimpleArrayPattern.Matches(pkey,0); + if (amatches.Count > 0) { if (rmap.Type != OSDType.Array) @@ -410,9 +436,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore } // ---------- Check for a hash index ---------- - Regex hPattern = new Regex("{([^}]+)}"); - MatchCollection hmatches = hPattern.Matches(pkey,0); - + MatchCollection hmatches = m_HashPattern.Matches(pkey,0); + if (hmatches.Count > 0) { if (rmap.Type != OSDType.Map) diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index 29955afd5a..5b7a79d013 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs @@ -165,29 +165,32 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore try { - m_comms.RegisterScriptInvocation(this, "JsonCreateStore"); - m_comms.RegisterScriptInvocation(this, "JsonDestroyStore"); - m_comms.RegisterScriptInvocation(this, "JsonTestStore"); + m_comms.RegisterScriptInvocations(this); - m_comms.RegisterScriptInvocation(this, "JsonReadNotecard"); - m_comms.RegisterScriptInvocation(this, "JsonWriteNotecard"); + // m_comms.RegisterScriptInvocation(this, "JsonCreateStore"); + // m_comms.RegisterScriptInvocation(this, "JsonDestroyStore"); + // m_comms.RegisterScriptInvocation(this, "JsonTestStore"); - m_comms.RegisterScriptInvocation(this, "JsonTestPath"); - m_comms.RegisterScriptInvocation(this, "JsonTestPathJson"); + // m_comms.RegisterScriptInvocation(this, "JsonReadNotecard"); + // m_comms.RegisterScriptInvocation(this, "JsonWriteNotecard"); - m_comms.RegisterScriptInvocation(this, "JsonGetValue"); - m_comms.RegisterScriptInvocation(this, "JsonGetValueJson"); + // m_comms.RegisterScriptInvocation(this, "JsonTestPathList"); + // m_comms.RegisterScriptInvocation(this, "JsonTestPath"); + // m_comms.RegisterScriptInvocation(this, "JsonTestPathJson"); - m_comms.RegisterScriptInvocation(this, "JsonTakeValue"); - m_comms.RegisterScriptInvocation(this, "JsonTakeValueJson"); + // m_comms.RegisterScriptInvocation(this, "JsonGetValue"); + // m_comms.RegisterScriptInvocation(this, "JsonGetValueJson"); - m_comms.RegisterScriptInvocation(this, "JsonReadValue"); - m_comms.RegisterScriptInvocation(this, "JsonReadValueJson"); + // m_comms.RegisterScriptInvocation(this, "JsonTakeValue"); + // m_comms.RegisterScriptInvocation(this, "JsonTakeValueJson"); - m_comms.RegisterScriptInvocation(this, "JsonSetValue"); - m_comms.RegisterScriptInvocation(this, "JsonSetValueJson"); + // m_comms.RegisterScriptInvocation(this, "JsonReadValue"); + // m_comms.RegisterScriptInvocation(this, "JsonReadValueJson"); - m_comms.RegisterScriptInvocation(this, "JsonRemoveValue"); + // m_comms.RegisterScriptInvocation(this, "JsonSetValue"); + // m_comms.RegisterScriptInvocation(this, "JsonSetValueJson"); + + // m_comms.RegisterScriptInvocation(this, "JsonRemoveValue"); } catch (Exception e) { @@ -215,17 +218,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected void GenerateRuntimeError(string msg) - { - throw new Exception("JsonStore Runtime Error: " + msg); - } - - // ----------------------------------------------------------------- - /// - /// - /// - // ----------------------------------------------------------------- - protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) + [ScriptInvocation] + public UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) { UUID uuid = UUID.Zero; if (! m_store.CreateStore(value, ref uuid)) @@ -239,7 +233,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) + [ScriptInvocation] + public int JsonDestroyStore(UUID hostID, UUID scriptID, UUID storeID) { return m_store.DestroyStore(storeID) ? 1 : 0; } @@ -249,7 +244,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected int JsonTestStore(UUID hostID, UUID scriptID, UUID storeID) + [ScriptInvocation] + public int JsonTestStore(UUID hostID, UUID scriptID, UUID storeID) { return m_store.TestStore(storeID) ? 1 : 0; } @@ -259,7 +255,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) + [ScriptInvocation] + public UUID JsonReadNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, UUID assetID) { UUID reqID = UUID.Random(); Util.FireAndForget(delegate(object o) { DoJsonReadNotecard(reqID,hostID,scriptID,storeID,path,assetID); }); @@ -271,7 +268,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name) + [ScriptInvocation] + public UUID JsonWriteNotecard(UUID hostID, UUID scriptID, UUID storeID, string path, string name) { UUID reqID = UUID.Random(); Util.FireAndForget(delegate(object o) { DoJsonWriteNotecard(reqID,hostID,scriptID,storeID,path,name); }); @@ -283,12 +281,25 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path) + [ScriptInvocation] + public string JsonList2Path(UUID hostID, UUID scriptID, object[] pathlist) + { + return JsonStore.CanonicalPathExpression(ConvertList2Path(pathlist)); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + [ScriptInvocation] + public int JsonTestPath(UUID hostID, UUID scriptID, UUID storeID, string path) { return m_store.TestPath(storeID,path,false) ? 1 : 0; } - protected int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path) + [ScriptInvocation] + public int JsonTestPathJson(UUID hostID, UUID scriptID, UUID storeID, string path) { return m_store.TestPath(storeID,path,true) ? 1 : 0; } @@ -298,12 +309,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value) + [ScriptInvocation] + public int JsonSetValue(UUID hostID, UUID scriptID, UUID storeID, string path, string value) { return m_store.SetValue(storeID,path,value,false) ? 1 : 0; } - protected int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value) + [ScriptInvocation] + public int JsonSetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path, string value) { return m_store.SetValue(storeID,path,value,true) ? 1 : 0; } @@ -313,7 +326,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path) + [ScriptInvocation] + public int JsonRemoveValue(UUID hostID, UUID scriptID, UUID storeID, string path) { return m_store.RemoveValue(storeID,path) ? 1 : 0; } @@ -323,14 +337,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path) + [ScriptInvocation] + public string JsonGetValue(UUID hostID, UUID scriptID, UUID storeID, string path) { string value = String.Empty; m_store.GetValue(storeID,path,false,out value); return value; } - protected string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) + [ScriptInvocation] + public string JsonGetValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) { string value = String.Empty; m_store.GetValue(storeID,path,true, out value); @@ -342,20 +358,70 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path) + [ScriptInvocation] + public UUID JsonTakeValue(UUID hostID, UUID scriptID, UUID storeID, string path) { UUID reqID = UUID.Random(); Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,false); }); return reqID; } - protected UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) + [ScriptInvocation] + public UUID JsonTakeValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) { UUID reqID = UUID.Random(); Util.FireAndForget(delegate(object o) { DoJsonTakeValue(scriptID,reqID,storeID,path,true); }); return reqID; } + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + [ScriptInvocation] + public UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); }); + return reqID; + } + + [ScriptInvocation] + public UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) + { + UUID reqID = UUID.Random(); + Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); }); + return reqID; + } + +#endregion + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected void GenerateRuntimeError(string msg) + { + throw new Exception("JsonStore Runtime Error: " + msg); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- + protected void DispatchValue(UUID scriptID, UUID reqID, string value) + { + m_comms.DispatchReply(scriptID,1,value,reqID.ToString()); + } + + // ----------------------------------------------------------------- + /// + /// + /// + // ----------------------------------------------------------------- private void DoJsonTakeValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson) { try @@ -377,20 +443,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - protected UUID JsonReadValue(UUID hostID, UUID scriptID, UUID storeID, string path) - { - UUID reqID = UUID.Random(); - Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,false); }); - return reqID; - } - - protected UUID JsonReadValueJson(UUID hostID, UUID scriptID, UUID storeID, string path) - { - UUID reqID = UUID.Random(); - Util.FireAndForget(delegate(object o) { DoJsonReadValue(scriptID,reqID,storeID,path,true); }); - return reqID; - } - private void DoJsonReadValue(UUID scriptID, UUID reqID, UUID storeID, string path, bool useJson) { try @@ -406,18 +458,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore DispatchValue(scriptID,reqID,String.Empty); } -#endregion - - // ----------------------------------------------------------------- - /// - /// - /// - // ----------------------------------------------------------------- - protected void DispatchValue(UUID scriptID, UUID reqID, string value) - { - m_comms.DispatchReply(scriptID,1,value,reqID.ToString()); - } - // ----------------------------------------------------------------- /// /// @@ -505,5 +545,43 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString()); } + + // ----------------------------------------------------------------- + /// + /// Convert a list of values that are path components to a single string path + /// + // ----------------------------------------------------------------- + protected static Regex m_ArrayPattern = new Regex("^([0-9]+|\\+)$"); + private string ConvertList2Path(object[] pathlist) + { + string path = ""; + for (int i = 0; i < pathlist.Length; i++) + { + string token = ""; + + if (pathlist[i] is string) + { + token = pathlist[i].ToString(); + + // Check to see if this is a bare number which would not be a valid + // identifier otherwise + if (m_ArrayPattern.IsMatch(token)) + token = '[' + token + ']'; + } + else if (pathlist[i] is int) + { + token = "[" + pathlist[i].ToString() + "]"; + } + else + { + token = "." + pathlist[i].ToString() + "."; + } + + path += token + "."; + } + + return path; + } + } } \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 3884a5dd0d..192bcb5f3a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -126,9 +126,9 @@ public sealed class BSCharacter : BSPhysObject DetailLog("{0},BSCharacter.Destroy", LocalID); PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() { - PhysicsScene.Shapes.DereferenceBody(PhysBody, true /* inTaintTime */, null /* bodyCallback */); + PhysicsScene.Shapes.DereferenceBody(PhysBody, null /* bodyCallback */); PhysBody.Clear(); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true /* inTaintTime */, null /* bodyCallback */); + PhysicsScene.Shapes.DereferenceShape(PhysShape, null /* bodyCallback */); PhysShape.Clear(); }); } @@ -557,11 +557,12 @@ public sealed class BSCharacter : BSPhysObject { get { - return _velocityMotor.TargetValue; + return m_targetVelocity; } set { DetailLog("{0},BSCharacter.setTargetVelocity,call,vel={1}", LocalID, value); + m_targetVelocity = value; OMV.Vector3 targetVel = value; if (_setAlwaysRun) targetVel *= BSParam.AvatarAlwaysRunFactor; @@ -591,7 +592,6 @@ public sealed class BSCharacter : BSPhysObject _velocityMotor.Reset(); _velocityMotor.SetCurrent(_velocity); _velocityMotor.SetTarget(_velocity); - // Even though the motor is initialized, it's not used and the velocity goes straight into the avatar. _velocityMotor.Enabled = false; DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 05ab180050..8ecf2ff521 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -581,9 +581,18 @@ namespace OpenSim.Region.Physics.BulletSPlugin } #endregion // Vehicle parameter setting + public void Refresh() + { + // If asking for a refresh, reset the physical parameters before the next simulation step. + PhysicsScene.PostTaintObject("BSDynamics.Refresh", Prim.LocalID, delegate() + { + SetPhysicalParameters(); + }); + } + // Some of the properties of this prim may have changed. // Do any updating needed for a vehicle - public void Refresh() + private void SetPhysicalParameters() { if (IsActive) { @@ -614,7 +623,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // The actual vehicle gravity is set to zero in Bullet so we can do all the application of same. PhysicsScene.PE.SetGravity(Prim.PhysBody, Vector3.Zero); - VDetailLog("{0},BSDynamics.Refresh,mass={1},inert={2},grav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", + VDetailLog("{0},BSDynamics.SetPhysicalParameters,mass={1},inert={2},vehGrav={3},aDamp={4},frict={5},rest={6},lFact={7},aFact={8}", Prim.LocalID, m_vehicleMass, Prim.Inertia, m_VehicleGravity, BSParam.VehicleAngularDamping, BSParam.VehicleFriction, BSParam.VehicleRestitution, BSParam.VehicleLinearFactor, BSParam.VehicleAngularFactor @@ -622,26 +631,15 @@ namespace OpenSim.Region.Physics.BulletSPlugin } else { - PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); + if (Prim.PhysBody.HasPhysicalBody) + PhysicsScene.PE.RemoveFromCollisionFlags(Prim.PhysBody, CollisionFlags.BS_VEHICLE_COLLISIONS); } } public bool RemoveBodyDependencies(BSPhysObject prim) { - // If active, we need to add our properties back when the body is rebuilt. - return IsActive; - } - - public void RestoreBodyDependencies(BSPhysObject prim) - { - if (Prim.LocalID != prim.LocalID) - { - // The call should be on us by our prim. Error if not. - PhysicsScene.Logger.ErrorFormat("{0} RestoreBodyDependencies: called by not my prim. passedLocalID={1}, vehiclePrimLocalID={2}", - LogHeader, prim.LocalID, Prim.LocalID); - return; - } Refresh(); + return IsActive; } #region Known vehicle value functions diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 54dc458e09..0c4db4063c 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -219,43 +219,65 @@ public sealed class BSLinksetCompound : BSLinkset { // Gather the child info. It might not be there if the linkset is in transition. BSLinksetCompoundInfo lsi = updated.LinksetInfo as BSLinksetCompoundInfo; - if (LinksetRoot.PhysShape.HasPhysicalShape && lsi != null) + if (lsi != null) { - if (PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) + // Since the child moved or rotationed, it needs a new relative position within the linkset + BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement); + updated.LinksetInfo = newLsi; + + // Find the physical instance of the child + if (LinksetRoot.PhysShape.HasPhysicalShape && PhysicsScene.PE.IsCompound(LinksetRoot.PhysShape)) { - BulletShape linksetChildShape = PhysicsScene.PE.GetChildShapeFromCompoundShapeIndex(LinksetRoot.PhysShape, lsi.Index); - if (linksetChildShape.HasPhysicalShape) + // 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) { - // Compute the offset from the center-of-gravity - BSLinksetCompoundInfo newLsi = new BSLinksetCompoundInfo(lsi.Index, LinksetRoot, updated, LinksetRoot.PositionDisplacement); - PhysicsScene.PE.UpdateChildTransform(LinksetRoot.PhysShape, lsi.Index, - newLsi.OffsetFromCenterOfMass, - newLsi.OffsetRot, - true /* shouldRecalculateLocalAabb */); - DetailLog("{0},BSLinksetCompound.UpdateProperties,changeChildPosRot,whichUpdated={1},newLsi={2}", - updated.LocalID, whichUpdated, newLsi); - updated.LinksetInfo = newLsi; - updatedChild = true; + 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 } else // DEBUG DEBUG { // DEBUG DEBUG - DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noChildShape,shape={1}", - updated.LocalID, linksetChildShape); + // 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); } // DEBUG DEBUG } else // DEBUG DEBUG { // DEBUG DEBUG - DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,notCompound", updated.LocalID); + DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noBodyOrNotCompound", updated.LocalID); } // DEBUG DEBUG } else // DEBUG DEBUG { // DEBUG DEBUG - DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,rootPhysShape={1},lsi={2}", - updated.LocalID, LinksetRoot.PhysShape, lsi == null ? "NULL" : lsi.ToString()); + DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild,noLinkSetInfo,rootPhysShape={1}", + updated.LocalID, LinksetRoot.PhysShape); } // DEBUG DEBUG + if (!updatedChild) { // If couldn't do the individual child, the linkset needs a rebuild to incorporate the new child info. + // Note: there are several ways through this code that will not update the child if + // the linkset is being rebuilt. In this case, scheduling a rebuild is a NOOP since + // there will already be a rebuild scheduled. DetailLog("{0},BSLinksetCompound.UpdateProperties,couldNotUpdateChild.schedulingRebuild,whichUpdated={1}", updated.LocalID, whichUpdated); updated.LinksetInfo = null; // setting to 'null' causes relative position to be recomputed. @@ -274,13 +296,14 @@ public sealed class BSLinksetCompound : BSLinkset bool ret = false; DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.AddrString, IsRoot(child)); + child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody, IsRoot(child)); if (!IsRoot(child)) { // Because it is a convenient time, recompute child world position and rotation based on // its position in the linkset. - RecomputeChildWorldPosition(child, true); + RecomputeChildWorldPosition(child, true /* inTaintTime */); + child.LinksetInfo = null; } // Cannot schedule a refresh/rebuild here because this routine is called when @@ -295,6 +318,14 @@ public sealed class BSLinksetCompound : BSLinkset // prim. The child prim's location must be recomputed based on the location of the root shape. private void RecomputeChildWorldPosition(BSPhysObject child, bool inTaintTime) { + // For the moment (20130201), disable this computation (converting the child physical addr back to + // a region address) until we have a good handle on center-of-mass offsets and what the physics + // engine moving a child actually means. + // The simulator keeps track of where children should be as the linkset moves. Setting + // the pos/rot here does not effect that knowledge as there is no good way for the + // physics engine to send the simulator an update for a child. + + /* BSLinksetCompoundInfo lci = child.LinksetInfo as BSLinksetCompoundInfo; if (lci != null) { @@ -323,6 +354,7 @@ public sealed class BSLinksetCompound : BSLinkset // LogHeader, child.LocalID); DetailLog("{0},BSLinksetCompound.recomputeChildWorldPosition,noRelativePositonInfo", child.LocalID); } + */ } // ================================================================ @@ -356,6 +388,7 @@ public sealed class BSLinksetCompound : BSLinkset // Cause the child's body to be rebuilt and thus restored to normal operation RecomputeChildWorldPosition(child, false); + child.LinksetInfo = null; child.ForceBodyShapeRebuild(false); if (!HasAnyChildren) @@ -377,16 +410,16 @@ public sealed class BSLinksetCompound : BSLinkset // Constraint linksets are rebuilt every time. // Note that this works for rebuilding just the root after a linkset is taken apart. // Called at taint time!! - private bool disableCOM = true; // disable until we get this debugged + private bool disableCOM = true; // DEBUG DEBUG: disable until we get this debugged private void RecomputeLinksetCompound() { try { - // Suppress rebuilding while rebuilding + // Suppress rebuilding while rebuilding. (We know rebuilding is on only one thread.) Rebuilding = true; // Cause the root shape to be rebuilt as a compound object with just the root in it - LinksetRoot.ForceBodyShapeRebuild(true); + LinksetRoot.ForceBodyShapeRebuild(true /* inTaintTime */); // 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. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs index a113530567..823402ba03 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs @@ -190,18 +190,6 @@ public abstract class BSPhysObject : PhysicsActor public abstract OMV.Quaternion RawOrientation { get; set; } public abstract OMV.Quaternion ForceOrientation { get; set; } - // The system is telling us the velocity it wants to move at. - // Velocity in world coordinates. - // protected OMV.Vector3 m_targetVelocity; // use the definition in PhysicsActor - public override OMV.Vector3 TargetVelocity - { - get { return m_targetVelocity; } - set - { - m_targetVelocity = value; - Velocity = value; - } - } public virtual float TargetSpeed { get diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index b5dd131abe..54bf063add 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -146,9 +146,9 @@ public sealed class BSPrim : BSPhysObject { DetailLog("{0},BSPrim.Destroy,taint,", LocalID); // If there are physical body and shape, release my use of same. - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); + PhysicsScene.Shapes.DereferenceBody(PhysBody, null); PhysBody.Clear(); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); + PhysicsScene.Shapes.DereferenceShape(PhysShape, null); PhysShape.Clear(); }); } @@ -181,11 +181,19 @@ public sealed class BSPrim : BSPhysObject public override bool ForceBodyShapeRebuild(bool inTaintTime) { - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() + if (inTaintTime) { _mass = CalculateMass(); // changing the shape changes the mass CreateGeomAndObject(true); - }); + } + else + { + PhysicsScene.TaintedObject("BSPrim.ForceBodyShapeRebuild", delegate() + { + _mass = CalculateMass(); // changing the shape changes the mass + CreateGeomAndObject(true); + }); + } return true; } public override bool Grabbed { @@ -1597,9 +1605,9 @@ public sealed class BSPrim : BSPhysObject public void CreateGeomAndObject(bool forceRebuild) { // Create the correct physical representation for this type of object. - // Updates PhysBody and PhysShape with the new information. + // Updates base.PhysBody and base.PhysShape with the new information. // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) + PhysicsScene.Shapes.GetBodyAndShape(false /*forceRebuild */, PhysicsScene.World, this, null, delegate(BulletBody dBody) { // Called if the current prim body is about to be destroyed. // Remove all the physical dependencies on the old body. diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs index 473ef10aca..37bccbce4b 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs @@ -116,8 +116,7 @@ public sealed class BSShapeCollection : IDisposable // rebuild the body around it. // Updates prim.BSBody with information/pointers to requested body // Returns 'true' if BSBody was changed. - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.PhysShape, bodyCallback); + bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, bodyCallback); ret = newGeom || newBody; } DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", @@ -134,48 +133,44 @@ public sealed class BSShapeCollection : IDisposable // Track another user of a body. // We presume the caller has allocated the body. // Bodies only have one user so the body is just put into the world if not already there. - public void ReferenceBody(BulletBody body, bool inTaintTime) + private void ReferenceBody(BulletBody body) { lock (m_collectionActivityLock) { if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() + if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) { - if (!PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) - { - PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body); - if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); - } - }); + PhysicsScene.PE.AddObjectToWorld(PhysicsScene.World, body); + if (DDetail) DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); + } } } // Release the usage of a body. // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) + // Called in taint time. + public void DereferenceBody(BulletBody body, BodyDestructionCallback bodyCallback ) { if (!body.HasPhysicalBody) return; + PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceBody"); + lock (m_collectionActivityLock) { - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() + if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1}", body.ID, body); + // If the caller needs to know the old body is going away, pass the event up. + if (bodyCallback != null) bodyCallback(body); + + if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) { - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", - body.ID, body, inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); + PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); + if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); + } - if (PhysicsScene.PE.IsInWorld(PhysicsScene.World, body)) - { - PhysicsScene.PE.RemoveObjectFromWorld(PhysicsScene.World, body); - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); - } - - // Zero any reference to the shape so it is not freed when the body is deleted. - PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); - PhysicsScene.PE.DestroyObject(PhysicsScene.World, body); - }); + // Zero any reference to the shape so it is not freed when the body is deleted. + PhysicsScene.PE.SetCollisionShape(PhysicsScene.World, body, null); + PhysicsScene.PE.DestroyObject(PhysicsScene.World, body); } } @@ -246,44 +241,43 @@ public sealed class BSShapeCollection : IDisposable } // Release the usage of a shape. - public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) + public void DereferenceShape(BulletShape shape, ShapeDestructionCallback shapeCallback) { if (!shape.HasPhysicalShape) return; - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() + PhysicsScene.AssertInTaintTime("BSShapeCollection.DereferenceShape"); + + if (shape.HasPhysicalShape) { - if (shape.HasPhysicalShape) + if (shape.isNativeShape) { - if (shape.isNativeShape) + // Native shapes are not tracked and are released immediately + if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1}", + BSScene.DetailLogZero, shape.AddrString); + if (shapeCallback != null) shapeCallback(shape); + PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); + } + else + { + switch (shape.type) { - // Native shapes are not tracked and are released immediately - if (DDetail) DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.AddrString, inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - PhysicsScene.PE.DeleteCollisionShape(PhysicsScene.World, shape); - } - else - { - switch (shape.type) - { - case BSPhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_COMPOUND: - DereferenceCompound(shape, shapeCallback); - break; - case BSPhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - break; - } + case BSPhysicsShapeType.SHAPE_HULL: + DereferenceHull(shape, shapeCallback); + break; + case BSPhysicsShapeType.SHAPE_MESH: + DereferenceMesh(shape, shapeCallback); + break; + case BSPhysicsShapeType.SHAPE_COMPOUND: + DereferenceCompound(shape, shapeCallback); + break; + case BSPhysicsShapeType.SHAPE_UNKNOWN: + break; + default: + break; } } - }); + } } // Count down the reference count for a mesh shape @@ -394,7 +388,7 @@ public sealed class BSShapeCollection : IDisposable if (shapeInfo.type != BSPhysicsShapeType.SHAPE_UNKNOWN) { - DereferenceShape(shapeInfo, true, null); + DereferenceShape(shapeInfo, null); } else { @@ -544,7 +538,7 @@ public sealed class BSShapeCollection : IDisposable ShapeDestructionCallback shapeCallback) { // release any previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, shapeCallback); BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); @@ -612,7 +606,7 @@ public sealed class BSShapeCollection : IDisposable prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, shapeCallback); newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); // Take evasive action if the mesh was not constructed. @@ -683,7 +677,7 @@ public sealed class BSShapeCollection : IDisposable prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); // Remove usage of the previous shape. - DereferenceShape(prim.PhysShape, true, shapeCallback); + DereferenceShape(prim.PhysShape, shapeCallback); newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); newShape = VerifyMeshCreated(newShape, prim); @@ -818,7 +812,6 @@ public sealed class BSShapeCollection : IDisposable // Don't need to do this as the shape is freed when the new root shape is created below. // DereferenceShape(prim.PhysShape, true, shapeCallback); - BulletShape cShape = PhysicsScene.PE.CreateCompoundShape(PhysicsScene.World, false); // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. @@ -933,8 +926,7 @@ public sealed class BSShapeCollection : IDisposable // Updates prim.BSBody with the information about the new body if one is created. // Returns 'true' if an object was actually created. // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BulletShape shape, - BodyDestructionCallback bodyCallback) + private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletWorld sim, BodyDestructionCallback bodyCallback) { bool ret = false; @@ -951,27 +943,28 @@ public sealed class BSShapeCollection : IDisposable { // If the collisionObject is not the correct type for solidness, rebuild what's there mustRebuild = true; + if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,forceRebuildBecauseChangingBodyType,bodyType={1}", prim.LocalID, bodyType); } } if (mustRebuild || forceRebuild) { // Free any old body - DereferenceBody(prim.PhysBody, true, bodyCallback); + DereferenceBody(prim.PhysBody, bodyCallback); BulletBody aBody; if (prim.IsSolid) { - aBody = PhysicsScene.PE.CreateBodyFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation); + aBody = PhysicsScene.PE.CreateBodyFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,mesh,body={1}", prim.LocalID, aBody); } else { - aBody = PhysicsScene.PE.CreateGhostFromShape(sim, shape, prim.LocalID, prim.RawPosition, prim.RawOrientation); + aBody = PhysicsScene.PE.CreateGhostFromShape(sim, prim.PhysShape, prim.LocalID, prim.RawPosition, prim.RawOrientation); if (DDetail) DetailLog("{0},BSShapeCollection.CreateBody,ghost,body={1}", prim.LocalID, aBody); } - ReferenceBody(aBody, true); + ReferenceBody(aBody); prim.PhysBody = aBody; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt index a95e169742..a3b355656d 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimTODO.txt @@ -6,6 +6,7 @@ One sided meshes? Should terrain be built into a closed shape? Ref: http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4869 Deleting a linkset while standing on the root will leave the physical shape of the root behind. Not sure if it is because standing on it. Done with large prim linksets. +Terrain detail: double terrain mesh detail Vehicle angular vertical attraction vehicle angular banking Center-of-gravity @@ -34,34 +35,20 @@ Vehicle script tuning/debugging Weapon shooter script Add material densities to the material types -CRASHES -================================================= -Crazyness during 20130115 office hours was PositionAdjustUnderground for both char and prim - m1:logs/20130115.0934/physics-BulletSim-20130115083613.log - Creation of Neb's terrain made the terrain "disappear". Everything started to fall - and then get restored to be above terrain. -20121129.1411: editting/moving phys object across region boundries causes crash - getPos-> btRigidBody::upcast -> getBodyType -> BOOM -20121128.1600: mesh object not rezzing (no physics mesh). - Causes many errors. Doesn't stop after first error with box shape. - Eventually crashes when deleting the object. -20121206.1434: rez Sam-pan into OSGrid BulletSim11 region - Immediate simulator crash. Mono does not output any stacktrace and - log just stops after reporting taint-time linking of the linkset. - VEHICLES TODO LIST: ================================================= Border crossing with linked vehicle causes crash + 20121129.1411: editting/moving phys object across region boundries causes crash + getPos-> btRigidBody::upcast -> getBodyType -> BOOM Vehicles (Move smoothly) Some vehicles should not be able to turn if no speed or off ground. +What to do if vehicle and prim buoyancy differ? Cannot edit/move a vehicle being ridden: it jumps back to the origional position. Neb car jiggling left and right Happens on terrain and any other mesh object. Flat cubes are much smoother. This has been reduced but not eliminated. Implement referenceFrame for all the motion routines. For limitMotorUp, use raycast down to find if vehicle is in the air. -Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. - Verify that angular motion specified around Z moves in the vehicle coordinates. Verify llGetVel() is returning a smooth and good value for vehicle movement. llGetVel() should return the root's velocity if requested in a child prim. Implement function efficiency for lineaar and angular motion. @@ -73,10 +60,15 @@ Remove vehicle angular velocity zeroing in BSPrim.UpdateProperties(). Incorporate inter-relationship of angular corrections. For instance, angularDeflection and angularMotorUp will compute same X or Y correction. When added together creates over-correction and over-shoot and wabbling. +Vehicle attributes are not restored when a vehicle is rezzed on region creation + Create vehicle, setup vehicle properties, restart region, vehicle is not reinitialized. GENERAL TODO LIST: ================================================= -Avatar standing on a moving object should start to move with the object. +Collisions are inconsistant: arrows are supposed to hit and report collision. Often don't. + If arrow show at prim, collision reported about 1/3 of time. If collision reported, + both arrow and prim report it. The arrow bounces off the prim 9 out of 10 times. + Shooting 5m sphere "arrows" at 60m/s. llMoveToTarget objects are not effected by gravity until target is removed. Compute CCD parameters based on body size Can solver iterations be changed per body/shape? Can be for constraints but what @@ -135,6 +127,7 @@ Physical and phantom will drop through the terrain LINKSETS ====================================================== +Child prims do not report collisions Editing a child of a linkset causes the child to go phantom Move a child prim once when it is physical and can never move it again without it going phantom Offset the center of the linkset to be the geometric center of all the prims @@ -330,4 +323,8 @@ Boats float low in the water (DONE) Boats floating at proper level (DONE) When is force introduced by SetForce removed? The prestep action could go forever. (DONE) (Resolution: setForce registers a prestep action which keeps applying the force) -Child movement in linkset (don't rebuild linkset) (DONE 20130122)) \ No newline at end of file +Child movement in linkset (don't rebuild linkset) (DONE 20130122)) +Avatar standing on a moving object should start to move with the object. (DONE 20130125) +Angular motion around Z moves the vehicle in world Z and not vehicle Z in ODE. + Verify that angular motion specified around Z moves in the vehicle coordinates. + DONE 20130120: BulletSim properly applies force in vehicle relative coordinates. \ No newline at end of file diff --git a/OpenSim/Region/Physics/Manager/PhysicsScene.cs b/OpenSim/Region/Physics/Manager/PhysicsScene.cs index fe418d33a1..20a70b41e5 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsScene.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsScene.cs @@ -47,7 +47,7 @@ namespace OpenSim.Region.Physics.Manager public delegate void JointDeactivated(PhysicsJoint joint); public delegate void JointErrorMessage(PhysicsJoint joint, string message); // this refers to an "error message due to a problem", not "amount of joint constraint violation" - public enum RayFilterFlags:ushort + public enum RayFilterFlags : ushort { // the flags water = 0x01, @@ -64,7 +64,7 @@ namespace OpenSim.Region.Physics.Manager ClosestHit = 0x8000, // some combinations - LSLPhanton = phantom | volumedtc, + LSLPhantom = phantom | volumedtc, PrimsNonPhantom = nonphysical | physical, PrimsNonPhantomAgents = nonphysical | physical | agent, diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 38a9cb004a..f4a812ccd6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -12342,7 +12342,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (checkNonPhysical) rayfilter |= RayFilterFlags.nonphysical; if (detectPhantom) - rayfilter |= RayFilterFlags.LSLPhanton; + rayfilter |= RayFilterFlags.LSLPhantom; Vector3 direction = dir * ( 1/dist); diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 26eb8edf39..7e7b23179c 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -265,9 +265,10 @@ ; DefaultScriptEngine = "XEngine" ;# {GenerateMaptiles} {} {Generate map tiles?} {true false} true - ;; Map tile options. You can choose to generate no map tiles at all, - ;; generate normal maptiles, or nominate an uploaded texture to - ;; be the map tile + ;; Map tile options. You can choose to generate normal maptiles or nominate an uploaded texture to + ;; be the map tile using the MaptileStaticUUID parameter in this section or for individual regions in + ;; the regions config file(s). If you do not want to upload map tiles at all, then you will need + ;; to disable the MapImageServiceModule entirely. ; GenerateMaptiles = true ;# {MaptileRefresh} {GenerateMaptiles} {Maptile refresh period?} {} 0 diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index fa88146f13..2edc1f800f 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -1,7 +1,6 @@ ; This file contains defaults for various settings in OpenSimulator. These can be overriden ; by changing the same setting in OpenSim.ini (once OpenSim.ini.example has been copied to OpenSim.ini). - [Startup] ; Console prompt ; Certain special characters can be used to customize the prompt