From f5a088c9cc1e068cc49f13dce3cbbf1beae2468f Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 4 Mar 2010 08:33:01 -0800 Subject: [PATCH 01/17] Replaced BclExtras.dll with a newer version compiled for .NET 3.5. This solves the compilation errors that have been affecting build on Windows for the past day. Thanks lkalif for noticing the conflict. --- bin/BclExtras.dll | Bin 178688 -> 0 bytes bin/BclExtras35.dll | Bin 0 -> 153600 bytes prebuild.xml | 4 ++-- 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 bin/BclExtras.dll create mode 100644 bin/BclExtras35.dll diff --git a/bin/BclExtras.dll b/bin/BclExtras.dll deleted file mode 100644 index 505cf01f0656986a3fbde418777885c51a9ff5c7..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 178688 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≺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 - + @@ -1605,7 +1605,7 @@ - + From e07548d703798bfd661c1ab89cc3b48c936d0a77 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 4 Mar 2010 20:08:25 +0000 Subject: [PATCH 02/17] move linden notecard parsing from LSL_Api.cs to SLUtil so that region modules can use it --- OpenSim/Framework/SLUtil.cs | 99 ++++++++++++++++++- .../Region/Application/ConfigurationLoader.cs | 19 ++-- .../Region/Framework/Scenes/EventManager.cs | 30 +++--- .../Scenes/SceneObjectPartInventory.cs | 1 - .../Shared/Api/Implementation/LSL_Api.cs | 83 +--------------- 5 files changed, 123 insertions(+), 109 deletions(-) diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs index 9d5c30a8f1..ff5f8b9556 100644 --- a/OpenSim/Framework/SLUtil.cs +++ b/OpenSim/Framework/SLUtil.cs @@ -1,4 +1,5 @@ using System; +using System.Collections.Generic; using OpenMetaverse; namespace OpenSim.Framework @@ -181,5 +182,101 @@ namespace OpenSim.Framework } #endregion SL / file extension / content-type conversions + + ///

+ /// Parse a notecard in Linden format to a string of ordinary text. + /// + /// + /// + public static string ParseNotecardToString(string rawInput) + { + return string.Join("\n", ParseNotecardToList(rawInput).ToArray()); + } + + /// + /// Parse a notecard in Linden format to a list of ordinary lines. + /// + /// + /// + public static List ParseNotecardToList(string rawInput) + { + string[] input = rawInput.Replace("\r", "").Split('\n'); + int idx = 0; + int level = 0; + List output = new List(); + string[] words; + + while (idx < input.Length) + { + if (input[idx] == "{") + { + level++; + idx++; + continue; + } + + if (input[idx]== "}") + { + level--; + idx++; + continue; + } + + switch (level) + { + case 0: + words = input[idx].Split(' '); // Linden text ver + // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) + if (words.Length < 3) + return output; + + int version = int.Parse(words[3]); + if (version != 2) + return output; + break; + case 1: + words = input[idx].Split(' '); + if (words[0] == "LLEmbeddedItems") + break; + if (words[0] == "Text") + { + int len = int.Parse(words[2]); + idx++; + + int count = -1; + + while (count < len) + { + // int l = input[idx].Length; + string ln = input[idx]; + + int need = len-count-1; + if (ln.Length > need) + ln = ln.Substring(0, need); + + output.Add(ln); + count += ln.Length + 1; + idx++; + } + + return output; + } + break; + case 2: + words = input[idx].Split(' '); // count + if (words[0] == "count") + { + int c = int.Parse(words[1]); + if (c > 0) + return output; + break; + } + break; + } + idx++; + } + + return output; + } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 655c5ca2e3..8f19417018 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -164,12 +164,12 @@ namespace OpenSim m_config.Source = new IniConfigSource(); m_config.Source.Merge(DefaultConfig()); - m_log.Info("[CONFIG] Reading configuration settings"); + m_log.Info("[CONFIG]: Reading configuration settings"); if (sources.Count == 0) { - m_log.FatalFormat("[CONFIG] Could not load any configuration"); - m_log.FatalFormat("[CONFIG] Did you copy the OpenSim.ini.example file to OpenSim.ini?"); + m_log.FatalFormat("[CONFIG]: Could not load any configuration"); + m_log.FatalFormat("[CONFIG]: Did you copy the OpenSim.ini.example file to OpenSim.ini?"); Environment.Exit(1); } @@ -182,8 +182,8 @@ namespace OpenSim if (!iniFileExists) { - m_log.FatalFormat("[CONFIG] Could not load any configuration"); - m_log.FatalFormat("[CONFIG] Configuration exists, but there was an error loading it!"); + m_log.FatalFormat("[CONFIG]: Could not load any configuration"); + m_log.FatalFormat("[CONFIG]: Configuration exists, but there was an error loading it!"); Environment.Exit(1); } @@ -257,20 +257,17 @@ namespace OpenSim if (!IsUri(iniPath)) { - m_log.InfoFormat("[CONFIG] Reading configuration file {0}", - Path.GetFullPath(iniPath)); + m_log.InfoFormat("[CONFIG]: Reading configuration file {0}", Path.GetFullPath(iniPath)); m_config.Source.Merge(new IniConfigSource(iniPath)); success = true; } else { - m_log.InfoFormat("[CONFIG] {0} is a http:// URI, fetching ...", - iniPath); + m_log.InfoFormat("[CONFIG]: {0} is a http:// URI, fetching ...", iniPath); // The ini file path is a http URI // Try to read it - // try { XmlReader r = XmlReader.Create(iniPath); @@ -281,7 +278,7 @@ namespace OpenSim } catch (Exception e) { - m_log.FatalFormat("[CONFIG] Exception reading config from URI {0}\n" + e.ToString(), iniPath); + m_log.FatalFormat("[CONFIG]: Exception reading config from URI {0}\n" + e.ToString(), iniPath); Environment.Exit(1); } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index ac0446246b..f0d346fbc0 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -110,21 +110,24 @@ namespace OpenSim.Region.Framework.Scenes public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; /// - /// Called when an object is touched/grabbed. + /// Fired when an object is touched/grabbed. /// /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of - /// the root part. - public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); + /// the root part. public event ObjectGrabDelegate OnObjectGrab; + public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); public event ObjectGrabDelegate OnObjectGrabbing; public event ObjectDeGrabDelegate OnObjectDeGrab; public event ScriptResetDelegate OnScriptReset; - public event OnPermissionErrorDelegate OnPermissionError; + public event OnPermissionErrorDelegate OnPermissionError; - public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); + /// + /// Fired when a new script is created. + /// public event NewRezScript OnRezScript; + public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); public delegate void RemoveScript(uint localID, UUID itemID); public event RemoveScript OnRemoveScript; @@ -166,38 +169,35 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientClosed(UUID clientID, Scene scene); - public event ClientClosed OnClientClosed; + public event ClientClosed OnClientClosed; + /// + /// This is fired when a scene object property that a script might be interested in (such as color, scale or + /// inventory) changes. Only enough information is sent for the LSL changed event + /// (see http://lslwiki.net/lslwiki/wakka.php?wakka=changed) + /// + public event ScriptChangedEvent OnScriptChangedEvent; public delegate void ScriptChangedEvent(uint localID, uint change); - public event ScriptChangedEvent OnScriptChangedEvent; - public delegate void ScriptControlEvent(uint localID, UUID item, UUID avatarID, uint held, uint changed); - public event ScriptControlEvent OnScriptControlEvent; public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); - public event ScriptAtTargetEvent OnScriptAtTargetEvent; public delegate void ScriptNotAtTargetEvent(uint localID); - public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); - public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; public delegate void ScriptNotAtRotTargetEvent(uint localID); - public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; public delegate void ScriptColliding(uint localID, ColliderArgs colliders); - public event ScriptColliding OnScriptColliderStart; public event ScriptColliding OnScriptColliding; public event ScriptColliding OnScriptCollidingEnd; - public event ScriptColliding OnScriptLandColliderStart; public event ScriptColliding OnScriptLandColliding; public event ScriptColliding OnScriptLandColliderEnd; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 04e32212df..77bf6fe616 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -637,7 +637,6 @@ namespace OpenSim.Region.Framework.Scenes m_items[item.ItemID] = item; m_inventorySerial++; m_part.TriggerScriptChangedEvent(Changed.INVENTORY); - HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index dc4249cc4e..974f91b9a1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -9705,90 +9705,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Notecard nc = new Notecard(); nc.lastRef = DateTime.Now; - nc.text = ParseText(text.Replace("\r", "").Split('\n')); + nc.text = SLUtil.ParseNotecardToList(text).ToArray(); m_Notecards[assetID] = nc; } } - protected static string[] ParseText(string[] input) - { - int idx = 0; - int level = 0; - List output = new List(); - string[] words; - - while (idx < input.Length) - { - if (input[idx] == "{") - { - level++; - idx++; - continue; - } - - if (input[idx]== "}") - { - level--; - idx++; - continue; - } - - switch (level) - { - case 0: - words = input[idx].Split(' '); // Linden text ver - // Notecards are created *really* empty. Treat that as "no text" (just like after saving an empty notecard) - if (words.Length < 3) - return new String[0]; - - int version = int.Parse(words[3]); - if (version != 2) - return new String[0]; - break; - case 1: - words = input[idx].Split(' '); - if (words[0] == "LLEmbeddedItems") - break; - if (words[0] == "Text") - { - int len = int.Parse(words[2]); - idx++; - - int count = -1; - - while (count < len) - { - // int l = input[idx].Length; - string ln = input[idx]; - - int need = len-count-1; - if (ln.Length > need) - ln = ln.Substring(0, need); - - output.Add(ln); - count += ln.Length + 1; - idx++; - } - - return output.ToArray(); - } - break; - case 2: - words = input[idx].Split(' '); // count - if (words[0] == "count") - { - int c = int.Parse(words[1]); - if (c > 0) - return new String[0]; - break; - } - break; - } - idx++; - } - return output.ToArray(); - } - public static bool IsCached(UUID assetID) { lock (m_Notecards) @@ -9844,4 +9765,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } -} +} \ No newline at end of file From a1643c78beddf6e96d6bf124cdee8ef8c96cab51 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 4 Mar 2010 22:43:30 +0000 Subject: [PATCH 03/17] remove test presence from NullPresenceData since this appears to stop existing sessions with home locations from being picked up only tested for a single user so this may still fail for multiple users this may well be all academic anyway since standalone need to persistently store home location in presence data in some way --- OpenSim/Data/MySQL/MySQLPresenceData.cs | 4 +- OpenSim/Data/Null/NullPresenceData.cs | 51 +++++++++++++++---- .../Services/LLLoginService/LLLoginService.cs | 31 +++++++++-- 3 files changed, 72 insertions(+), 14 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLPresenceData.cs b/OpenSim/Data/MySQL/MySQLPresenceData.cs index fcbe3d669e..68a68af3c8 100644 --- a/OpenSim/Data/MySQL/MySQLPresenceData.cs +++ b/OpenSim/Data/MySQL/MySQLPresenceData.cs @@ -122,7 +122,7 @@ namespace OpenSim.Data.MySQL cmd.CommandText = String.Format("select * from {0} where UserID=?UserID", m_Realm); cmd.Parameters.AddWithValue("?UserID", userID); -; + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); @@ -131,7 +131,6 @@ namespace OpenSim.Data.MySQL using (IDataReader reader = cmd.ExecuteReader()) { - List deleteSessions = new List(); int online = 0; @@ -143,6 +142,7 @@ namespace OpenSim.Data.MySQL deleteSessions.Add(new UUID(reader["SessionID"].ToString())); } + // Leave one session behind so that we can pick up details such as home location if (online == 0 && deleteSessions.Count > 0) deleteSessions.RemoveAt(0); diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs index 5f786910c3..555c92f950 100644 --- a/OpenSim/Data/Null/NullPresenceData.cs +++ b/OpenSim/Data/Null/NullPresenceData.cs @@ -28,6 +28,8 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; @@ -36,6 +38,8 @@ namespace OpenSim.Data.Null { public class NullPresenceData : IPresenceData { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static NullPresenceData Instance; Dictionary m_presenceData = new Dictionary(); @@ -48,20 +52,25 @@ namespace OpenSim.Data.Null //Console.WriteLine("[XXX] NullRegionData constructor"); // Let's stick in a test presence + /* PresenceData p = new PresenceData(); p.SessionID = UUID.Zero; p.UserID = UUID.Zero.ToString(); p.Data = new Dictionary(); p.Data["Online"] = true.ToString(); m_presenceData.Add(UUID.Zero, p); + */ } } public bool Store(PresenceData data) - { + { if (Instance != this) return Instance.Store(data); +// m_log.DebugFormat("[NULL PRESENCE DATA]: Storing presence {0}", data.UserID); +// Console.WriteLine("HOME for " + data.UserID + " is " + (data.Data.ContainsKey("HomeRegionID") ? data.Data["HomeRegionID"] : "Not found")); + m_presenceData[data.SessionID] = data; return true; } @@ -100,6 +109,7 @@ namespace OpenSim.Data.Null { if (Instance != this) return Instance.ReportAgent(sessionID, regionID, position, lookAt); + if (m_presenceData.ContainsKey(sessionID)) { m_presenceData[sessionID].RegionID = regionID; @@ -112,7 +122,7 @@ namespace OpenSim.Data.Null } public bool SetHomeLocation(string userID, UUID regionID, Vector3 position, Vector3 lookAt) - { + { if (Instance != this) return Instance.SetHomeLocation(userID, regionID, position, lookAt); @@ -121,27 +131,40 @@ namespace OpenSim.Data.Null { if (p.UserID == userID) { +// m_log.DebugFormat( +// "[NULL PRESENCE DATA]: Setting home location {0} {1} {2} for {3}", +// regionID, position, lookAt, p.UserID); + p.Data["HomeRegionID"] = regionID.ToString(); p.Data["HomePosition"] = position.ToString(); p.Data["HomeLookAt"] = lookAt.ToString(); foundone = true; - } + } } return foundone; } public PresenceData[] Get(string field, string data) - { + { if (Instance != this) return Instance.Get(field, data); +// m_log.DebugFormat( +// "[NULL PRESENCE DATA]: Getting presence data for field {0} with parameter {1}", field, data); + List presences = new List(); if (field == "UserID") { foreach (PresenceData p in m_presenceData.Values) - if (p.UserID == data) - presences.Add(p); + { + if (p.UserID == data) + { + presences.Add(p); +// Console.WriteLine("HOME for " + p.UserID + " is " + (p.Data.ContainsKey("HomeRegionID") ? p.Data["HomeRegionID"] : "Not found")); + } + } + return presences.ToArray(); } else if (field == "SessionID") @@ -180,36 +203,46 @@ namespace OpenSim.Data.Null } public void Prune(string userID) - { + { if (Instance != this) { Instance.Prune(userID); return; } +// m_log.DebugFormat("[NULL PRESENCE DATA]: Prune called for {0}", userID); + List deleteSessions = new List(); int online = 0; foreach (KeyValuePair kvp in m_presenceData) { + m_log.DebugFormat("Online: {0}", kvp.Value.Data["Online"]); + bool on = false; if (bool.TryParse(kvp.Value.Data["Online"], out on) && on) online++; else deleteSessions.Add(kvp.Key); } + +// m_log.DebugFormat("[NULL PRESENCE DATA]: online [{0}], deleteSession.Count [{1}]", online, deleteSessions.Count); + + // Leave one session behind so that we can pick up details such as home location if (online == 0 && deleteSessions.Count > 0) deleteSessions.RemoveAt(0); foreach (UUID s in deleteSessions) m_presenceData.Remove(s); - } public bool Delete(string field, string data) { +// m_log.DebugFormat( +// "[NULL PRESENCE DATA]: Deleting presence data for field {0} with parameter {1}", field, data); + if (Instance != this) - return Delete(field, data); + return Instance.Delete(field, data); List presences = new List(); if (field == "UserID") diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index ee93f73cde..ae729f8ca4 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -279,7 +279,31 @@ namespace OpenSim.Services.LLLoginService GridRegion region = null; - if (pinfo.HomeRegionID.Equals(UUID.Zero) || (region = m_GridService.GetRegionByUUID(account.ScopeID, pinfo.HomeRegionID)) == null) + bool tryDefaults = false; + + if (pinfo.HomeRegionID.Equals(UUID.Zero)) + { + m_log.WarnFormat( + "[LLOGIN SERVICE]: User {0} {1} tried to login to a 'home' start location but they have none set", + account.FirstName, account.LastName); + + tryDefaults = true; + } + else + { + region = m_GridService.GetRegionByUUID(account.ScopeID, pinfo.HomeRegionID); + + if (null == region) + { + m_log.WarnFormat( + "[LLOGIN SERVICE]: User {0} {1} has a recorded home region of {2} but this cannot be found by the grid service", + account.FirstName, account.LastName, pinfo.HomeRegionID); + + tryDefaults = true; + } + } + + if (tryDefaults) { List defaults = m_GridService.GetDefaultRegions(account.ScopeID); if (defaults != null && defaults.Count > 0) @@ -288,7 +312,8 @@ namespace OpenSim.Services.LLLoginService where = "safe"; } else - m_log.WarnFormat("[LLOGIN SERVICE]: User {0} {1} does not have a home set and this grid does not have default locations.", + m_log.WarnFormat( + "[LLOGIN SERVICE]: User {0} {1} does not have a valid home and this grid does not have default locations.", account.FirstName, account.LastName); } @@ -318,8 +343,8 @@ namespace OpenSim.Services.LLLoginService position = pinfo.Position; lookAt = pinfo.LookAt; } + return region; - } else { From 82cccdeb94bf6437df79cc77009c8e19da5aaaf0 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Thu, 4 Mar 2010 22:50:02 +0000 Subject: [PATCH 04/17] minor: comment out a forgotton debug log line --- OpenSim/Data/Null/NullPresenceData.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs index 555c92f950..2ceb0c66a4 100644 --- a/OpenSim/Data/Null/NullPresenceData.cs +++ b/OpenSim/Data/Null/NullPresenceData.cs @@ -217,7 +217,7 @@ namespace OpenSim.Data.Null foreach (KeyValuePair kvp in m_presenceData) { - m_log.DebugFormat("Online: {0}", kvp.Value.Data["Online"]); +// m_log.DebugFormat("Online: {0}", kvp.Value.Data["Online"]); bool on = false; if (bool.TryParse(kvp.Value.Data["Online"], out on) && on) From e39fc95659a405a8500c9014d2ac31c5d85741d7 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 5 Mar 2010 00:54:46 +0000 Subject: [PATCH 05/17] Fix LocalPresenceServiceConnector test now that the hardcoded test data has been removed from Data.Null.NullPresenceData Unfortunately, this meant publicly exposing the underlying service for the connector. The other solution would be to create alternative initializers for services and connectors where objects could be given directly rather than loaded indirectly through config. Unfortunately, this would require a lot of work in this case but might be the better way forward. --- OpenSim/Data/Null/NullPresenceData.cs | 9 --------- OpenSim/Framework/SLUtil.cs | 12 +++++++++++- OpenSim/Region/Application/ConfigurationLoader.cs | 14 ++------------ .../Presence/LocalPresenceServiceConnector.cs | 6 +++++- .../Presence/Tests/PresenceConnectorsTests.cs | 13 +++++++++++++ .../Shared/Api/Implementation/LSL_Api.cs | 1 - 6 files changed, 31 insertions(+), 24 deletions(-) diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs index 2ceb0c66a4..9fc45958eb 100644 --- a/OpenSim/Data/Null/NullPresenceData.cs +++ b/OpenSim/Data/Null/NullPresenceData.cs @@ -51,15 +51,6 @@ namespace OpenSim.Data.Null Instance = this; //Console.WriteLine("[XXX] NullRegionData constructor"); - // Let's stick in a test presence - /* - PresenceData p = new PresenceData(); - p.SessionID = UUID.Zero; - p.UserID = UUID.Zero.ToString(); - p.Data = new Dictionary(); - p.Data["Online"] = true.ToString(); - m_presenceData.Add(UUID.Zero, p); - */ } } diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs index ff5f8b9556..81d82bee5e 100644 --- a/OpenSim/Framework/SLUtil.cs +++ b/OpenSim/Framework/SLUtil.cs @@ -1,11 +1,15 @@ using System; using System.Collections.Generic; +using System.Reflection; +using log4net; using OpenMetaverse; namespace OpenSim.Framework { public static class SLUtil { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + #region SL / file extension / content-type conversions public static string SLAssetTypeToContentType(int assetType) @@ -190,7 +194,12 @@ namespace OpenSim.Framework /// public static string ParseNotecardToString(string rawInput) { - return string.Join("\n", ParseNotecardToList(rawInput).ToArray()); + string[] output = ParseNotecardToList(rawInput).ToArray(); + +// foreach (string line in output) +// m_log.DebugFormat("[PARSE NOTECARD]: ParseNotecardToString got line {0}", line); + + return string.Join("\n", output); } /// @@ -254,6 +263,7 @@ namespace OpenSim.Framework if (ln.Length > need) ln = ln.Substring(0, need); +// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", ln); output.Add(ln); count += ln.Length + 1; idx++; diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 8f19417018..4ca6595501 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -42,6 +42,8 @@ namespace OpenSim /// public class ConfigurationLoader { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// /// Various Config settings the region needs to start /// Physics Engine, Mesh Engine, GridMode, PhysicsPrim allowed, Neighbor, @@ -60,17 +62,6 @@ namespace OpenSim /// protected NetworkServersInfo m_networkServersInfo; - /// - /// Console logger - /// - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - public ConfigurationLoader() - { - } - /// /// Loads the region configuration /// @@ -188,7 +179,6 @@ namespace OpenSim } // Make sure command line options take precedence - // m_config.Source.Merge(argvSource); ReadConfigSettings(); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs index d78daf9be4..c402a3face 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/LocalPresenceServiceConnector.cs @@ -47,7 +47,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence private bool m_Enabled = false; private PresenceDetector m_PresenceDetector; - private IPresenceService m_PresenceService; + + /// + /// Underlying presence service. Do not use directly. + /// + public IPresenceService m_PresenceService; public LocalPresenceServicesConnector() { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs index ca424615a0..292ff8ea87 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/Tests/PresenceConnectorsTests.cs @@ -59,6 +59,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests config.Configs["PresenceService"].Set("StorageProvider", "OpenSim.Data.Null.dll"); m_LocalConnector = new LocalPresenceServicesConnector(config); + + // Let's stick in a test presence + m_LocalConnector.m_PresenceService.LoginAgent(UUID.Zero.ToString(), UUID.Zero, UUID.Zero); } /// @@ -68,6 +71,16 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence.Tests public void TestPresenceV0_1() { SetUp(); + + // Let's stick in a test presence + /* + PresenceData p = new PresenceData(); + p.SessionID = UUID.Zero; + p.UserID = UUID.Zero.ToString(); + p.Data = new Dictionary(); + p.Data["Online"] = true.ToString(); + m_presenceData.Add(UUID.Zero, p); + */ string user1 = UUID.Zero.ToString(); UUID session1 = UUID.Zero; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 974f91b9a1..0134b03180 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -52,7 +52,6 @@ using OpenSim.Region.ScriptEngine.Shared.ScriptBase; using OpenSim.Region.ScriptEngine.Interfaces; using OpenSim.Region.ScriptEngine.Shared.Api.Interfaces; using OpenSim.Services.Interfaces; -using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using PrimType = OpenSim.Region.Framework.Scenes.PrimType; From 463d7752614df8a8b3c01a52150afac4e0f8adec Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Thu, 4 Mar 2010 21:02:35 -0800 Subject: [PATCH 06/17] Bug fix on user account creation -- ServiceURLs field now properly filled out. --- OpenSim/Services/UserAccountService/UserAccountService.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index ca6e44ac14..82c34e7bfa 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -280,7 +280,7 @@ namespace OpenSim.Services.UserAccountService if (null == account) { account = new UserAccount(UUID.Zero, firstName, lastName, email); - if (account.ServiceURLs == null) + if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0)) { account.ServiceURLs = new Dictionary(); account.ServiceURLs["HomeURI"] = string.Empty; From e906dd3d28a3cb4dfada36daccfd8900f0e844b5 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 5 Mar 2010 22:29:51 +0000 Subject: [PATCH 07/17] add initial UserGrid service classes as per diva's direction this will initially store home location data instead of the presence service compiles but not enough to actually test yet --- OpenSim/Data/IUserGridData.cs | 50 +++++++ .../Data/MySQL/MySQLGenericTableHandler.cs | 3 +- OpenSim/Data/MySQL/MySQLUserGridData.cs | 64 ++++++++ .../UserGrid/LocalUserGridServiceConnector.cs | 139 ++++++++++++++++++ .../UserGrid/UserGridServiceConnector.cs | 38 +++++ .../Services/Interfaces/IUserGridService.cs | 75 ++++++++++ .../UserAccountService/UserGridService.cs | 76 ++++++++++ .../UserAccountService/UserGridServiceBase.cs | 82 +++++++++++ bin/config-include/Standalone.ini | 19 ++- 9 files changed, 534 insertions(+), 12 deletions(-) create mode 100644 OpenSim/Data/IUserGridData.cs create mode 100644 OpenSim/Data/MySQL/MySQLUserGridData.cs create mode 100644 OpenSim/Region/CoreModules/ServiceConnectorsOut/UserGrid/LocalUserGridServiceConnector.cs create mode 100644 OpenSim/Services/Connectors/UserGrid/UserGridServiceConnector.cs create mode 100644 OpenSim/Services/Interfaces/IUserGridService.cs create mode 100644 OpenSim/Services/UserAccountService/UserGridService.cs create mode 100644 OpenSim/Services/UserAccountService/UserGridServiceBase.cs diff --git a/OpenSim/Data/IUserGridData.cs b/OpenSim/Data/IUserGridData.cs new file mode 100644 index 0000000000..6f7467ee96 --- /dev/null +++ b/OpenSim/Data/IUserGridData.cs @@ -0,0 +1,50 @@ +/* + * 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.Generic; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Data +{ + // This MUST be a ref type! + public class UserGridData + { + public string UserID; + public Dictionary Data; + } + + /// + /// An interface for connecting to the user grid datastore + /// + public interface IUserGridData + { + UserGridData GetUserGridData(string userID); + bool StoreUserGridData(UserGridData data); + } +} \ No newline at end of file diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index b170ddee90..756b42d7c1 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -197,8 +197,7 @@ namespace OpenSim.Data.MySQL public virtual T[] Get(string where) { using (MySqlCommand cmd = new MySqlCommand()) - { - + { string query = String.Format("select * from {0} where {1}", m_Realm, where); diff --git a/OpenSim/Data/MySQL/MySQLUserGridData.cs b/OpenSim/Data/MySQL/MySQLUserGridData.cs new file mode 100644 index 0000000000..7209b18226 --- /dev/null +++ b/OpenSim/Data/MySQL/MySQLUserGridData.cs @@ -0,0 +1,64 @@ +/* + * 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.Generic; +using System.Data; +using System.Reflection; +using System.Threading; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using MySql.Data.MySqlClient; + +namespace OpenSim.Data.MySQL +{ + /// + /// A MySQL Interface for user grid data + /// + public class MySQLUserGridData : MySQLGenericTableHandler, IUserGridData + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public MySQLUserGridData(string connectionString, string realm) : base(connectionString, realm, "UserGrid") {} + + public UserGridData GetUserGridData(string userID) + { + UserGridData[] ret = Get("UserID", userID); + + if (ret.Length == 0) + return null; + + return ret[0]; + } + + public bool StoreUserGridData(UserGridData data) + { + return Store(data); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserGrid/LocalUserGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserGrid/LocalUserGridServiceConnector.cs new file mode 100644 index 0000000000..f4309fead0 --- /dev/null +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserGrid/LocalUserGridServiceConnector.cs @@ -0,0 +1,139 @@ +/* + * 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.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; + +using OpenMetaverse; + +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserGrid +{ + public class LocalUserGridServicesConnector : ISharedRegionModule, IUserGridService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IUserGridService m_service; + + private bool m_Enabled = false; + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "LocalUserGridServicesConnector"; } + } + + public void Initialise(IConfigSource source) + { + IConfig moduleConfig = source.Configs["Modules"]; + if (moduleConfig != null) + { + string name = moduleConfig.GetString("UserGridServices", ""); + if (name == Name) + { + IConfig userConfig = source.Configs["UserGridService"]; + if (userConfig == null) + { + m_log.Error("[LOCAL USER GRID SERVICE CONNECTOR]: UserGridService missing from ini files"); + return; + } + + string serviceDll = userConfig.GetString("LocalServiceModule", String.Empty); + + if (serviceDll == String.Empty) + { + m_log.Error("[LOCAL USER GRID SERVICE CONNECTOR]: No LocalServiceModule named in section UserGridService"); + return; + } + + Object[] args = new Object[] { source }; + m_service = ServerUtils.LoadPlugin(serviceDll, args); + + if (m_service == null) + { + m_log.Error("[LOCAL USER GRID SERVICE CONNECTOR]: Can't load UserGrid service"); + return; + } + m_Enabled = true; + m_log.Info("[LOCAL USER GRID SERVICE CONNECTOR]: Local UserGrid connector enabled"); + } + } + } + + public void PostInitialise() + { + if (!m_Enabled) + return; + } + + public void Close() + { + if (!m_Enabled) + return; + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + scene.RegisterModuleInterface(m_service); + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + } + + public UserGridInfo GetUserGridInfo(string userID) + { + return m_service.GetUserGridInfo(userID); + } + + public bool StoreUserGridInfo(UserGridInfo info) + { + return m_service.StoreUserGridInfo(info); + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/UserGrid/UserGridServiceConnector.cs b/OpenSim/Services/Connectors/UserGrid/UserGridServiceConnector.cs new file mode 100644 index 0000000000..3aa8940e8a --- /dev/null +++ b/OpenSim/Services/Connectors/UserGrid/UserGridServiceConnector.cs @@ -0,0 +1,38 @@ +/* + * 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; + +namespace OpenSim.Services.Connectors +{ + public class UserGridServiceConnector + { + public UserGridServiceConnector() + { + } + } +} diff --git a/OpenSim/Services/Interfaces/IUserGridService.cs b/OpenSim/Services/Interfaces/IUserGridService.cs new file mode 100644 index 0000000000..50134e0c6c --- /dev/null +++ b/OpenSim/Services/Interfaces/IUserGridService.cs @@ -0,0 +1,75 @@ +/* + * 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.Generic; +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + /// + /// Records user information specific to a grid but which is not part of a user's account. + /// + public class UserGridInfo + { + public string UserID; + public UUID HomeRegionID; + public Vector3 HomePosition; + public Vector3 HomeLookAt; + + public UserGridInfo() {} + + public UserGridInfo(Dictionary kvp) + { + if (kvp.ContainsKey("UserID")) + UserID = kvp["UserID"].ToString(); + if (kvp.ContainsKey("HomeRegionID")) + UUID.TryParse(kvp["HomeRegionID"].ToString(), out HomeRegionID); + if (kvp.ContainsKey("HomePosition")) + Vector3.TryParse(kvp["HomePosition"].ToString(), out HomePosition); + if (kvp.ContainsKey("HomeLookAt")) + Vector3.TryParse(kvp["HomeLookAt"].ToString(), out HomeLookAt); + } + + public Dictionary ToKeyValuePairs() + { + Dictionary result = new Dictionary(); + result["UserID"] = UserID; + result["HomeRegionID"] = HomeRegionID.ToString(); + result["HomePosition"] = HomePosition.ToString(); + result["HomeLookAt"] = HomeLookAt.ToString(); + + return result; + } + } + + public interface IUserGridService + { + UserGridInfo GetUserGridInfo(string userID); + bool StoreUserGridInfo(UserGridInfo info); + } +} \ No newline at end of file diff --git a/OpenSim/Services/UserAccountService/UserGridService.cs b/OpenSim/Services/UserAccountService/UserGridService.cs new file mode 100644 index 0000000000..2d28b331d2 --- /dev/null +++ b/OpenSim/Services/UserAccountService/UserGridService.cs @@ -0,0 +1,76 @@ +/* + * 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.Generic; +using System.Reflection; +using Nini.Config; +using OpenSim.Data; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Console; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; + +using OpenMetaverse; +using log4net; + +namespace OpenSim.Services.UserAccountService +{ + public class UserGridService : UserGridServiceBase, IUserGridService + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public UserGridService(IConfigSource config) : base(config) + { + m_log.Debug("[USER GRID SERVICE]: Starting user grid service"); + } + + public UserGridInfo GetUserGridInfo(string userID) + { + UserGridData d = m_Database.GetUserGridData(userID); + + UserGridInfo info = new UserGridInfo(); + info.UserID = d.UserID; + info.HomeRegionID = new UUID(d.Data["HomeRegionID"]); + info.HomePosition = Vector3.Parse(d.Data["HomePosition"]); + info.HomeLookAt = Vector3.Parse(d.Data["HomeLookAt"]); + + return info; + } + + public bool StoreUserGridInfo(UserGridInfo info) + { + UserGridData d = new UserGridData(); + + d.Data["UserID"] = info.UserID; + d.Data["HomeRegionID"] = info.HomeRegionID.ToString(); + d.Data["HomePosition"] = info.HomePosition.ToString(); + d.Data["HomeLookAt"] = info.HomeLookAt.ToString(); + + return m_Database.StoreUserGridData(d); + } + } +} \ No newline at end of file diff --git a/OpenSim/Services/UserAccountService/UserGridServiceBase.cs b/OpenSim/Services/UserAccountService/UserGridServiceBase.cs new file mode 100644 index 0000000000..80aaa49a64 --- /dev/null +++ b/OpenSim/Services/UserAccountService/UserGridServiceBase.cs @@ -0,0 +1,82 @@ +/* + * 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.Reflection; +using Nini.Config; +using OpenSim.Framework; +using OpenSim.Data; +using OpenSim.Services.Interfaces; +using OpenSim.Services.Base; + +namespace OpenSim.Services.UserAccountService +{ + public class UserGridServiceBase : ServiceBase + { + protected IUserGridData m_Database = null; + + public UserGridServiceBase(IConfigSource config) : base(config) + { + string dllName = String.Empty; + string connString = String.Empty; + string realm = "UserGrid"; + + // + // Try reading the [DatabaseService] section, if it exists + // + IConfig dbConfig = config.Configs["DatabaseService"]; + if (dbConfig != null) + { + if (dllName == String.Empty) + dllName = dbConfig.GetString("StorageProvider", String.Empty); + if (connString == String.Empty) + connString = dbConfig.GetString("ConnectionString", String.Empty); + } + + // + // [PresenceService] section overrides [DatabaseService], if it exists + // + IConfig presenceConfig = config.Configs["PresenceService"]; + if (presenceConfig != null) + { + dllName = presenceConfig.GetString("StorageProvider", dllName); + connString = presenceConfig.GetString("ConnectionString", connString); + realm = presenceConfig.GetString("Realm", realm); + } + + // + // We tried, but this doesn't exist. We can't proceed. + // + if (dllName.Equals(String.Empty)) + throw new Exception("No StorageProvider configured"); + + m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); + if (m_Database == null) + throw new Exception("Could not find a storage interface in the given module " + dllName); + } + } +} \ No newline at end of file diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 30113708a1..1843ef640e 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -24,22 +24,21 @@ [InventoryService] LocalServiceModule = "OpenSim.Services.InventoryService.dll:InventoryService" - [LibraryService] - LocalServiceModule = "OpenSim.Services.InventoryService.dll:LibraryService" - LibraryName = "OpenSim Library" - DefaultLibrary = "./inventory/Libraries.xml" + LocalServiceModule = "OpenSim.Services.InventoryService.dll:LibraryService" + LibraryName = "OpenSim Library" + DefaultLibrary = "./inventory/Libraries.xml" [AvatarService] LocalServiceModule = "OpenSim.Services.AvatarService.dll:AvatarService" - ConnectionString = "URI=file:avatars.db,version=3" + ; ConnectionString = "URI=file:avatars.db,version=3" [AuthorizationService] LocalServiceModule = "OpenSim.Services.AuthorizationService.dll:AuthorizationService" [AuthenticationService] LocalServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" - ConnectionString = "URI=file:auth.db,version=3" + ; ConnectionString = "URI=file:auth.db,version=3" [GridService] LocalServiceModule = "OpenSim.Services.GridService.dll:GridService" @@ -48,12 +47,12 @@ [PresenceService] LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" - StorageProvider = "OpenSim.Data.Null.dll" + ;StorageProvider = "OpenSim.Data.Null.dll" + StorageProvider = "OpenSim.Data.MySQL.dll" [UserAccountService] LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" - ConnectionString = "URI=file:userprofiles.db,version=3" - + ; ConnectionString = "URI=file:userprofiles.db,version=3" ;; These are for creating new accounts AuthenticationService = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" @@ -62,7 +61,7 @@ [FriendsService] LocalServiceModule = "OpenSim.Services.FriendsService.dll" - ConnectionString = "URI=file:friends.db,version=3" + ; ConnectionString = "URI=file:friends.db,version=3" [Friends] Connector = "OpenSim.Services.FriendsService.dll" From a3ac2cbdde347ae591ba05fb16be5d7ca07cc5fd Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 5 Mar 2010 22:38:03 +0000 Subject: [PATCH 08/17] automatically delete %temp% directory after running tests this prevents a huge cruft buildup --- .nant/local.include | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.nant/local.include b/.nant/local.include index 29674ab671..114c12d28f 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -85,6 +85,8 @@ + + From 60553e62a3f576b8bf6ab88a83b2d4550bd69d2b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 5 Mar 2010 23:18:47 +0000 Subject: [PATCH 09/17] refactor: begin to move attachments code into a region module --- .../Avatar/Attachments/AttachmentsModule.cs | 141 ++++++++++++++++++ .../Interfaces/IAttachmentsModule.cs | 49 ++++++ .../Framework/Scenes/Scene.Inventory.cs | 15 -- OpenSim/Region/Framework/Scenes/Scene.cs | 8 +- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 86 +---------- .../Shared/Api/Implementation/LSL_Api.cs | 8 +- 6 files changed, 205 insertions(+), 102 deletions(-) create mode 100644 OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs create mode 100644 OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs new file mode 100644 index 0000000000..103a8135b1 --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -0,0 +1,141 @@ +/* + * 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.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.Avatar.Attachments +{ + public class AttachmentsModule : IAttachmentsModule, IRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene = null; + + public void Initialise(Scene scene, IConfigSource source) + { + scene.RegisterModuleInterface(this); + m_scene = scene; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "Attachments Module"; } + } + + public bool IsSharedModule + { + get { return false; } + } + + public bool AttachObject( + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) + { + SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); + if (group != null) + { + if (m_scene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) + { + // If the attachment point isn't the same as the one previously used + // set it's offset position = 0 so that it appears on the attachment point + // and not in a weird location somewhere unknown. + if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) + { + attachPos = Vector3.Zero; + } + + // AttachmentPt 0 means the client chose to 'wear' the attachment. + if (AttachmentPt == 0) + { + // Check object for stored attachment point + AttachmentPt = (uint)group.GetAttachmentPoint(); + } + + // if we still didn't find a suitable attachment point....... + if (AttachmentPt == 0) + { + // Stick it on left hand with Zero Offset from the attachment point. + AttachmentPt = (uint)AttachmentPoint.LeftHand; + attachPos = Vector3.Zero; + } + + group.SetAttachmentPoint((byte)AttachmentPt); + group.AbsolutePosition = attachPos; + + // Saves and gets itemID + UUID itemId; + + if (group.GetFromItemID() == UUID.Zero) + { + m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); + } + else + { + itemId = group.GetFromItemID(); + } + + m_scene.AttachObject(remoteClient, AttachmentPt, itemId, group); + + group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); + + // In case it is later dropped again, don't let + // it get cleaned up + group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); + group.HasGroupChanged = false; + } + else + { + remoteClient.SendAgentAlertMessage( + "You don't have sufficient permissions to attach this object", false); + + return false; + } + } + else + { + m_log.DebugFormat("[SCENE GRAPH]: AttachObject found no such scene object {0}", objectLocalID); + return false; + } + + return true; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs new file mode 100644 index 0000000000..c965bcf8e7 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -0,0 +1,49 @@ +/* + * 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 OpenSim 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 OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Region.Framework.Interfaces +{ + public interface IAttachmentsModule + { + /// + /// Attach an object to an avatar. + /// + /// + /// + /// + /// + /// + /// + /// true if the object was successfully attached, false otherwise + bool AttachObject( + IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent); + } +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 5f3cd8cf4d..474fba9e11 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1902,21 +1902,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Attach an object. - /// - /// - /// - /// - /// - /// - /// - /// true if the object was successfully attached, false otherwise - public bool AttachObject(IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent) - { - return m_sceneGraph.AttachObject(controllingClient, localID, attachPoint, rot, pos, silent); - } - /// /// This registers the item as attached in a user's inventory /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a880fe7d59..c83132f97d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -307,6 +307,7 @@ namespace OpenSim.Region.Framework.Scenes protected IXMLRPC m_xmlrpcModule; protected IWorldComm m_worldCommModule; + public IAttachmentsModule AttachmentsModule { get; set; } protected IAvatarFactory m_AvatarFactory; public IAvatarFactory AvatarFactory { @@ -1215,6 +1216,7 @@ namespace OpenSim.Region.Framework.Scenes m_worldCommModule = RequestModuleInterface(); XferManager = RequestModuleInterface(); m_AvatarFactory = RequestModuleInterface(); + AttachmentsModule = RequestModuleInterface(); m_serialiser = RequestModuleInterface(); m_dialogModule = RequestModuleInterface(); m_capsModule = RequestModuleInterface(); @@ -2405,9 +2407,11 @@ namespace OpenSim.Region.Framework.Scenes //grp.SetFromAssetID(grp.RootPart.LastOwnerID); m_log.DebugFormat( "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); + + if (AttachmentsModule != null) + AttachmentsModule.AttachObject( + sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); - AttachObject( - sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); RootPrim.RemFlag(PrimFlags.TemporaryOnRez); grp.SendGroupFullUpdate(); } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 22613e925f..48744d71a9 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -504,7 +504,7 @@ namespace OpenSim.Region.Framework.Scenes return; // Calls attach with a Zero position - if (AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false)) + if (m_parentScene.AttachmentsModule.AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false)) { m_parentScene.SendAttachEvent(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); @@ -547,8 +547,10 @@ namespace OpenSim.Region.Framework.Scenes if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) tainted = true; - AttachObject(remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); + m_parentScene.AttachmentsModule.AttachObject( + remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); //objatt.ScheduleGroupForFullUpdate(); + if (tainted) objatt.HasGroupChanged = true; @@ -605,86 +607,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Attach a scene object to an avatar. - /// - /// - /// - /// - /// - /// - /// - /// true if the attachment was successful, false otherwise - protected internal bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) - { - SceneObjectGroup group = GetGroupByPrim(objectLocalID); - if (group != null) - { - if (m_parentScene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) - { - // If the attachment point isn't the same as the one previously used - // set it's offset position = 0 so that it appears on the attachment point - // and not in a weird location somewhere unknown. - if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) - { - attachPos = Vector3.Zero; - } - - // AttachmentPt 0 means the client chose to 'wear' the attachment. - if (AttachmentPt == 0) - { - // Check object for stored attachment point - AttachmentPt = (uint)group.GetAttachmentPoint(); - } - - // if we still didn't find a suitable attachment point....... - if (AttachmentPt == 0) - { - // Stick it on left hand with Zero Offset from the attachment point. - AttachmentPt = (uint)AttachmentPoint.LeftHand; - attachPos = Vector3.Zero; - } - - group.SetAttachmentPoint((byte)AttachmentPt); - group.AbsolutePosition = attachPos; - - // Saves and gets itemID - UUID itemId; - - if (group.GetFromItemID() == UUID.Zero) - { - m_parentScene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); - } - else - { - itemId = group.GetFromItemID(); - } - - m_parentScene.AttachObject(remoteClient, AttachmentPt, itemId, group); - - group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); - // In case it is later dropped again, don't let - // it get cleaned up - // - group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); - group.HasGroupChanged = false; - } - else - { - remoteClient.SendAgentAlertMessage("You don't have sufficient permissions to attach this object", false); - return false; - } - } - else - { - m_log.DebugFormat("[SCENE GRAPH]: AttachObject found no such scene object {0}", objectLocalID); - return false; - } - - return true; - } - protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance) { ScenePresence newAvatar = null; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0134b03180..0eee1471c1 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2896,9 +2896,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(m_host.OwnerID); - m_ScriptEngine.World.AttachObject(presence.ControllingClient, - grp.LocalId, (uint)attachment, Quaternion.Identity, - Vector3.Zero, false); + IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; + if (attachmentsModule != null) + attachmentsModule.AttachObject( + presence.ControllingClient, grp.LocalId, + (uint)attachment, Quaternion.Identity, Vector3.Zero, false); } } From b88259db7d7550dc963e0bfae8a7800ec38a119a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 5 Mar 2010 23:19:22 +0000 Subject: [PATCH 10/17] revert accidental Standalone.ini change --- bin/config-include/Standalone.ini | 19 ++++++++++--------- 1 file changed, 10 insertions(+), 9 deletions(-) diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 1843ef640e..30113708a1 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -24,21 +24,22 @@ [InventoryService] LocalServiceModule = "OpenSim.Services.InventoryService.dll:InventoryService" + [LibraryService] - LocalServiceModule = "OpenSim.Services.InventoryService.dll:LibraryService" - LibraryName = "OpenSim Library" - DefaultLibrary = "./inventory/Libraries.xml" + LocalServiceModule = "OpenSim.Services.InventoryService.dll:LibraryService" + LibraryName = "OpenSim Library" + DefaultLibrary = "./inventory/Libraries.xml" [AvatarService] LocalServiceModule = "OpenSim.Services.AvatarService.dll:AvatarService" - ; ConnectionString = "URI=file:avatars.db,version=3" + ConnectionString = "URI=file:avatars.db,version=3" [AuthorizationService] LocalServiceModule = "OpenSim.Services.AuthorizationService.dll:AuthorizationService" [AuthenticationService] LocalServiceModule = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" - ; ConnectionString = "URI=file:auth.db,version=3" + ConnectionString = "URI=file:auth.db,version=3" [GridService] LocalServiceModule = "OpenSim.Services.GridService.dll:GridService" @@ -47,12 +48,12 @@ [PresenceService] LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" - ;StorageProvider = "OpenSim.Data.Null.dll" - StorageProvider = "OpenSim.Data.MySQL.dll" + StorageProvider = "OpenSim.Data.Null.dll" [UserAccountService] LocalServiceModule = "OpenSim.Services.UserAccountService.dll:UserAccountService" - ; ConnectionString = "URI=file:userprofiles.db,version=3" + ConnectionString = "URI=file:userprofiles.db,version=3" + ;; These are for creating new accounts AuthenticationService = "OpenSim.Services.AuthenticationService.dll:PasswordAuthenticationService" PresenceService = "OpenSim.Services.PresenceService.dll:PresenceService" @@ -61,7 +62,7 @@ [FriendsService] LocalServiceModule = "OpenSim.Services.FriendsService.dll" - ; ConnectionString = "URI=file:friends.db,version=3" + ConnectionString = "URI=file:friends.db,version=3" [Friends] Connector = "OpenSim.Services.FriendsService.dll" From b72c2dc6e88fa2ea6bb97e0b32d0cdbb2ea78c4a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 5 Mar 2010 23:29:24 +0000 Subject: [PATCH 11/17] refactor: move user inventory side of RezSingleAttachment to module --- .../Avatar/Attachments/AttachmentsModule.cs | 30 +++++++++++++++++++ .../Interfaces/IAttachmentsModule.cs | 12 ++++++++ .../Framework/Scenes/Scene.Inventory.cs | 30 +------------------ 3 files changed, 43 insertions(+), 29 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 103a8135b1..0ea1f63168 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -137,5 +137,35 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return true; } + + /// + /// Update the user inventory to reflect an attachment + /// + /// + /// + /// + /// + /// + public UUID SetAttachmentInventoryStatus( + SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) + { + m_log.DebugFormat( + "[USER INVENTORY]: Updating inventory of {0} to show attachment of {1} (item ID {2})", + remoteClient.Name, att.Name, itemID); + + if (!att.IsDeleted) + AttachmentPt = att.RootPart.AttachmentPoint; + + ScenePresence presence; + if (m_scene.TryGetAvatar(remoteClient.AgentId, out presence)) + { + InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); + item = m_scene.InventoryService.GetItem(item); + + presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); + } + + return att.UUID; + } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index c965bcf8e7..5e5df4bcf5 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -28,6 +28,7 @@ using System; using OpenMetaverse; using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.Framework.Interfaces { @@ -45,5 +46,16 @@ namespace OpenSim.Region.Framework.Interfaces /// true if the object was successfully attached, false otherwise bool AttachObject( IClientAPI controllingClient, uint localID, uint attachPoint, Quaternion rot, Vector3 pos, bool silent); + + /// + /// Update the user inventory to the attachment of an item + /// + /// + /// + /// + /// + /// + UUID SetAttachmentInventoryStatus( + SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt); } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 474fba9e11..6a5dc56276 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1862,35 +1862,7 @@ namespace OpenSim.Region.Framework.Scenes return UUID.Zero; } - return RezSingleAttachment(att, remoteClient, itemID, AttachmentPt); - } - - /// - /// Update the user inventory to reflect an attachment - /// - /// - /// - /// - /// - /// - public UUID RezSingleAttachment(SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) - { - m_log.DebugFormat( - "[USER INVENTORY]: Updating inventory of {0} to show attachment of {1} (item ID {2})", - remoteClient.Name, att.Name, itemID); - - if (!att.IsDeleted) - AttachmentPt = att.RootPart.AttachmentPoint; - - ScenePresence presence; - if (TryGetAvatar(remoteClient.AgentId, out presence)) - { - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = InventoryService.GetItem(item); - - presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /*att.UUID*/); - } - return att.UUID; + return AttachmentsModule.SetAttachmentInventoryStatus(att, remoteClient, itemID, AttachmentPt); } public void RezMultipleAttachments(IClientAPI remoteClient, RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, From 71797af540bfa1ccb1ccfe856b42350844531607 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 5 Mar 2010 23:35:49 +0000 Subject: [PATCH 12/17] refactor: move another AttachObject method --- .../Avatar/Attachments/AttachmentsModule.cs | 47 ++++++++++++++++++- .../Framework/Scenes/Scene.Inventory.cs | 44 ----------------- 2 files changed, 46 insertions(+), 45 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 0ea1f63168..530a21ce70 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -112,7 +112,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments itemId = group.GetFromItemID(); } - m_scene.AttachObject(remoteClient, AttachmentPt, itemId, group); + SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemId, group); group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); @@ -167,5 +167,50 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return att.UUID; } + + /// + /// Update the user inventory to reflect an attachment + /// + /// + /// + /// + /// + public void SetAttachmentInventoryStatus( + IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att) + { +// m_log.DebugFormat( +// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", +// att.Name, remoteClient.Name, AttachmentPt, itemID); + + if (UUID.Zero == itemID) + { + m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error inventory item ID."); + return; + } + + if (0 == AttachmentPt) + { + m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error attachment point."); + return; + } + + if (null == att.RootPart) + { + m_log.Error("[SCENE INVENTORY]: Unable to save attachment for a prim without the rootpart!"); + return; + } + + ScenePresence presence; + if (m_scene.TryGetAvatar(remoteClient.AgentId, out presence)) + { + // XXYY!! + InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); + item = m_scene.InventoryService.GetItem(item); + presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */); + + if (m_scene.AvatarFactory != null) + m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } + } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6a5dc56276..bd3b433b5b 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1874,50 +1874,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// This registers the item as attached in a user's inventory - /// - /// - /// - /// - /// - public void AttachObject(IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att) - { -// m_log.DebugFormat( -// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", -// att.Name, remoteClient.Name, AttachmentPt, itemID); - - if (UUID.Zero == itemID) - { - m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error inventory item ID."); - return; - } - - if (0 == AttachmentPt) - { - m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error attachment point."); - return; - } - - if (null == att.RootPart) - { - m_log.Error("[SCENE INVENTORY]: Unable to save attachment for a prim without the rootpart!"); - return; - } - - ScenePresence presence; - if (TryGetAvatar(remoteClient.AgentId, out presence)) - { - // XXYY!! - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = InventoryService.GetItem(item); - presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID /* att.UUID */); - - if (m_AvatarFactory != null) - m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - } - public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) { SceneObjectPart part = GetSceneObjectPart(itemID); From 395f343498bc429c0360201991147c6e089b0730 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 6 Mar 2010 00:07:47 +0000 Subject: [PATCH 13/17] refactor: Move DetachSingleAttachmentToInv to region module need to rationalize method names later --- .../Avatar/Attachments/AttachmentsModule.cs | 71 +++++++++++++++---- .../Interfaces/IAttachmentsModule.cs | 11 +++ .../Framework/Scenes/Scene.Inventory.cs | 20 +----- OpenSim/Region/Framework/Scenes/Scene.cs | 18 ++--- OpenSim/Region/Framework/Scenes/SceneGraph.cs | 35 +-------- .../Shared/Api/Implementation/LSL_Api.cs | 5 +- 6 files changed, 82 insertions(+), 78 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 530a21ce70..d458364052 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using System.Reflection; using log4net; using Nini.Config; @@ -131,26 +132,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } else { - m_log.DebugFormat("[SCENE GRAPH]: AttachObject found no such scene object {0}", objectLocalID); + m_log.DebugFormat("[ATTACHMENTS MODULE]: AttachObject found no such scene object {0}", objectLocalID); return false; } return true; - } - - /// - /// Update the user inventory to reflect an attachment - /// - /// - /// - /// - /// - /// + } + public UUID SetAttachmentInventoryStatus( SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) { m_log.DebugFormat( - "[USER INVENTORY]: Updating inventory of {0} to show attachment of {1} (item ID {2})", + "[ATTACHMENTS MODULEY]: Updating inventory of {0} to show attachment of {1} (item ID {2})", remoteClient.Name, att.Name, itemID); if (!att.IsDeleted) @@ -184,19 +177,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (UUID.Zero == itemID) { - m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error inventory item ID."); + m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error inventory item ID."); return; } if (0 == AttachmentPt) { - m_log.Error("[SCENE INVENTORY]: Unable to save attachment. Error attachment point."); + m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment. Error attachment point."); return; } if (null == att.RootPart) { - m_log.Error("[SCENE INVENTORY]: Unable to save attachment for a prim without the rootpart!"); + m_log.Error("[ATTACHMENTS MODULE]: Unable to save attachment for a prim without the rootpart!"); return; } @@ -212,5 +205,53 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); } } + + public void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient) + { + ScenePresence presence; + if (m_scene.TryGetAvatar(remoteClient.AgentId, out presence)) + { + presence.Appearance.DetachAttachment(itemID); + + // Save avatar attachment information + if (m_scene.AvatarFactory != null) + { + m_log.Debug("[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", ItemID: " + itemID); + m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } + } + + DetachSingleAttachmentToInv(itemID, remoteClient); + } + + // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. + // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? + protected void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) + { + if (itemID == UUID.Zero) // If this happened, someone made a mistake.... + return; + + // We can NOT use the dictionries here, as we are looking + // for an entity by the fromAssetID, which is NOT the prim UUID + List detachEntities = m_scene.GetEntities(); + SceneObjectGroup group; + + foreach (EntityBase entity in detachEntities) + { + if (entity is SceneObjectGroup) + { + group = (SceneObjectGroup)entity; + if (group.GetFromItemID() == itemID) + { + m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); + group.DetachToInventoryPrep(); + m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); + m_scene.UpdateKnownItem(remoteClient, group,group.GetFromItemID(), group.OwnerID); + m_scene.DeleteSceneObject(group, false); + return; + } + } + } + } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index 5e5df4bcf5..367ff3da5f 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -57,5 +57,16 @@ namespace OpenSim.Region.Framework.Interfaces /// UUID SetAttachmentInventoryStatus( SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt); + + /// + /// Update the user inventory to show a detach. + /// + /// + /// A + /// + /// + /// A + /// + void ShowDetachInUserInventory(UUID itemID, IClientAPI remoteClient); } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index bd3b433b5b..dad0efd6fa 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1858,7 +1858,7 @@ namespace OpenSim.Region.Framework.Scenes if (att == null) { - DetachSingleAttachmentToInv(itemID, remoteClient); + AttachmentsModule.ShowDetachInUserInventory(itemID, remoteClient); return UUID.Zero; } @@ -1904,24 +1904,6 @@ namespace OpenSim.Region.Framework.Scenes SendAttachEvent(part.ParentGroup.LocalId, itemID, UUID.Zero); } - public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) - { - ScenePresence presence; - if (TryGetAvatar(remoteClient.AgentId, out presence)) - { - presence.Appearance.DetachAttachment(itemID); - - // Save avatar attachment information - if (m_AvatarFactory != null) - { - m_log.Info("[SCENE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", ItemID: " + itemID); - m_AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); - } - } - - m_sceneGraph.DetachSingleAttachmentToInv(itemID, remoteClient); - } - public void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) { EventManager.TriggerGetScriptRunning(controllingClient, objectID, itemID); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index c83132f97d..7c0375ec22 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -2646,10 +2646,12 @@ namespace OpenSim.Region.Framework.Scenes public virtual void SubscribeToClientAttachmentEvents(IClientAPI client) { client.OnRezSingleAttachmentFromInv += RezSingleAttachment; - client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; - client.OnDetachAttachmentIntoInv += DetachSingleAttachmentToInv; + client.OnRezMultipleAttachmentsFromInv += RezMultipleAttachments; client.OnObjectAttach += m_sceneGraph.AttachObject; client.OnObjectDetach += m_sceneGraph.DetachObject; + + if (AttachmentsModule != null) + client.OnDetachAttachmentIntoInv += AttachmentsModule.ShowDetachInUserInventory; } public virtual void SubscribeToClientTeleportEvents(IClientAPI client) @@ -2696,8 +2698,7 @@ namespace OpenSim.Region.Framework.Scenes } protected virtual void UnsubscribeToClientEvents(IClientAPI client) - { - + { } /// @@ -2719,7 +2720,6 @@ namespace OpenSim.Region.Framework.Scenes UnSubscribeToClientNetworkEvents(client); - // EventManager.TriggerOnNewClient(client); } @@ -2799,12 +2799,14 @@ namespace OpenSim.Region.Framework.Scenes } public virtual void UnSubscribeToClientAttachmentEvents(IClientAPI client) - { - client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; + { client.OnRezMultipleAttachmentsFromInv -= RezMultipleAttachments; - client.OnDetachAttachmentIntoInv -= DetachSingleAttachmentToInv; + client.OnRezSingleAttachmentFromInv -= RezSingleAttachment; client.OnObjectAttach -= m_sceneGraph.AttachObject; client.OnObjectDetach -= m_sceneGraph.DetachObject; + + if (AttachmentsModule != null) + client.OnDetachAttachmentIntoInv -= AttachmentsModule.ShowDetachInUserInventory; } public virtual void UnSubscribeToClientTeleportEvents(IClientAPI client) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 48744d71a9..380722d53b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -452,7 +452,7 @@ namespace OpenSim.Region.Framework.Scenes if (group != null) { //group.DetachToGround(); - m_parentScene.DetachSingleAttachmentToInv(group.GetFromItemID(), remoteClient); + m_parentScene.AttachmentsModule.ShowDetachInUserInventory(group.GetFromItemID(), remoteClient); } } @@ -574,39 +574,6 @@ namespace OpenSim.Region.Framework.Scenes return null; } - // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. - // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? - public void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) - { - if (itemID == UUID.Zero) // If this happened, someone made a mistake.... - return; - - // We can NOT use the dictionries here, as we are looking - // for an entity by the fromAssetID, which is NOT the prim UUID - // - List detachEntities = GetEntities(); - SceneObjectGroup group; - - foreach (EntityBase entity in detachEntities) - { - if (entity is SceneObjectGroup) - { - group = (SceneObjectGroup)entity; - if (group.GetFromItemID() == itemID) - { - m_parentScene.SendAttachEvent(group.LocalId, itemID, UUID.Zero); - group.DetachToInventoryPrep(); - m_log.Debug("[DETACH]: Saving attachpoint: " + - ((uint)group.GetAttachmentPoint()).ToString()); - m_parentScene.UpdateKnownItem(remoteClient, group, - group.GetFromItemID(), group.OwnerID); - m_parentScene.DeleteSceneObject(group, false); - return; - } - } - } - } - protected internal ScenePresence CreateAndAddChildScenePresence(IClientAPI client, AvatarAppearance appearance) { ScenePresence newAvatar = null; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0eee1471c1..8217248671 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -2931,8 +2931,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(m_host.OwnerID); - m_ScriptEngine.World.DetachSingleAttachmentToInv(itemID, - presence.ControllingClient); + IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; + if (attachmentsModule != null) + attachmentsModule.ShowDetachInUserInventory(itemID, presence.ControllingClient); } } From cde3c20ba3f4f506fc69d3db54171f88223219aa Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 5 Mar 2010 17:01:31 -0800 Subject: [PATCH 14/17] * Fixed an order of operations bug in CheckForSignificantMovement() that was causing a flood of child updates to neighbors on login * Removed an unnecessary call to the presence service --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 465e916f2c..4256be9af9 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2675,6 +2675,9 @@ namespace OpenSim.Region.Framework.Scenes if (Util.GetDistanceTo(AbsolutePosition, m_lastChildAgentUpdatePosition) >= Scene.ChildReprioritizationDistance || Util.GetDistanceTo(CameraPosition, m_lastChildAgentUpdateCamPosition) >= Scene.ChildReprioritizationDistance) { + m_lastChildAgentUpdatePosition = AbsolutePosition; + m_lastChildAgentUpdateCamPosition = CameraPosition; + ChildAgentDataUpdate cadu = new ChildAgentDataUpdate(); cadu.ActiveGroupID = UUID.Zero.Guid; cadu.AgentID = UUID.Guid; @@ -2683,8 +2686,6 @@ namespace OpenSim.Region.Framework.Scenes Vector3 tempCameraCenter = m_CameraCenter; cadu.cameraPosition = tempCameraCenter; cadu.drawdistance = m_DrawDistance; - if (m_scene.Permissions.IsGod(new UUID(cadu.AgentID))) - cadu.godlevel = m_godlevel; cadu.GroupAccess = 0; cadu.Position = AbsolutePosition; cadu.regionHandle = m_rootRegionHandle; @@ -2707,9 +2708,6 @@ namespace OpenSim.Region.Framework.Scenes agentpos.CopyFrom(cadu); m_scene.SendOutChildAgentUpdates(agentpos, this); - - m_lastChildAgentUpdatePosition = AbsolutePosition; - m_lastChildAgentUpdateCamPosition = CameraPosition; } } From 36afd0bfd1f80131a9f8dd72cc8b3eb71f060e02 Mon Sep 17 00:00:00 2001 From: John Hurliman Date: Fri, 5 Mar 2010 17:04:20 -0800 Subject: [PATCH 15/17] * Cache packed throttle data to avoid repeated allocations in CheckForSignificantMovement() * Removed a lock on "return m_neighbours.Count" in GetInaccurateNeighborCount(). Dictionary<>.Count by itself does not benefit from locking --- .../ClientStack/LindenUDP/LLUDPClient.cs | 33 +++++++++++++------ OpenSim/Region/Framework/Scenes/Scene.cs | 5 +-- 2 files changed, 24 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs index 55d9c9cd47..6232c48105 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLUDPClient.cs @@ -144,6 +144,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// A reference to the LLUDPServer that is managing this client private readonly LLUDPServer m_udpServer; + /// Caches packed throttle information + private byte[] m_packedThrottles; + private int m_defaultRTO = 3000; private int m_maxRTO = 60000; @@ -350,21 +353,31 @@ namespace OpenSim.Region.ClientStack.LindenUDP bucket = m_throttleCategories[(int)ThrottleOutPacketType.Texture]; bucket.DripRate = texture; bucket.MaxBurst = texture; + + // Reset the packed throttles cached data + m_packedThrottles = null; } public byte[] GetThrottlesPacked() { - byte[] data = new byte[7 * 4]; - int i = 0; + byte[] data = m_packedThrottles; - Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)(m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + - m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; - Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; + if (data == null) + { + data = new byte[7 * 4]; + int i = 0; + + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Resend].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Land].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Wind].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Cloud].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)(m_throttleCategories[(int)ThrottleOutPacketType.Task].DripRate) + + m_throttleCategories[(int)ThrottleOutPacketType.State].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Texture].DripRate), 0, data, i, 4); i += 4; + Buffer.BlockCopy(Utils.FloatToBytes((float)m_throttleCategories[(int)ThrottleOutPacketType.Asset].DripRate), 0, data, i, 4); i += 4; + + m_packedThrottles = data; + } return data; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index a880fe7d59..8f9663caef 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1132,10 +1132,7 @@ namespace OpenSim.Region.Framework.Scenes public int GetInaccurateNeighborCount() { - lock (m_neighbours) - { - return m_neighbours.Count; - } + return m_neighbours.Count; } // This is the method that shuts down the scene. From 5171464ac199f958a9a8a11664958260a88e863d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 5 Mar 2010 21:36:45 -0800 Subject: [PATCH 16/17] Justin, I must have been dyslexic when I wrote UserGridService as the name for it. GridUserService makes more sense; it's the user of the grid, "grid user". I changed it everywhere. --- .../{IUserGridData.cs => IGridUserData.cs} | 8 ++--- ...QLUserGridData.cs => MySQLGridUserData.cs} | 10 +++--- .../LocalGridUserServiceConnector.cs} | 32 +++++++++---------- .../GridUserServiceConnector.cs} | 4 +-- ...UserGridService.cs => IGridUserService.cs} | 12 +++---- ...{UserGridService.cs => GridUserService.cs} | 16 +++++----- ...dServiceBase.cs => GridUserServiceBase.cs} | 14 ++++---- 7 files changed, 48 insertions(+), 48 deletions(-) rename OpenSim/Data/{IUserGridData.cs => IGridUserData.cs} (91%) rename OpenSim/Data/MySQL/{MySQLUserGridData.cs => MySQLGridUserData.cs} (87%) rename OpenSim/Region/CoreModules/ServiceConnectorsOut/{UserGrid/LocalUserGridServiceConnector.cs => GridUser/LocalGridUserServiceConnector.cs} (75%) rename OpenSim/Services/Connectors/{UserGrid/UserGridServiceConnector.cs => GridUser/GridUserServiceConnector.cs} (95%) rename OpenSim/Services/Interfaces/{IUserGridService.cs => IGridUserService.cs} (91%) rename OpenSim/Services/UserAccountService/{UserGridService.cs => GridUserService.cs} (85%) rename OpenSim/Services/UserAccountService/{UserGridServiceBase.cs => GridUserServiceBase.cs} (88%) diff --git a/OpenSim/Data/IUserGridData.cs b/OpenSim/Data/IGridUserData.cs similarity index 91% rename from OpenSim/Data/IUserGridData.cs rename to OpenSim/Data/IGridUserData.cs index 6f7467ee96..abd2cef054 100644 --- a/OpenSim/Data/IUserGridData.cs +++ b/OpenSim/Data/IGridUserData.cs @@ -33,7 +33,7 @@ using OpenSim.Framework; namespace OpenSim.Data { // This MUST be a ref type! - public class UserGridData + public class GridUserData { public string UserID; public Dictionary Data; @@ -42,9 +42,9 @@ namespace OpenSim.Data /// /// An interface for connecting to the user grid datastore /// - public interface IUserGridData + public interface IGridUserData { - UserGridData GetUserGridData(string userID); - bool StoreUserGridData(UserGridData data); + GridUserData GetGridUserData(string userID); + bool StoreGridUserData(GridUserData data); } } \ No newline at end of file diff --git a/OpenSim/Data/MySQL/MySQLUserGridData.cs b/OpenSim/Data/MySQL/MySQLGridUserData.cs similarity index 87% rename from OpenSim/Data/MySQL/MySQLUserGridData.cs rename to OpenSim/Data/MySQL/MySQLGridUserData.cs index 7209b18226..15834d2ab7 100644 --- a/OpenSim/Data/MySQL/MySQLUserGridData.cs +++ b/OpenSim/Data/MySQL/MySQLGridUserData.cs @@ -40,15 +40,15 @@ namespace OpenSim.Data.MySQL /// /// A MySQL Interface for user grid data /// - public class MySQLUserGridData : MySQLGenericTableHandler, IUserGridData + public class MySQLGridUserData : MySQLGenericTableHandler, IGridUserData { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public MySQLUserGridData(string connectionString, string realm) : base(connectionString, realm, "UserGrid") {} + public MySQLGridUserData(string connectionString, string realm) : base(connectionString, realm, "UserGrid") {} - public UserGridData GetUserGridData(string userID) + public GridUserData GetGridUserData(string userID) { - UserGridData[] ret = Get("UserID", userID); + GridUserData[] ret = Get("UserID", userID); if (ret.Length == 0) return null; @@ -56,7 +56,7 @@ namespace OpenSim.Data.MySQL return ret[0]; } - public bool StoreUserGridData(UserGridData data) + public bool StoreGridUserData(GridUserData data) { return Store(data); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserGrid/LocalUserGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs similarity index 75% rename from OpenSim/Region/CoreModules/ServiceConnectorsOut/UserGrid/LocalUserGridServiceConnector.cs rename to OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs index f4309fead0..d5fae232d6 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserGrid/LocalUserGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs @@ -37,13 +37,13 @@ using OpenSim.Services.Interfaces; using OpenMetaverse; -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserGrid +namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser { - public class LocalUserGridServicesConnector : ISharedRegionModule, IUserGridService + public class LocalGridUserServicesConnector : ISharedRegionModule, IGridUserService { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private IUserGridService m_service; + private IGridUserService m_service; private bool m_Enabled = false; @@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserGrid public string Name { - get { return "LocalUserGridServicesConnector"; } + get { return "LocalGridUserServicesConnector"; } } public void Initialise(IConfigSource source) @@ -62,13 +62,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserGrid IConfig moduleConfig = source.Configs["Modules"]; if (moduleConfig != null) { - string name = moduleConfig.GetString("UserGridServices", ""); + string name = moduleConfig.GetString("GridUserServices", ""); if (name == Name) { - IConfig userConfig = source.Configs["UserGridService"]; + IConfig userConfig = source.Configs["GridUserService"]; if (userConfig == null) { - m_log.Error("[LOCAL USER GRID SERVICE CONNECTOR]: UserGridService missing from ini files"); + m_log.Error("[LOCAL GRID USER SERVICE CONNECTOR]: GridUserService missing from ini files"); return; } @@ -76,20 +76,20 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserGrid if (serviceDll == String.Empty) { - m_log.Error("[LOCAL USER GRID SERVICE CONNECTOR]: No LocalServiceModule named in section UserGridService"); + m_log.Error("[LOCAL GRID USER SERVICE CONNECTOR]: No LocalServiceModule named in section GridUserService"); return; } Object[] args = new Object[] { source }; - m_service = ServerUtils.LoadPlugin(serviceDll, args); + m_service = ServerUtils.LoadPlugin(serviceDll, args); if (m_service == null) { - m_log.Error("[LOCAL USER GRID SERVICE CONNECTOR]: Can't load UserGrid service"); + m_log.Error("[LOCAL GRID USER SERVICE CONNECTOR]: Can't load GridUser service"); return; } m_Enabled = true; - m_log.Info("[LOCAL USER GRID SERVICE CONNECTOR]: Local UserGrid connector enabled"); + m_log.Info("[LOCAL GRID USER SERVICE CONNECTOR]: Local GridUser connector enabled"); } } } @@ -111,7 +111,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserGrid if (!m_Enabled) return; - scene.RegisterModuleInterface(m_service); + scene.RegisterModuleInterface(m_service); } public void RemoveRegion(Scene scene) @@ -126,14 +126,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserGrid return; } - public UserGridInfo GetUserGridInfo(string userID) + public GridUserInfo GetGridUserInfo(string userID) { - return m_service.GetUserGridInfo(userID); + return m_service.GetGridUserInfo(userID); } - public bool StoreUserGridInfo(UserGridInfo info) + public bool StoreGridUserInfo(GridUserInfo info) { - return m_service.StoreUserGridInfo(info); + return m_service.StoreGridUserInfo(info); } } } \ No newline at end of file diff --git a/OpenSim/Services/Connectors/UserGrid/UserGridServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs similarity index 95% rename from OpenSim/Services/Connectors/UserGrid/UserGridServiceConnector.cs rename to OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs index 3aa8940e8a..ce88236ae3 100644 --- a/OpenSim/Services/Connectors/UserGrid/UserGridServiceConnector.cs +++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs @@ -29,9 +29,9 @@ using System; namespace OpenSim.Services.Connectors { - public class UserGridServiceConnector + public class GridUserServiceConnector { - public UserGridServiceConnector() + public GridUserServiceConnector() { } } diff --git a/OpenSim/Services/Interfaces/IUserGridService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs similarity index 91% rename from OpenSim/Services/Interfaces/IUserGridService.cs rename to OpenSim/Services/Interfaces/IGridUserService.cs index 50134e0c6c..a7c2c6f014 100644 --- a/OpenSim/Services/Interfaces/IUserGridService.cs +++ b/OpenSim/Services/Interfaces/IGridUserService.cs @@ -34,16 +34,16 @@ namespace OpenSim.Services.Interfaces /// /// Records user information specific to a grid but which is not part of a user's account. /// - public class UserGridInfo + public class GridUserInfo { public string UserID; public UUID HomeRegionID; public Vector3 HomePosition; public Vector3 HomeLookAt; - public UserGridInfo() {} + public GridUserInfo() {} - public UserGridInfo(Dictionary kvp) + public GridUserInfo(Dictionary kvp) { if (kvp.ContainsKey("UserID")) UserID = kvp["UserID"].ToString(); @@ -67,9 +67,9 @@ namespace OpenSim.Services.Interfaces } } - public interface IUserGridService + public interface IGridUserService { - UserGridInfo GetUserGridInfo(string userID); - bool StoreUserGridInfo(UserGridInfo info); + GridUserInfo GetGridUserInfo(string userID); + bool StoreGridUserInfo(GridUserInfo info); } } \ No newline at end of file diff --git a/OpenSim/Services/UserAccountService/UserGridService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs similarity index 85% rename from OpenSim/Services/UserAccountService/UserGridService.cs rename to OpenSim/Services/UserAccountService/GridUserService.cs index 2d28b331d2..36cce758ce 100644 --- a/OpenSim/Services/UserAccountService/UserGridService.cs +++ b/OpenSim/Services/UserAccountService/GridUserService.cs @@ -39,20 +39,20 @@ using log4net; namespace OpenSim.Services.UserAccountService { - public class UserGridService : UserGridServiceBase, IUserGridService + public class GridUserService : GridUserServiceBase, IGridUserService { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - public UserGridService(IConfigSource config) : base(config) + public GridUserService(IConfigSource config) : base(config) { m_log.Debug("[USER GRID SERVICE]: Starting user grid service"); } - public UserGridInfo GetUserGridInfo(string userID) + public GridUserInfo GetGridUserInfo(string userID) { - UserGridData d = m_Database.GetUserGridData(userID); + GridUserData d = m_Database.GetGridUserData(userID); - UserGridInfo info = new UserGridInfo(); + GridUserInfo info = new GridUserInfo(); info.UserID = d.UserID; info.HomeRegionID = new UUID(d.Data["HomeRegionID"]); info.HomePosition = Vector3.Parse(d.Data["HomePosition"]); @@ -61,16 +61,16 @@ namespace OpenSim.Services.UserAccountService return info; } - public bool StoreUserGridInfo(UserGridInfo info) + public bool StoreGridUserInfo(GridUserInfo info) { - UserGridData d = new UserGridData(); + GridUserData d = new GridUserData(); d.Data["UserID"] = info.UserID; d.Data["HomeRegionID"] = info.HomeRegionID.ToString(); d.Data["HomePosition"] = info.HomePosition.ToString(); d.Data["HomeLookAt"] = info.HomeLookAt.ToString(); - return m_Database.StoreUserGridData(d); + return m_Database.StoreGridUserData(d); } } } \ No newline at end of file diff --git a/OpenSim/Services/UserAccountService/UserGridServiceBase.cs b/OpenSim/Services/UserAccountService/GridUserServiceBase.cs similarity index 88% rename from OpenSim/Services/UserAccountService/UserGridServiceBase.cs rename to OpenSim/Services/UserAccountService/GridUserServiceBase.cs index 80aaa49a64..990cb63dcf 100644 --- a/OpenSim/Services/UserAccountService/UserGridServiceBase.cs +++ b/OpenSim/Services/UserAccountService/GridUserServiceBase.cs @@ -35,15 +35,15 @@ using OpenSim.Services.Base; namespace OpenSim.Services.UserAccountService { - public class UserGridServiceBase : ServiceBase + public class GridUserServiceBase : ServiceBase { - protected IUserGridData m_Database = null; + protected IGridUserData m_Database = null; - public UserGridServiceBase(IConfigSource config) : base(config) + public GridUserServiceBase(IConfigSource config) : base(config) { string dllName = String.Empty; string connString = String.Empty; - string realm = "UserGrid"; + string realm = "GridUser"; // // Try reading the [DatabaseService] section, if it exists @@ -58,9 +58,9 @@ namespace OpenSim.Services.UserAccountService } // - // [PresenceService] section overrides [DatabaseService], if it exists + // [GridUsetService] section overrides [DatabaseService], if it exists // - IConfig presenceConfig = config.Configs["PresenceService"]; + IConfig presenceConfig = config.Configs["GridUserService"]; if (presenceConfig != null) { dllName = presenceConfig.GetString("StorageProvider", dllName); @@ -74,7 +74,7 @@ namespace OpenSim.Services.UserAccountService if (dllName.Equals(String.Empty)) throw new Exception("No StorageProvider configured"); - m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); + m_Database = LoadPlugin(dllName, new Object[] { connString, realm }); if (m_Database == null) throw new Exception("Could not find a storage interface in the given module " + dllName); } From c0bc25059c932bbef41b2fbe2f319163407aed1b Mon Sep 17 00:00:00 2001 From: unknown Date: Sat, 6 Mar 2010 00:56:55 -0600 Subject: [PATCH 17/17] - implementing server 1.38 functions Signed-off-by: Melanie --- .../Framework/Scenes/SceneObjectPart.cs | 5 + .../Shared/Api/Implementation/LSL_Api.cs | 99 +++++++++++++++++-- .../Shared/Api/Interface/ILSL_Api.cs | 4 + .../Shared/Api/Runtime/LSL_Constants.cs | 1 + .../Shared/Api/Runtime/LSL_Stub.cs | 20 ++++ 5 files changed, 119 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 10a186e164..472938209e 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -4707,5 +4707,10 @@ namespace OpenSim.Region.Framework.Scenes m_log.Error("[Physics] " + ex); } } + + public Color4 GetTextColor() + { + return new Color4((byte)Color.R, (byte)Color.G, (byte)Color.B, (byte)(0xFF - Color.A)); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index dc4249cc4e..f1241a1957 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -5406,12 +5406,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetTextureAnim(int mode, int face, int sizex, int sizey, double start, double length, double rate) { m_host.AddScriptLPS(1); + + SetTextureAnim(m_host, mode, face, sizex, sizey, start, length, rate); + } + + public void llSetLinkTextureAnim(int linknumber, int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + foreach (var part in parts) + { + SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); + } + } + + private void SetTextureAnim(SceneObjectPart part, int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + Primitive.TextureAnimation pTexAnim = new Primitive.TextureAnimation(); pTexAnim.Flags = (Primitive.TextureAnimMode)mode; //ALL_SIDES if (face == ScriptBaseClass.ALL_SIDES) - face = 255; + face = 255; pTexAnim.Face = (uint)face; pTexAnim.Length = (float)length; @@ -5420,9 +5439,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api pTexAnim.SizeY = (uint)sizey; pTexAnim.Start = (float)start; - m_host.AddTextureAnimation(pTexAnim); - m_host.SendFullUpdateToAllClients(); - m_host.ParentGroup.HasGroupChanged = true; + part.AddTextureAnimation(pTexAnim); + part.SendFullUpdateToAllClients(); + part.ParentGroup.HasGroupChanged = true; } public void llTriggerSoundLimited(string sound, double volume, LSL_Vector top_north_east, @@ -5819,13 +5838,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return ps; } + public void llLinkParticleSystem(int linknumber, LSL_List rules) + { + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + foreach (var part in parts) + { + SetParticleSystem(part, rules); + } + } + public void llParticleSystem(LSL_List rules) { m_host.AddScriptLPS(1); + SetParticleSystem(m_host, rules); + } + + private void SetParticleSystem(SceneObjectPart part, LSL_List rules) { + + if (rules.Length == 0) { - m_host.RemoveParticleSystem(); - m_host.ParentGroup.HasGroupChanged = true; + part.RemoveParticleSystem(); + part.ParentGroup.HasGroupChanged = true; } else { @@ -5936,7 +5973,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - prules.Target = m_host.UUID; + prules.Target = part.UUID; } break; @@ -5962,10 +5999,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } prules.CRC = 1; - m_host.AddNewParticleSystem(prules); - m_host.ParentGroup.HasGroupChanged = true; + part.AddNewParticleSystem(prules); + part.ParentGroup.HasGroupChanged = true; } - m_host.SendFullUpdateToAllClients(); + part.SendFullUpdateToAllClients(); } public void llGroundRepel(double height, int water, double tau) @@ -6759,6 +6796,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api SetPrimParams(part, rules); } + public void llSetLinkPrimitiveParamsFast(int linknumber, LSL_List rules) + { + llSetLinkPrimitiveParams(linknumber, rules); + } + protected void SetPrimParams(SceneObjectPart part, LSL_List rules) { int idx = 0; @@ -7114,6 +7156,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api face = rules.GetLSLIntegerItem(idx++); int style = rules.GetLSLIntegerItem(idx++); SetTexGen(part, face, style); + break; + case (int)ScriptBaseClass.PRIM_TEXT: + if (remain < 3) + return; + string primText = rules.GetLSLStringItem(idx++); + LSL_Vector primTextColor = rules.GetVector3Item(idx++); + LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); + Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), + Util.Clip((float)primTextColor.y, 0.0f, 1.0f), + Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); + part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); + break; } } @@ -7358,6 +7412,23 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return GetLinkPrimitiveParams(m_host, rules); } + public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) + { + m_host.AddScriptLPS(1); + + List parts = GetLinkParts(linknumber); + + LSL_List res = new LSL_List(); + + foreach (var part in parts) + { + LSL_List partRes = GetLinkPrimitiveParams(part, rules); + res += partRes; + } + + return res; + } + public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) { LSL_List res = new LSL_List(); @@ -7635,6 +7706,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api res.Add(new LSL_Float(0)); break; + case (int)ScriptBaseClass.PRIM_TEXT: + Color4 textColor = part.GetTextColor(); + res.Add(part.Text); + res.Add(new LSL_Vector(textColor.R, + textColor.G, + textColor.B)); + res.Add(new LSL_Float(textColor.A)); + break; } } return res; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index a74e8dadc2..7ab04a3cbb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -135,6 +135,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Key llGetLinkKey(int linknum); LSL_String llGetLinkName(int linknum); LSL_Integer llGetLinkNumber(); + LSL_List llGetLinkPrimitiveParams(int linknum, LSL_List rules); LSL_Integer llGetListEntryType(LSL_List src, int index); LSL_Integer llGetListLength(LSL_List src); LSL_Vector llGetLocalPos(); @@ -206,6 +207,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llInstantMessage(string user, string message); LSL_String llIntegerToBase64(int number); LSL_String llKey2Name(string id); + void llLinkParticleSystem(int linknum, LSL_List rules); LSL_String llList2CSV(LSL_List src); LSL_Float llList2Float(LSL_List src, int index); LSL_Integer llList2Integer(LSL_List src, int index); @@ -322,6 +324,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llSetLinkColor(int linknumber, LSL_Vector color, int face); void llSetLinkPrimitiveParams(int linknumber, LSL_List rules); void llSetLinkTexture(int linknumber, string texture, int face); + void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate); void llSetLocalRot(LSL_Rotation rot); void llSetObjectDesc(string desc); void llSetObjectName(string name); @@ -330,6 +333,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llSetPayPrice(int price, LSL_List quick_pay_buttons); void llSetPos(LSL_Vector pos); void llSetPrimitiveParams(LSL_List rules); + void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules); void llSetPrimURL(string url); void llSetRemoteScriptAccessPin(int pin); void llSetRot(LSL_Rotation rot); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 7cf82b275e..ee35fa4b6a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -313,6 +313,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_CAST_SHADOWS = 24; // Not implemented, here for completeness sake public const int PRIM_POINT_LIGHT = 23; // Huh? public const int PRIM_GLOW = 25; + public const int PRIM_TEXT = 26; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index a28e97bea6..3339995f66 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -674,6 +674,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llGetPrimitiveParams(rules); } + public LSL_List llGetLinkPrimitiveParams(int linknum, LSL_List rules) + { + return m_LSL_Functions.llGetLinkPrimitiveParams(linknum, rules); + } + public LSL_Integer llGetRegionAgentCount() { return m_LSL_Functions.llGetRegionAgentCount(); @@ -889,6 +894,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llKey2Name(id); } + public void llLinkParticleSystem(int linknum, LSL_List rules) + { + m_LSL_Functions.llLinkParticleSystem(linknum, rules); + } + public LSL_String llList2CSV(LSL_List src) { return m_LSL_Functions.llList2CSV(src); @@ -1468,6 +1478,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llSetLinkTexture(linknumber, texture, face); } + public void llSetLinkTextureAnim(int linknum, int mode, int face, int sizex, int sizey, double start, double length, double rate) + { + m_LSL_Functions.llSetLinkTextureAnim(linknum, mode, face, sizex, sizey, start, length, rate); + } + public void llSetLocalRot(LSL_Rotation rot) { m_LSL_Functions.llSetLocalRot(rot); @@ -1508,6 +1523,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llSetPrimitiveParams(rules); } + public void llSetLinkPrimitiveParamsFast(int linknum, LSL_List rules) + { + m_LSL_Functions.llSetLinkPrimitiveParamsFast(linknum, rules); + } + public void llSetPrimURL(string url) { m_LSL_Functions.llSetPrimURL(url);