diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index e7fb9dfa4f..518f2ea9f9 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -33,7 +33,7 @@ namespace OpenSim private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour - { + { Unknown, Dev, RC1, diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index 773baf541b..552f64c978 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -5255,7 +5255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP args.Channel = ch; args.From = String.Empty; args.Message = Utils.BytesToString(msg); - args.Type = ChatTypeEnum.Shout; + args.Type = ChatTypeEnum.Region; //Behaviour in SL is that the response can be heard from any distance args.Position = new Vector3(); args.Scene = Scene; args.Sender = this; @@ -11277,9 +11277,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_groupPowers.Clear(); - for (int i = 0; i < GroupMembership.Length; i++) + if (GroupMembership != null) { - m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + for (int i = 0; i < GroupMembership.Length; i++) + { + m_groupPowers[GroupMembership[i].GroupID] = GroupMembership[i].GroupPowers; + } } } } diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 37cdaae2bd..9eaa758bd5 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -406,6 +406,11 @@ namespace Flotsam.RegionModules.AssetCache return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public void Expire(string id) { if (m_LogLevel >= 2) diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs new file mode 100644 index 0000000000..3b6685938d --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -0,0 +1,229 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps +{ + #region Stream Handler + + public delegate byte[] StreamHandlerCallback(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse); + + public class StreamHandler : BaseStreamHandler + { + StreamHandlerCallback m_callback; + + public StreamHandler(string httpMethod, string path, StreamHandlerCallback callback) + : base(httpMethod, path) + { + m_callback = callback; + } + + public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + return m_callback(path, request, httpRequest, httpResponse); + } + } + + #endregion Stream Handler + + public class GetTextureModule : IRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private Scene m_scene; + private IAssetService m_assetService; + + #region IRegionModule Members + + public void Initialise(Scene pScene, IConfigSource pSource) + { + m_scene = pScene; + } + + public void PostInitialise() + { + m_assetService = m_scene.RequestModuleInterface(); + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void Close() { } + + public string Name { get { return "GetTextureModule"; } } + public bool IsSharedModule { get { return false; } } + + public void RegisterCaps(UUID agentID, Caps caps) + { + UUID capID = UUID.Random(); + + m_log.Info("[GETTEXTURE]: /CAPS/" + capID); + caps.RegisterHandler("GetTexture", new StreamHandler("GET", "/CAPS/" + capID, ProcessGetTexture)); + } + + #endregion + + private byte[] ProcessGetTexture(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) + { + // TODO: Change this to a config option + const string REDIRECT_URL = null; + + // Try to parse the texture ID from the request URL + NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); + string textureStr = GetOne(query, "texture_id"); + + if (m_assetService == null) + { + m_log.Error("[GETTEXTURE]: Cannot fetch texture " + textureStr + " without an asset service"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return null; + } + + UUID textureID; + if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) + { + AssetBase texture; + + if (!String.IsNullOrEmpty(REDIRECT_URL)) + { + // Only try to fetch locally cached textures. Misses are redirected + texture = m_assetService.GetCached(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + string textureUrl = REDIRECT_URL + textureID.ToString(); + m_log.Debug("[GETTEXTURE]: Redirecting texture request to " + textureUrl); + httpResponse.RedirectLocation = textureUrl; + } + } + else + { + // Fetch locally or remotely. Misses return a 404 + texture = m_assetService.Get(textureID.ToString()); + + if (texture != null) + { + SendTexture(httpRequest, httpResponse, texture); + } + else + { + m_log.Warn("[GETTEXTURE]: Texture " + textureID + " not found"); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + } + } + } + else + { + m_log.Warn("[GETTEXTURE]: Failed to parse a texture_id from GetTexture request: " + httpRequest.Url); + } + + httpResponse.Send(); + return null; + } + + private void SendTexture(OSHttpRequest request, OSHttpResponse response, AssetBase texture) + { + string range = GetOne(request.Headers, "Range"); + if (!String.IsNullOrEmpty(range)) + { + // Range request + int start, end; + if (TryParseRange(range, out start, out end)) + { + end = Utils.Clamp(end, 1, texture.Data.Length); + start = Utils.Clamp(start, 0, end - 1); + + m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); + + if (end - start < texture.Data.Length) + response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; + + response.ContentLength = end - start; + response.ContentType = texture.Metadata.ContentType; + + response.Body.Write(texture.Data, start, end - start); + } + else + { + m_log.Warn("Malformed Range header: " + range); + response.StatusCode = (int)System.Net.HttpStatusCode.BadRequest; + } + } + else + { + // Full content request + response.ContentLength = texture.Data.Length; + response.ContentType = texture.Metadata.ContentType; + response.Body.Write(texture.Data, 0, texture.Data.Length); + } + } + + private bool TryParseRange(string header, out int start, out int end) + { + if (header.StartsWith("bytes=")) + { + string[] rangeValues = header.Substring(6).Split('-'); + if (rangeValues.Length == 2) + { + if (Int32.TryParse(rangeValues[0], out start) && Int32.TryParse(rangeValues[1], out end)) + return true; + } + } + + start = end = 0; + return false; + } + + private static string GetOne(NameValueCollection collection, string key) + { + string[] values = collection.GetValues(key); + if (values != null && values.Length > 0) + return values[0]; + + return null; + } + } +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index af2f3d6558..ebd6bbdcfa 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -229,6 +229,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 50348da728..1b3419d12f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -165,6 +165,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { AssetBase asset = null; diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index f58904f8c8..16ca3f9e21 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -73,8 +73,6 @@ namespace OpenSim.Region.Framework.Interfaces /// void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource); - ArrayList GetScriptErrors(UUID itemID); - /// /// Stop all the scripts in this entity. /// @@ -104,6 +102,8 @@ namespace OpenSim.Region.Framework.Interfaces /// void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); + ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource); + /// /// Stop a script which is in this prim's inventory. /// diff --git a/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs new file mode 100644 index 0000000000..6fd6ba7224 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/ISnmpModule.cs @@ -0,0 +1,12 @@ +/////////////////////////////////////////////////////////////////// +// +// (c) Careminster LImited, Melanie Thielker and the Meta7 Team +// +// This file is not open source. All rights reserved +// Mod 2 +public interface ISnmpModule +{ + void Alert(string message); + void Trap(int code,string simname,string Message); + void ColdStart(int step , string simname); +} diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 1875c48da5..357cdc49f6 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -212,8 +212,7 @@ namespace OpenSim.Region.Framework.Scenes { // Needs to determine which engine was running it and use that // - part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); - errors = part.Inventory.GetScriptErrors(item.ItemID); + errors = part.Inventory.CreateScriptInstanceEr(item.ItemID, 0, false, DefaultScriptEngine, 0); } else { diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index e4daa0bc74..671f8fceee 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -156,6 +156,20 @@ namespace OpenSim.Region.Framework.Scenes public IXfer XferManager; + protected ISnmpModule m_snmpService = null; + public ISnmpModule SnmpService + { + get + { + if (m_snmpService == null) + { + m_snmpService = RequestModuleInterface(); + } + + return m_snmpService; + } + } + protected IAssetService m_AssetService; protected IAuthorizationService m_AuthorizationService; @@ -1727,7 +1741,7 @@ namespace OpenSim.Region.Framework.Scenes public void SaveTerrain() { m_storageManager.DataStore.StoreTerrain(Heightmap.GetDoubles(), RegionInfo.RegionID); - } + } public void StoreWindlightProfile(RegionLightShareData wl) { diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 014b007647..84c371990c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -104,8 +104,12 @@ namespace OpenSim.Region.Framework.Scenes /// since the group's last persistent backup /// private bool m_hasGroupChanged = false; - private long timeFirstChanged; - private long timeLastChanged; + private long timeFirstChanged = 0; + private long timeLastChanged = 0; + private long m_maxPersistTime = 0; + private long m_minPersistTime = 0; + private Random m_rand; + private System.Threading.ReaderWriterLockSlim m_partsLock = new System.Threading.ReaderWriterLockSlim(); public void lockPartsForRead(bool locked) @@ -182,6 +186,32 @@ namespace OpenSim.Region.Framework.Scenes timeLastChanged = DateTime.Now.Ticks; if (!m_hasGroupChanged) timeFirstChanged = DateTime.Now.Ticks; + if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null) + { + if (m_rand == null) + { + byte[] val = new byte[16]; + m_rootPart.UUID.ToBytes(val, 0); + m_rand = new Random(BitConverter.ToInt32(val, 0)); + } + + if (m_scene.GetRootAgentCount() == 0) + { + //If the region is empty, this change has been made by an automated process + //and thus we delay the persist time by a random amount between 1.5 and 2.5. + + float factor = 1.5f + (float)(m_rand.NextDouble()); + m_maxPersistTime = (long)((float)m_scene.m_persistAfter * factor); + m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * factor); + } + else + { + //If the region is not empty, we want to obey the minimum and maximum persist times + //but add a random factor so we stagger the object persistance a little + m_maxPersistTime = (long)((float)m_scene.m_persistAfter * (1.0d - (m_rand.NextDouble() / 5.0d))); //Multiply by 1.0-1.5 + m_minPersistTime = (long)((float)m_scene.m_dontPersistBefore * (1.0d + (m_rand.NextDouble() / 2.0d))); //Multiply by 0.8-1.0 + } + } } m_hasGroupChanged = value; } @@ -197,8 +227,19 @@ namespace OpenSim.Region.Framework.Scenes return false; if (m_scene.ShuttingDown) return true; + + if (m_minPersistTime == 0 || m_maxPersistTime == 0) + { + m_maxPersistTime = m_scene.m_persistAfter; + m_minPersistTime = m_scene.m_dontPersistBefore; + } + long currentTime = DateTime.Now.Ticks; - if (currentTime - timeLastChanged > m_scene.m_dontPersistBefore || currentTime - timeFirstChanged > m_scene.m_persistAfter) + + if (timeLastChanged == 0) timeLastChanged = currentTime; + if (timeFirstChanged == 0) timeFirstChanged = currentTime; + + if (currentTime - timeLastChanged > m_minPersistTime || currentTime - timeFirstChanged > m_maxPersistTime) return true; return false; } @@ -530,6 +571,7 @@ namespace OpenSim.Region.Framework.Scenes /// public SceneObjectGroup() { + } /// @@ -546,7 +588,7 @@ namespace OpenSim.Region.Framework.Scenes /// Constructor. This object is added to the scene later via AttachToScene() /// public SceneObjectGroup(UUID ownerID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) - { + { SetRootPart(new SceneObjectPart(ownerID, shape, pos, rot, Vector3.Zero)); } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 836622d9b3..07d58a1c30 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -45,6 +45,8 @@ namespace OpenSim.Region.Framework.Scenes private string m_inventoryFileName = String.Empty; private int m_inventoryFileNameSerial = 0; + + private Dictionary m_scriptErrors = new Dictionary(); /// /// The part to which the inventory belongs. @@ -210,7 +212,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public ArrayList GetScriptErrors(UUID itemID) + private ArrayList GetScriptErrors(UUID itemID) { ArrayList ret = new ArrayList(); @@ -269,7 +271,10 @@ namespace OpenSim.Region.Framework.Scenes // item.Name, item.ItemID, Name, UUID); if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) + { + StoreScriptError(item.ItemID, "no permission"); return; + } m_part.AddFlag(PrimFlags.Scripted); @@ -284,6 +289,7 @@ namespace OpenSim.Region.Framework.Scenes m_items.LockItemsForWrite(false); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, String.Empty, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID)); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); return; @@ -293,11 +299,13 @@ namespace OpenSim.Region.Framework.Scenes { if (null == asset) { + string msg = String.Format("asset ID {0} could not be found", item.AssetID); + StoreScriptError(item.ItemID, msg); m_log.ErrorFormat( "[PRIM INVENTORY]: " + - "Couldn't start script {0}, {1} at {2} in {3} since asset ID {4} could not be found", + "Couldn't start script {0}, {1} at {2} in {3} since {4}", item.Name, item.ItemID, m_part.AbsolutePosition, - m_part.ParentGroup.Scene.RegionInfo.RegionName, item.AssetID); + m_part.ParentGroup.Scene.RegionInfo.RegionName, msg); } else { @@ -310,11 +318,16 @@ namespace OpenSim.Region.Framework.Scenes string script = Utils.BytesToString(asset.Data); m_part.ParentGroup.Scene.EventManager.TriggerRezScript( m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); + StoreScriptErrors(item.ItemID, GetScriptErrors(item.ItemID)); m_part.ParentGroup.AddActiveScriptCount(1); m_part.ScheduleFullUpdate(); } }); } + else + { + StoreScriptError(item.ItemID, "scripts disabled"); + } } private void RestoreSavedScriptState(UUID oldID, UUID newID) @@ -391,24 +404,71 @@ namespace OpenSim.Region.Framework.Scenes else { m_items.LockItemsForRead(false); + string msg = String.Format("couldn't be found for prim {0}, {1} at {2} in {3}", m_part.Name, m_part.UUID, + m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); + StoreScriptError(itemId, msg); m_log.ErrorFormat( "[PRIM INVENTORY]: " + - "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2} at {3} in {4}", - itemId, m_part.Name, m_part.UUID, - m_part.AbsolutePosition, m_part.ParentGroup.Scene.RegionInfo.RegionName); + "Couldn't start script with ID {0} since it {1}", itemId, msg); } } else { m_items.LockItemsForRead(false); + string msg = String.Format("couldn't be found for prim {0}, {1}", m_part.Name, m_part.UUID); + StoreScriptError(itemId, msg); m_log.ErrorFormat( "[PRIM INVENTORY]: " + - "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", - itemId, m_part.Name, m_part.UUID); + "Couldn't start script with ID {0} since it {1}", itemId, msg); } } + public ArrayList CreateScriptInstanceEr(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) + { + ArrayList errors; + + lock (m_scriptErrors) + { + m_scriptErrors.Remove(itemId); + } + CreateScriptInstance(itemId, startParam, postOnRez, engine, stateSource); + lock (m_scriptErrors) + { + while (!m_scriptErrors.TryGetValue(itemId, out errors)) + { + if (!System.Threading.Monitor.Wait(m_scriptErrors, 15000)) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "timedout waiting for script {0} errors", itemId); + if (!m_scriptErrors.TryGetValue(itemId, out errors)) + { + errors = new ArrayList(1); + errors.Add("timedout waiting for errors"); + } + break; + } + } + m_scriptErrors.Remove(itemId); + } + return errors; + } + private void StoreScriptErrors(UUID itemId, ArrayList errors) + { + lock (m_scriptErrors) + { + m_scriptErrors[itemId] = errors; + System.Threading.Monitor.PulseAll(m_scriptErrors); + } + } + private void StoreScriptError(UUID itemId, string message) + { + ArrayList errors = new ArrayList(1); + errors.Add(message); + StoreScriptErrors(itemId, errors); + } + /// /// Stop a script which is in this prim's inventory. /// diff --git a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs index e8894f701a..01c3f81a5d 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/ODEPrim.cs @@ -180,6 +180,7 @@ namespace OpenSim.Region.Physics.OdePlugin internal int m_material = (int)Material.Wood; private int frcount = 0; // Used to limit dynamics debug output to + private int revcount = 0; // Reverse motion while > 0 private IntPtr m_body = IntPtr.Zero; @@ -1888,22 +1889,19 @@ namespace OpenSim.Region.Physics.OdePlugin public void changemove(float timestep) { -//Console.WriteLine("changemove for {0}", m_primName ); - +//Console.WriteLine("changemove sing/root {0} to {1}", m_primName, _position ); if (m_isphysical) { //Console.WriteLine("phys {0} {1} {2}", m_disabled, m_taintremove, childPrim); // if (!m_disabled && !m_taintremove && !childPrim) After one edit m_disabled is sometimes set, disabling further edits! if (!m_taintremove && !childPrim) { -//Console.WriteLine("physOK"); if (Body == IntPtr.Zero) enableBody(); //Prim auto disable after 20 frames, //if you move it, re-enable the prim manually. if (_parent != null) { -//Console.WriteLine("physChild"); if (m_linkJoint != IntPtr.Zero) { d.JointDestroy(m_linkJoint); @@ -1912,7 +1910,6 @@ namespace OpenSim.Region.Physics.OdePlugin } if (Body != IntPtr.Zero) { -//Console.WriteLine("physNotIPZ"); d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); if (_parent != null) @@ -1945,7 +1942,6 @@ Console.WriteLine(" JointCreateFixed"); } else { -//Console.WriteLine("NONphys"); // string primScenAvatarIn = _parent_scene.whichspaceamIin(_position); // int[] arrayitem = _parent_scene.calculateSpaceArrayItemFromPos(_position); _parent_scene.waitForSpaceUnlock(m_targetSpace); @@ -2382,9 +2378,7 @@ Console.WriteLine(" JointCreateFixed"); if (IsPhysical) { if (Body != IntPtr.Zero) - { d.BodySetLinearVel(Body, m_taintVelocity.X, m_taintVelocity.Y, m_taintVelocity.Z); - } } //resetCollisionAccounting(); @@ -2394,31 +2388,9 @@ Console.WriteLine(" JointCreateFixed"); public void UpdatePositionAndVelocity() { - return; // moved to the Move() method + return; // moved to the Move () method } -/* No one uses this? - public Matrix4 FromDMass(d.Mass pMass) - { - Matrix4 obj; - obj.M11 = pMass.I.M00; - obj.M12 = pMass.I.M01; - obj.M13 = pMass.I.M02; - obj.M14 = 0; - obj.M21 = pMass.I.M10; - obj.M22 = pMass.I.M11; - obj.M23 = pMass.I.M12; - obj.M24 = 0; - obj.M31 = pMass.I.M20; - obj.M32 = pMass.I.M21; - obj.M33 = pMass.I.M22; - obj.M34 = 0; - obj.M41 = 0; - obj.M42 = 0; - obj.M43 = 0; - obj.M44 = 1; - return obj; - } -*/ + public d.Mass FromMatrix4(Matrix4 pMat, ref d.Mass obj) { obj.I.M00 = pMat[0, 0]; @@ -2654,15 +2626,15 @@ Console.WriteLine(" JointCreateFixed"); // m_angularDeflectionEfficiency = pValue; break; case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; // m_angularDeflectionTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.3f) pValue = 0.3f; m_angularMotorDecayTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.3f) pValue = 0.3f; m_angularMotorTimescale = pValue; break; case Vehicle.BANKING_EFFICIENCY: @@ -2691,7 +2663,7 @@ Console.WriteLine(" JointCreateFixed"); m_VhoverHeight = pValue; break; case Vehicle.HOVER_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; m_VhoverTimescale = pValue; break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: @@ -2703,11 +2675,11 @@ Console.WriteLine(" JointCreateFixed"); // m_linearDeflectionTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.3f) pValue = 0.3f; m_linearMotorDecayTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; m_linearMotorTimescale = pValue; break; case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: @@ -2716,7 +2688,7 @@ Console.WriteLine(" JointCreateFixed"); m_verticalAttractionEfficiency = pValue; break; case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - if (pValue < 0.01f) pValue = 0.01f; + if (pValue < 0.1f) pValue = 0.1f; m_verticalAttractionTimescale = pValue; break; @@ -2732,6 +2704,7 @@ Console.WriteLine(" JointCreateFixed"); UpdateAngDecay(); break; case Vehicle.LINEAR_FRICTION_TIMESCALE: + if (pValue < 0.1f) pValue = 0.1f; m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); break; case Vehicle.LINEAR_MOTOR_DIRECTION: @@ -2771,6 +2744,9 @@ Console.WriteLine(" JointCreateFixed"); UpdateAngDecay(); break; case Vehicle.LINEAR_FRICTION_TIMESCALE: + if (pValue.X < 0.1f) pValue.X = 0.1f; + if (pValue.Y < 0.1f) pValue.Y = 0.1f; + if (pValue.Z < 0.1f) pValue.Z = 0.1f; m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_DIRECTION: @@ -2967,7 +2943,7 @@ Console.WriteLine(" JointCreateFixed"); internal void Halt() { // Kill all motions, when non-physical - m_linearMotorDirection = Vector3.Zero; + // m_linearMotorDirection = Vector3.Zero; m_lLinMotorDVel = Vector3.Zero; m_lLinObjectVel = Vector3.Zero; m_wLinObjectVel = Vector3.Zero; @@ -2979,16 +2955,22 @@ Console.WriteLine(" JointCreateFixed"); private void UpdateLinDecay() { - if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X; - if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y; - if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z; +// if (Math.Abs(m_linearMotorDirection.X) > Math.Abs(m_lLinMotorDVel.X)) m_lLinMotorDVel.X = m_linearMotorDirection.X; +// if (Math.Abs(m_linearMotorDirection.Y) > Math.Abs(m_lLinMotorDVel.Y)) m_lLinMotorDVel.Y = m_linearMotorDirection.Y; +// if (Math.Abs(m_linearMotorDirection.Z) > Math.Abs(m_lLinMotorDVel.Z)) m_lLinMotorDVel.Z = m_linearMotorDirection.Z; + m_lLinMotorDVel.X = m_linearMotorDirection.X; + m_lLinMotorDVel.Y = m_linearMotorDirection.Y; + m_lLinMotorDVel.Z = m_linearMotorDirection.Z; } // else let the motor decay on its own private void UpdateAngDecay() { - if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X; - if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y; - if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z; +// if (Math.Abs(m_angularMotorDirection.X) > Math.Abs(m_angularMotorDVel.X)) m_angularMotorDVel.X = m_angularMotorDirection.X; +// if (Math.Abs(m_angularMotorDirection.Y) > Math.Abs(m_angularMotorDVel.Y)) m_angularMotorDVel.Y = m_angularMotorDirection.Y; +// if (Math.Abs(m_angularMotorDirection.Z) > Math.Abs(m_angularMotorDVel.Z)) m_angularMotorDVel.Z = m_angularMotorDirection.Z; + m_angularMotorDVel.X = m_angularMotorDirection.X; + m_angularMotorDVel.Y = m_angularMotorDirection.Y; + m_angularMotorDVel.Z = m_angularMotorDirection.Z; } // else let the motor decay on its own public void Move(float timestep) @@ -2996,44 +2978,114 @@ Console.WriteLine(" JointCreateFixed"); float fx = 0; float fy = 0; float fz = 0; + Vector3 linvel; // velocity applied, including any reversal + int outside = 0; + + // If geomCrossingFailuresBeforeOutofbounds is set to 0 in OpenSim.ini then phys objects bounce off region borders. + // This is a temp patch until proper region crossing is developed. + + int failureLimit = _parent_scene.geomCrossingFailuresBeforeOutofbounds; + int fence = _parent_scene.geomRegionFence; + + float border_limit = 0.05f; // original limit + if (fence == 1) border_limit = 0.5f; // bounce point frcount++; // used to limit debug comment output - if (frcount > 100) + if (frcount > 10) frcount = 0; - if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // KF: Only move root prims. + if(revcount > 0) revcount--; + + if (IsPhysical && (Body != IntPtr.Zero) && !m_isSelected && !childPrim) // Only move root prims. { - -// Old public void UpdatePositionAndVelocity(), more accuratley calculated here + // Old public void UpdatePositionAndVelocity(), more accuratley calculated here bool lastZeroFlag = _zeroFlag; // was it stopped + d.Vector3 vec = d.BodyGetPosition(Body); - d.Quaternion ori = d.BodyGetQuaternion(Body); - d.Vector3 vel = d.BodyGetLinearVel(Body); - // d.Vector3 rotvel = d.BodyGetAngularVel(Body); - d.Vector3 torque = d.BodyGetTorque(Body); - _torque = new Vector3(torque.X, torque.Y, torque.Z); Vector3 l_position = Vector3.Zero; - Quaternion l_orientation = Quaternion.Identity; - - m_lastposition = _position; - m_lastorientation = _orientation; - l_position.X = vec.X; l_position.Y = vec.Y; l_position.Z = vec.Z; - l_orientation.X = ori.X; - l_orientation.Y = ori.Y; - l_orientation.Z = ori.Z; - l_orientation.W = ori.W; + m_lastposition = _position; + _position = l_position; + + d.Quaternion ori = d.BodyGetQuaternion(Body); + // Quaternion l_orientation = Quaternion.Identity; + _orientation.X = ori.X; + _orientation.Y = ori.Y; + _orientation.Z = ori.Z; + _orientation.W = ori.W; + m_lastorientation = _orientation; + + d.Vector3 vel = d.BodyGetLinearVel(Body); + m_lastVelocity = _velocity; + _velocity.X = vel.X; + _velocity.Y = vel.Y; + _velocity.Z = vel.Z; + _acceleration = ((_velocity - m_lastVelocity) / timestep); + + d.Vector3 torque = d.BodyGetTorque(Body); + _torque = new Vector3(torque.X, torque.Y, torque.Z); + + base.RequestPhysicsterseUpdate(); + //Console.WriteLine("Move {0} at {1}", m_primName, l_position); - // Check if outside region horizontally - if (l_position.X > ((int)_parent_scene.WorldExtents.X - 0.05f) || - l_position.X < 0f || - l_position.Y > ((int)_parent_scene.WorldExtents.Y - 0.05f) || - l_position.Y < 0f) + // Check if outside region + // In Scene.cs/CrossPrimGroupIntoNewRegion the object is checked for 0.1M from border! + if (l_position.X > ((float)_parent_scene.WorldExtents.X - border_limit)) { - if (m_crossingfailures < _parent_scene.geomCrossingFailuresBeforeOutofbounds) + l_position.X = ((float)_parent_scene.WorldExtents.X - border_limit); + outside = 1; + } + + if (l_position.X < border_limit) + { + l_position.X = border_limit; + outside = 2; + } + if (l_position.Y > ((float)_parent_scene.WorldExtents.Y - border_limit)) + { + l_position.Y = ((float)_parent_scene.WorldExtents.Y - border_limit); + outside = 3; + } + + if (l_position.Y < border_limit) + { + l_position.Y = border_limit; + outside = 4; + } + + if (outside > 0) + { +//Console.WriteLine(" fence = {0}",fence); + +//Console.WriteLine("Border {0}", l_position); + if (fence == 1) // bounce object off boundary + { + if (revcount == 0) + { + if (outside < 3) + { + _velocity.X = -_velocity.X; + } + else + { + _velocity.Y = -_velocity.Y; + } + if (m_type != Vehicle.TYPE_NONE) Halt(); + _position = l_position; + m_taintposition = _position; + m_lastVelocity = _velocity; + _acceleration = Vector3.Zero; + d.BodySetPosition(Body, _position.X, _position.Y, _position.Z); + d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); + base.RequestPhysicsterseUpdate(); + + revcount = 25; // wait for object to move away from border + } + } // else old crossing mode + else if (m_crossingfailures < failureLimit) { // keep trying to cross? _position = l_position; //_parent_scene.remActivePrim(this); @@ -3043,9 +3095,12 @@ Console.WriteLine(" JointCreateFixed"); else { // Too many tries if (_parent == null) base.RaiseOutOfBounds(l_position); +//Console.WriteLine("ROOB 2"); + return; // Dont process any other motion? - } + } // end various methods } // end outside region horizontally + if (l_position.Z < 0) { @@ -3057,6 +3112,8 @@ Console.WriteLine(" JointCreateFixed"); //IsPhysical = false; if (_parent == null) base.RaiseOutOfBounds(_position); +//Console.WriteLine("ROOB 3"); + _acceleration.X = 0; // This stuff may stop client display but it has no _acceleration.Y = 0; // effect on the object in phys engine! @@ -3081,10 +3138,9 @@ Console.WriteLine(" JointCreateFixed"); if ((Math.Abs(m_lastposition.X - l_position.X) < 0.02) && (Math.Abs(m_lastposition.Y - l_position.Y) < 0.02) && (Math.Abs(m_lastposition.Z - l_position.Z) < 0.02) - && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, l_orientation)) < 0.0001)) // KF 0.01 is far to large + && (1.0 - Math.Abs(Quaternion.Dot(m_lastorientation, _orientation)) < 0.0001)) // KF 0.01 is far to large { _zeroFlag = true; -//Console.WriteLine("ZFT 2"); m_throttleUpdates = false; } else @@ -3104,10 +3160,7 @@ Console.WriteLine(" JointCreateFixed"); _acceleration.X = 0; _acceleration.Y = 0; _acceleration.Z = 0; - //_orientation.w = 0f; - //_orientation.X = 0f; - //_orientation.Y = 0f; - //_orientation.Z = 0f; + m_rotationalVelocity.X = 0; m_rotationalVelocity.Y = 0; m_rotationalVelocity.Z = 0; @@ -3132,26 +3185,6 @@ Console.WriteLine(" JointCreateFixed"); base.RequestPhysicsterseUpdate(); } } - - m_lastVelocity = _velocity; - - _position = l_position; - - _velocity.X = vel.X; - _velocity.Y = vel.Y; - _velocity.Z = vel.Z; -// Why 2 calcs??? -// _acceleration = ((_velocity - m_lastVelocity) / 0.1f); -// _acceleration = new Vector3(_velocity.X - m_lastVelocity.X / 0.1f, -// _velocity.Y - m_lastVelocity.Y / 0.1f, -// _velocity.Z - m_lastVelocity.Z / 0.1f); - - _acceleration = ((_velocity - m_lastVelocity) / timestep); - - _orientation.X = ori.X; - _orientation.Y = ori.Y; - _orientation.Z = ori.Z; - _orientation.W = ori.W; m_lastUpdateSent = false; if (!m_throttleUpdates || throttleCounter > _parent_scene.geomUpdatesPerThrottledUpdate) { @@ -3167,11 +3200,8 @@ Console.WriteLine(" JointCreateFixed"); } m_lastposition = l_position; - /// End of old UpdatePositionAndVelocity insert + /// End UpdatePositionAndVelocity insert -//if (!Acceleration.ApproxEquals(Vector3.Zero, 0.01f)) Console.WriteLine("Move " + m_primName + " Accel=" + Acceleration); -// if(frcount == 0) Console.WriteLine("Move " + m_primName + " VTyp " + m_type + -// " usePID=" + m_usePID + " seHover=" + m_useHoverPID + " useAPID=" + m_useAPID); if (m_type != Vehicle.TYPE_NONE) { // get body attitude @@ -3202,12 +3232,13 @@ Console.WriteLine(" JointCreateFixed"); { m_lLinMotorDVel = Vector3.Zero; } - else + + /* else { if (Math.Abs(m_lLinMotorDVel.X) < Math.Abs(m_lLinObjectVel.X)) m_lLinObjectVel.X = m_lLinMotorDVel.X; if (Math.Abs(m_lLinMotorDVel.Y) < Math.Abs(m_lLinObjectVel.Y)) m_lLinObjectVel.Y = m_lLinMotorDVel.Y; - if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z; - } + if (Math.Abs(m_lLinMotorDVel.Z) < Math.Abs(m_lLinObjectVel.Z)) m_lLinObjectVel.Z = m_lLinMotorDVel.Z; + } */ } // end linear motor decay if ( (! m_lLinMotorDVel.ApproxEquals(Vector3.Zero, 0.01f)) || (! m_lLinObjectVel.ApproxEquals(Vector3.Zero, 0.01f)) ) @@ -3235,7 +3266,6 @@ Console.WriteLine(" JointCreateFixed"); if (m_linearFrictionTimescale.Z < 300.0f) { float fricfactor = m_linearFrictionTimescale.Z / timestep; -//if(frcount == 0) Console.WriteLine("Zfric={0}", fricfactor); float fricZ = m_lLinObjectVel.Z / fricfactor; m_lLinObjectVel.Z -= fricZ; } @@ -3296,14 +3326,17 @@ Console.WriteLine(" JointCreateFixed"); } } else - { // not hovering, Gravity rules - m_wLinObjectVel.Z = vel_now.Z; + { // not hovering + if (m_wLinObjectVel.Z == 0f) + { // Gravity rules + m_wLinObjectVel.Z = vel_now.Z; + } // else the motor has it } - - + linvel = m_wLinObjectVel; + // Vehicle Linear Motion done ======================================= // Apply velocity - d.BodySetLinearVel(Body, m_wLinObjectVel.X, m_wLinObjectVel.Y, m_wLinObjectVel.Z); + d.BodySetLinearVel(Body, linvel.X, linvel.Y, linvel.Z); // apply gravity force d.BodyAddForce(Body, grav.X, grav.Y, grav.Z); //if(frcount == 0) Console.WriteLine("Grav {0}", grav); @@ -3626,9 +3659,10 @@ Console.WriteLine(" JointCreateFixed"); // react to the physics scene by moving it's position. // Avatar to Avatar collisions // Prim to avatar collisions + d.Vector3 dlinvel = vel; d.BodySetPosition(Body, pos.X, pos.Y, m_targetHoverHeight); - d.BodySetLinearVel(Body, vel.X, vel.Y, 0); + d.BodySetLinearVel(Body, dlinvel.X, dlinvel.Y, dlinvel.Z); d.BodyAddForce(Body, 0, 0, fz); //KF this prevents furthur motions return; } diff --git a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs index deb61641e2..79e2986231 100644 --- a/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/ChOdePlugin/OdePlugin.cs @@ -224,6 +224,7 @@ namespace OpenSim.Region.Physics.OdePlugin public float bodyPIDG = 25; public int geomCrossingFailuresBeforeOutofbounds = 5; + public int geomRegionFence = 0; public float bodyMotorJointMaxforceTensor = 2; @@ -447,6 +448,7 @@ namespace OpenSim.Region.Physics.OdePlugin geomContactPointsStartthrottle = physicsconfig.GetInt("geom_contactpoints_start_throttling", 3); geomUpdatesPerThrottledUpdate = physicsconfig.GetInt("geom_updates_before_throttled_update", 15); geomCrossingFailuresBeforeOutofbounds = physicsconfig.GetInt("geom_crossing_failures_before_outofbounds", 5); + geomRegionFence = physicsconfig.GetInt("region_border_fence", 0); geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", 10.000006836f); bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", 20); @@ -3419,76 +3421,56 @@ namespace OpenSim.Region.Physics.OdePlugin public void SetTerrain(float[] heightMap, Vector3 pOffset) { - // this._heightmap[i] = (double)heightMap[i]; - // dbm (danx0r) -- creating a buffer zone of one extra sample all around - //_origheightmap = heightMap; + uint regionsize = (uint) Constants.RegionSize; // visible region size eg. 256(M) + + uint heightmapWidth = regionsize + 1; // ODE map size 257 x 257 (Meters) (1 extra + uint heightmapHeight = regionsize + 1; + + uint heightmapWidthSamples = (uint)regionsize + 2; // Sample file size, 258 x 258 samples + uint heightmapHeightSamples = (uint)regionsize + 2; + + // Array of height samples for ODE float[] _heightmap; + _heightmap = new float[(heightmapWidthSamples * heightmapHeightSamples)]; // loaded samples 258 x 258 - // zero out a heightmap array float array (single dimension [flattened])) - //if ((int)Constants.RegionSize == 256) - // _heightmap = new float[514 * 514]; - //else - - _heightmap = new float[(((int)Constants.RegionSize + 2) * ((int)Constants.RegionSize + 2))]; - - uint heightmapWidth = Constants.RegionSize + 1; - uint heightmapHeight = Constants.RegionSize + 1; - - uint heightmapWidthSamples; - - uint heightmapHeightSamples; - - //if (((int)Constants.RegionSize) == 256) - //{ - // heightmapWidthSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapHeightSamples = 2 * (uint)Constants.RegionSize + 2; - // heightmapWidth++; - // heightmapHeight++; - //} - //else - //{ - - heightmapWidthSamples = (uint)Constants.RegionSize + 1; - heightmapHeightSamples = (uint)Constants.RegionSize + 1; - //} - + // Other ODE parameters const float scale = 1.0f; const float offset = 0.0f; - const float thickness = 0.2f; + const float thickness = 2.0f; // Was 0.2f, Larger appears to prevent Av fall-through const int wrap = 0; - int regionsize = (int) Constants.RegionSize + 2; - //Double resolution - //if (((int)Constants.RegionSize) == 256) - // heightMap = ResizeTerrain512Interpolation(heightMap); - - - // if (((int)Constants.RegionSize) == 256 && (int)Constants.RegionSize == 256) - // regionsize = 512; - - float hfmin = 2000; - float hfmax = -2000; + float hfmin = 2000f; + float hfmax = -2000f; + float minele = 0.0f; // Dont allow -ve heights - for (int x = 0; x < heightmapWidthSamples; x++) + uint x = 0; + uint y = 0; + uint xx = 0; + uint yy = 0; + + // load the height samples array from the heightMap + for ( x = 0; x < heightmapWidthSamples; x++) // 0 to 257 + { + for ( y = 0; y < heightmapHeightSamples; y++) // 0 to 257 { - for (int y = 0; y < heightmapHeightSamples; y++) - { - int xx = Util.Clip(x - 1, 0, regionsize - 1); - int yy = Util.Clip(y - 1, 0, regionsize - 1); - - - float val= heightMap[yy * (int)Constants.RegionSize + xx]; - _heightmap[x * ((int)Constants.RegionSize + 2) + y] = val; - - hfmin = (val < hfmin) ? val : hfmin; - hfmax = (val > hfmax) ? val : hfmax; - } + xx = x - 1; + if (xx < 0) xx = 0; + if (xx > (regionsize - 1)) xx = regionsize - 1; + + yy = y - 1; + if (yy < 0) yy = 0; + if (yy > (regionsize - 1)) yy = regionsize - 1; + // Input xx = 0 0 1 2 ..... 254 255 255 256 total in + // Output x = 0 1 2 3 ..... 255 256 257 258 total out + float val= heightMap[(yy * regionsize) + xx]; // input from heightMap, <0-255 * 256> <0-255> + if (val < minele) val = minele; + _heightmap[x * (regionsize + 2) + y] = val; // samples output to _heightmap, <0-257 * 258> <0-257> + hfmin = (val < hfmin) ? val : hfmin; + hfmax = (val > hfmax) ? val : hfmax; } + } - - - lock (OdeLock) { IntPtr GroundGeom = IntPtr.Zero; @@ -3504,19 +3486,17 @@ namespace OpenSim.Region.Physics.OdePlugin d.SpaceRemove(space, GroundGeom); d.GeomDestroy(GroundGeom); } - } IntPtr HeightmapData = d.GeomHeightfieldDataCreate(); - d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, heightmapWidth + 1, heightmapHeight + 1, - (int)heightmapWidthSamples + 1, (int)heightmapHeightSamples + 1, scale, - offset, thickness, wrap); + d.GeomHeightfieldDataBuildSingle(HeightmapData, _heightmap, 0, + heightmapWidth, heightmapHeight, (int)heightmapWidthSamples, + (int)heightmapHeightSamples, scale, offset, thickness, wrap); d.GeomHeightfieldDataSetBounds(HeightmapData, hfmin - 1, hfmax + 1); GroundGeom = d.CreateHeightfield(space, HeightmapData, 1); if (GroundGeom != IntPtr.Zero) { d.GeomSetCategoryBits(GroundGeom, (int)(CollisionCategories.Land)); d.GeomSetCollideBits(GroundGeom, (int)(CollisionCategories.Space)); - } geom_name_map[GroundGeom] = "Terrain"; @@ -3534,7 +3514,7 @@ namespace OpenSim.Region.Physics.OdePlugin d.RFromAxisAndAngle(out R, v3.X, v3.Y, v3.Z, angle); d.GeomSetRotation(GroundGeom, ref R); - d.GeomSetPosition(GroundGeom, (pOffset.X + ((int)Constants.RegionSize * 0.5f)) - 1, (pOffset.Y + ((int)Constants.RegionSize * 0.5f)) - 1, 0); + d.GeomSetPosition(GroundGeom, (pOffset.X + (regionsize * 0.5f)) - 0.5f, (pOffset.Y + (regionsize * 0.5f)) - 0.5f, 0); IntPtr testGround = IntPtr.Zero; if (RegionTerrain.TryGetValue(pOffset, out testGround)) { @@ -3542,7 +3522,6 @@ namespace OpenSim.Region.Physics.OdePlugin } RegionTerrain.Add(pOffset, GroundGeom, GroundGeom); TerrainHeightFieldHeights.Add(GroundGeom,_heightmap); - } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs index 880ca1bb7d..07cba60116 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs @@ -112,6 +112,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); } + /// + /// Like osGetAgents but returns enough info for a radar + /// + /// Strided list of the UUID, position and name of each avatar in the region + public LSL_List cmGetAvatarList() + { + LSL_List result = new LSL_List(); + World.ForEachScenePresence(delegate (ScenePresence avatar) + { + if (avatar.UUID != m_host.OwnerID) + { + if (avatar.IsChildAgent == false) + { + result.Add(avatar.UUID); + result.Add(avatar.PhysicsActor.Position); + result.Add(avatar.Name); + } + } + }); + return result; + } + /// /// Get the current Windlight scene /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3f630f4b18..228e9b8aa6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2881,6 +2881,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llLookAt(LSL_Vector target, double strength, double damping) { + /* m_host.AddScriptLPS(1); // Determine where we are looking from LSL_Vector from = llGetPos(); @@ -2900,12 +2901,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // the angles of rotation in radians into rotation value LSL_Types.Quaternion rot = llEuler2Rot(angle); - /* - Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); - m_host.startLookAt(rotation, (float)damping, (float)strength); - This would only work if your physics system contains an APID controller */ + + // This would only work if your physics system contains an APID controller: + // Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); + // m_host.startLookAt(rotation, (float)damping, (float)strength); + // Orient the object to the angle calculated llSetRot(rot); + */ + + //The above code, while nice, doesn't replicate the behaviour of SL and tends to "roll" the object. + //There's probably a smarter way of doing this, my rotation math-fu is weak. + // http://bugs.meta7.com/view.php?id=28 + // - Tom + + LSL_Rotation newrot = llGetRot() * llRotBetween(new LSL_Vector(1.0d, 0.0d, 0.0d) * llGetRot(), new LSL_Vector(0.0d, 0.0d, -1.0d)); + llSetRot(newrot * llRotBetween(new LSL_Vector(0.0d,0.0d,1.0d) * newrot, target - llGetPos())); + } public void llRotLookAt(LSL_Rotation target, double strength, double damping) @@ -6222,6 +6234,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api tempf = (float)rules.GetLSLFloatItem(i + 1); prules.OuterAngle = (float)tempf; break; + + case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: + tempf = (float)rules.GetLSLFloatItem(i + 1); + prules.InnerAngle = (float)tempf; + break; + + case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: + tempf = (float)rules.GetLSLFloatItem(i + 1); + prules.OuterAngle = (float)tempf; + break; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs index f13b6e50e3..fba27f9d35 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs @@ -44,5 +44,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_List cmGetWindlightScene(LSL_List rules); int cmSetWindlightScene(LSL_List rules); int cmSetWindlightSceneTargeted(LSL_List rules, key target); + LSL_List cmGetAvatarList(); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs index c0edaae6bc..aaffbe47fb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs @@ -72,5 +72,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); } + public LSL_List cmGetAvatarList() + { + return m_CM_Functions.cmGetAvatarList(); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index ee35fa4b6a..b3e474004e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -274,6 +274,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CHANGED_ALLOWED_DROP = 64; public const int CHANGED_OWNER = 128; public const int CHANGED_REGION_RESTART = 256; + public const int CHANGED_REGION_START = 256; //LL Changed the constant from CHANGED_REGION_RESTART public const int CHANGED_REGION = 512; public const int CHANGED_TELEPORT = 1024; public const int CHANGED_ANIMATION = 16384; diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index b9723a84b3..ed87f3f6fc 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -93,6 +93,11 @@ namespace OpenSim.Services.AssetService return m_Database.GetAsset(assetID); } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { UUID assetID; diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index a5c157d7f2..65b3537041 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -111,6 +111,14 @@ namespace OpenSim.Services.Connectors return asset; } + public AssetBase GetCached(string id) + { + if (m_Cache != null) + return m_Cache.Get(id); + + return null; + } + public AssetMetadata GetMetadata(string id) { if (m_Cache != null) diff --git a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs index 677169d76a..34df54a90b 100644 --- a/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/HGAssetServiceConnector.cs @@ -116,6 +116,20 @@ namespace OpenSim.Services.Connectors return null; } + public AssetBase GetCached(string id) + { + string url = string.Empty; + string assetID = string.Empty; + + if (StringToUrlAndAssetID(id, out url, out assetID)) + { + IAssetService connector = GetConnector(url); + return connector.GetCached(assetID); + } + + return null; + } + public AssetMetadata GetMetadata(string id) { string url = string.Empty; diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 27434ad0de..17febf9584 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -406,5 +406,13 @@ namespace OpenSim.Services.Connectors.SimianGrid } #endregion IAssetService + + public AssetBase GetCached(string id) + { + if (m_cache != null) + return m_cache.Get(id); + + return null; + } } } diff --git a/OpenSim/Services/Interfaces/IAssetService.cs b/OpenSim/Services/Interfaces/IAssetService.cs index 6dfe78d724..3be6815728 100644 --- a/OpenSim/Services/Interfaces/IAssetService.cs +++ b/OpenSim/Services/Interfaces/IAssetService.cs @@ -51,7 +51,15 @@ namespace OpenSim.Services.Interfaces byte[] GetData(string id); /// - /// Get an asset asynchronously + /// Synchronously fetches an asset from the local cache only + /// + /// Asset ID + /// The fetched asset, or null if it did not exist in the local cache + AssetBase GetCached(string id); + + /// + /// Get an asset synchronously or asynchronously (depending on whether + /// it is locally cached) and fire a callback with the fetched asset /// /// The asset id /// Represents the requester. Passed back via the handler diff --git a/OpenSim/Tests/Common/Mock/MockAssetService.cs b/OpenSim/Tests/Common/Mock/MockAssetService.cs index cb380431d4..4118308bed 100644 --- a/OpenSim/Tests/Common/Mock/MockAssetService.cs +++ b/OpenSim/Tests/Common/Mock/MockAssetService.cs @@ -65,6 +65,11 @@ namespace OpenSim.Tests.Common.Mock return asset; } + public AssetBase GetCached(string id) + { + return Get(id); + } + public AssetMetadata GetMetadata(string id) { throw new System.NotImplementedException();