diff --git a/.nant/local.include b/.nant/local.include index a9ba17d8e8..4fa3e4df4b 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -38,52 +38,8 @@ - - - - @@ -153,116 +109,17 @@ - - - - - - - - - - - - - - + + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + @@ -275,15 +132,12 @@ if="${int::parse(hasnunit2)==0}" /> - - - @@ -356,36 +210,7 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/BUILDING.txt b/BUILDING.txt index 0fb68cb5ba..12e5ea53cf 100644 --- a/BUILDING.txt +++ b/BUILDING.txt @@ -17,13 +17,22 @@ Prereqs: * On some Linux distributions you may need to install additional packages. See http://opensimulator.org/wiki/Dependencies for more information. + * May also use xbuild (included in mono distributions) + * May use Monodevelop, a cross-platform IDE + From the distribution type: * ./runprebuild.sh - * nant + * nant (or xbuild) * cd bin * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include * run mono OpenSim.exe +=== Using Monodevelop === + +From the distribution type: + * ./runprebuild.sh + * type monodevelop OpenSim.sln + === References === Helpful resources: diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 7106e6aded..7f1a0ed5a6 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -257,17 +257,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController { m_log.Info("[RADMIN]: Request to restart Region."); - CheckStringParameters(requestData, responseData, new string[] {"regionID"}); + CheckRegionParams(requestData, responseData); - UUID regionID = new UUID((string) requestData["regionID"]); - - Scene rebootedScene; + Scene rebootedScene = null; + GetSceneFromRegionParams(requestData, responseData, out rebootedScene); responseData["success"] = false; responseData["accepted"] = true; - if (!m_application.SceneManager.TryGetScene(regionID, out rebootedScene)) - throw new Exception("region not found"); - responseData["rebooting"] = true; IRestartModule restartModule = rebootedScene.RequestModuleInterface(); @@ -329,14 +325,15 @@ namespace OpenSim.ApplicationPlugins.RemoteController // } CheckStringParameters(requestData, responseData, new string[] {"filename", "regionid"}); + CheckRegionParams(requestData, responseData); - string file = (string) requestData["filename"]; - UUID regionID = (UUID) (string) requestData["regionid"]; - m_log.InfoFormat("[RADMIN]: Terrain Loading: {0}", file); + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); + string file = (string)requestData["filename"]; responseData["accepted"] = true; - LoadHeightmap(file, regionID); + LoadHeightmap(file, scene.RegionInfo.RegionID); responseData["success"] = true; @@ -353,18 +350,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController // m_log.DebugFormat("[RADMIN]: Save Terrain: XmlRpc {0}", request.ToString()); CheckStringParameters(requestData, responseData, new string[] { "filename", "regionid" }); + CheckRegionParams(requestData, responseData); + + Scene region = null; + GetSceneFromRegionParams(requestData, responseData, out region); string file = (string)requestData["filename"]; - UUID regionID = (UUID)(string)requestData["regionid"]; m_log.InfoFormat("[RADMIN]: Terrain Saving: {0}", file); responseData["accepted"] = true; - Scene region = null; - - if (!m_application.SceneManager.TryGetScene(regionID, out region)) - throw new Exception("1: unable to get a scene with that name"); - ITerrainModule terrainModule = region.RequestModuleInterface(); if (null == terrainModule) throw new Exception("terrain module not available"); @@ -732,7 +727,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController responseData["success"] = true; responseData["region_name"] = region.RegionName; - responseData["region_uuid"] = region.RegionID.ToString(); + responseData["region_id"] = region.RegionID.ToString(); + responseData["region_uuid"] = region.RegionID.ToString(); //Deprecate July 2012 m_log.Info("[RADMIN]: CreateRegion: request complete"); } @@ -774,16 +770,16 @@ namespace OpenSim.ApplicationPlugins.RemoteController lock (m_requestLock) { CheckStringParameters(requestData, responseData, new string[] {"region_name"}); + CheckRegionParams(requestData, responseData); Scene scene = null; - string regionName = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(regionName, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); + GetSceneFromRegionParams(requestData, responseData, out scene); m_application.RemoveRegion(scene, true); responseData["success"] = true; - responseData["region_name"] = regionName; + responseData["region_name"] = scene.RegionInfo.RegionName; + responseData["region_id"] = scene.RegionInfo.RegionID; m_log.Info("[RADMIN]: DeleteRegion: request complete"); } @@ -823,44 +819,21 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable responseData = (Hashtable)response.Value; Hashtable requestData = (Hashtable)request.Params[0]; - Scene scene = null; lock (m_requestLock) { - if (requestData.ContainsKey("region_id") && - !String.IsNullOrEmpty((string) requestData["region_id"])) - { - // Region specified by UUID - UUID regionID = (UUID) (string) requestData["region_id"]; - if (!m_application.SceneManager.TryGetScene(regionID, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionID)); + CheckRegionParams(requestData, responseData); - m_application.CloseRegion(scene); + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); - responseData["success"] = true; - responseData["region_id"] = regionID; + m_application.CloseRegion(scene); - response.Value = responseData; - } - else if ( - requestData.ContainsKey("region_name") - && !String.IsNullOrEmpty((string) requestData["region_name"])) - { - // Region specified by name + responseData["success"] = true; + responseData["region_name"] = scene.RegionInfo.RegionName; + responseData["region_id"] = scene.RegionInfo.RegionID; - string regionName = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(regionName, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); - - m_application.CloseRegion(scene); - - responseData["success"] = true; - responseData["region_name"] = regionName; - } - else - { - throw new Exception("no region specified"); - } + response.Value = responseData; m_log.Info("[RADMIN]: CloseRegion: request complete"); } @@ -907,12 +880,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController lock (m_requestLock) { - CheckStringParameters(requestData, responseData, new string[] {"region_name"}); + CheckRegionParams(requestData, responseData); Scene scene = null; - string regionName = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(regionName, out scene)) - throw new Exception(String.Format("region \"{0}\" does not exist", regionName)); + GetSceneFromRegionParams(requestData, responseData, out scene); // Modify access scene.RegionInfo.EstateSettings.PublicAccess = @@ -942,7 +913,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController } responseData["success"] = true; - responseData["region_name"] = regionName; + responseData["region_name"] = scene.RegionInfo.RegionName; + responseData["region_id"] = scene.RegionInfo.RegionID; m_log.Info("[RADMIN]: ModifyRegion: request complete"); } @@ -1338,22 +1310,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController try { CheckStringParameters(requestData, responseData, new string[] {"filename"}); + CheckRegionParams(requestData, responseData); + + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); string filename = (string) requestData["filename"]; - Scene scene = null; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TryGetScene(region_uuid, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(region_name, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - } - else throw new Exception("neither region_name nor region_uuid given"); bool mergeOar = false; bool skipAssets = false; @@ -1434,22 +1396,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController try { CheckStringParameters(requestData, responseData, new string[] {"filename"}); + CheckRegionParams(requestData, responseData); + + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); string filename = (string)requestData["filename"]; - Scene scene = null; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TryGetScene(region_uuid, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TryGetScene(region_name, out scene)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - } - else throw new Exception("neither region_name nor region_uuid given"); Dictionary options = new Dictionary(); @@ -1521,25 +1473,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController try { CheckStringParameters(requestData, responseData, new string[] {"filename"}); + CheckRegionParams(requestData, responseData); + + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); string filename = (string) requestData["filename"]; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); responseData["switched"] = true; @@ -1587,23 +1526,12 @@ namespace OpenSim.ApplicationPlugins.RemoteController try { CheckStringParameters(requestData, responseData, new string[] {"filename"}); + CheckRegionParams(requestData, responseData); + + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); string filename = (string) requestData["filename"]; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); responseData["switched"] = true; @@ -1647,33 +1575,15 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable responseData = (Hashtable)response.Value; Hashtable requestData = (Hashtable)request.Params[0]; - responseData["success"] = true; + CheckRegionParams(requestData, responseData); - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else - { - throw new Exception("neither region_name nor region_uuid given"); - } - - Scene scene = m_application.SceneManager.CurrentScene; int health = scene.GetHealth(); responseData["health"] = health; + responseData["success"] = true; m_log.Info("[RADMIN]: Query XML Administrator Request complete"); } @@ -1700,24 +1610,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController responseData["success"] = true; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); + CheckRegionParams(requestData, responseData); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); - Scene scene = m_application.SceneManager.CurrentScene; scene.RegionInfo.EstateSettings.EstateAccess = new UUID[]{}; if (scene.RegionInfo.Persistent) @@ -1733,32 +1630,17 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable responseData = (Hashtable)response.Value; Hashtable requestData = (Hashtable)request.Params[0]; - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else - { - throw new Exception("neither region_name nor region_uuid given"); - } + CheckRegionParams(requestData, responseData); + + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); int addedUsers = 0; if (requestData.Contains("users")) { - UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; - IUserAccountService userService = m_application.SceneManager.CurrentOrFirstScene.UserAccountService; - Scene scene = m_application.SceneManager.CurrentScene; + UUID scopeID = scene.RegionInfo.ScopeID; + IUserAccountService userService = scene.UserAccountService; Hashtable users = (Hashtable) requestData["users"]; List uuids = new List(); foreach (string name in users.Values) @@ -1797,32 +1679,18 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable responseData = (Hashtable)response.Value; Hashtable requestData = (Hashtable)request.Params[0]; - responseData["success"] = true; + CheckRegionParams(requestData, responseData); - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); int removedUsers = 0; if (requestData.Contains("users")) { - UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; - IUserAccountService userService = m_application.SceneManager.CurrentOrFirstScene.UserAccountService; + UUID scopeID = scene.RegionInfo.ScopeID; + IUserAccountService userService = scene.UserAccountService; //UserProfileCacheService ups = m_application.CommunicationsManager.UserProfileCacheService; - Scene scene = m_application.SceneManager.CurrentScene; Hashtable users = (Hashtable) requestData["users"]; List uuids = new List(); foreach (string name in users.Values) @@ -1849,6 +1717,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } responseData["removed"] = removedUsers; + responseData["success"] = true; m_log.Info("[RADMIN]: Access List Remove Request complete"); } @@ -1860,32 +1729,18 @@ namespace OpenSim.ApplicationPlugins.RemoteController Hashtable responseData = (Hashtable)response.Value; Hashtable requestData = (Hashtable)request.Params[0]; - responseData["success"] = true; + CheckRegionParams(requestData, responseData); - if (requestData.Contains("region_uuid")) - { - UUID region_uuid = (UUID) (string) requestData["region_uuid"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_uuid)) - throw new Exception(String.Format("failed to switch to region {0}", region_uuid.ToString())); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_uuid.ToString()); - } - else if (requestData.Contains("region_name")) - { - string region_name = (string) requestData["region_name"]; - if (!m_application.SceneManager.TrySetCurrentScene(region_name)) - throw new Exception(String.Format("failed to switch to region {0}", region_name)); - m_log.InfoFormat("[RADMIN]: Switched to region {0}", region_name); - } - else throw new Exception("neither region_name nor region_uuid given"); + Scene scene = null; + GetSceneFromRegionParams(requestData, responseData, out scene); - Scene scene = m_application.SceneManager.CurrentScene; UUID[] accessControlList = scene.RegionInfo.EstateSettings.EstateAccess; Hashtable users = new Hashtable(); foreach (UUID user in accessControlList) { - UUID scopeID = m_application.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; - UserAccount account = m_application.SceneManager.CurrentOrFirstScene.UserAccountService.GetUserAccount(scopeID, user); + UUID scopeID = scene.RegionInfo.ScopeID; + UserAccount account = scene.UserAccountService.GetUserAccount(scopeID, user); if (account != null) { users[user.ToString()] = account.FirstName + " " + account.LastName; @@ -1893,6 +1748,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController } responseData["users"] = users; + responseData["success"] = true; m_log.Info("[RADMIN]: Access List List Request complete"); } @@ -2010,6 +1866,126 @@ namespace OpenSim.ApplicationPlugins.RemoteController } } + private void CheckRegionParams(Hashtable requestData, Hashtable responseData) + { + //Checks if region parameters exist and gives exeption if no parameters are given + if ((requestData.ContainsKey("region_id") && !String.IsNullOrEmpty((string)requestData["region_id"])) || + (requestData.ContainsKey("region_name") && !String.IsNullOrEmpty((string)requestData["region_name"]))) + { + return; + } + #region Deprecate July 2012 + //region_ID, regionid, region_uuid will be deprecated in July 2012!!!!!! + else if (requestData.ContainsKey("regionid") && + !String.IsNullOrEmpty((string)requestData["regionid"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead"); + } + else if (requestData.ContainsKey("region_ID") && + !String.IsNullOrEmpty((string)requestData["region_ID"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead"); + } + else if (requestData.ContainsKey("regionID") && + !String.IsNullOrEmpty((string)requestData["regionID"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead"); + } + else if (requestData.ContainsKey("region_uuid") && + !String.IsNullOrEmpty((string)requestData["region_uuid"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead"); + } + #endregion + else + { + responseData["accepted"] = false; + throw new Exception("no region_name or region_id given"); + } + } + + private void GetSceneFromRegionParams(Hashtable requestData, Hashtable responseData, out Scene scene) + { + scene = null; + + if (requestData.ContainsKey("region_id") && + !String.IsNullOrEmpty((string)requestData["region_id"])) + { + UUID regionID = (UUID)(string)requestData["region_id"]; + if (!m_application.SceneManager.TryGetScene(regionID, out scene)) + { + responseData["error"] = String.Format("Region ID {0} not found", regionID); + throw new Exception(String.Format("Region ID {0} not found", regionID)); + } + } + #region Deprecate July 2012 + else if (requestData.ContainsKey("regionid") && + !String.IsNullOrEmpty((string)requestData["regionid"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter regionid will be deprecated as of July 2012. Use region_id instead"); + + UUID regionID = (UUID)(string)requestData["regionid"]; + if (!m_application.SceneManager.TryGetScene(regionID, out scene)) + { + responseData["error"] = String.Format("Region ID {0} not found", regionID); + throw new Exception(String.Format("Region ID {0} not found", regionID)); + } + } + else if (requestData.ContainsKey("region_ID") && + !String.IsNullOrEmpty((string)requestData["region_ID"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter region_ID will be deprecated as of July 2012. Use region_id instead"); + + UUID regionID = (UUID)(string)requestData["region_ID"]; + if (!m_application.SceneManager.TryGetScene(regionID, out scene)) + { + responseData["error"] = String.Format("Region ID {0} not found", regionID); + throw new Exception(String.Format("Region ID {0} not found", regionID)); + } + } + else if (requestData.ContainsKey("regionID") && + !String.IsNullOrEmpty((string)requestData["regionID"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter regionID will be deprecated as of July 2012. Use region_id instead"); + + UUID regionID = (UUID)(string)requestData["regionID"]; + if (!m_application.SceneManager.TryGetScene(regionID, out scene)) + { + responseData["error"] = String.Format("Region ID {0} not found", regionID); + throw new Exception(String.Format("Region ID {0} not found", regionID)); + } + } + else if (requestData.ContainsKey("region_uuid") && + !String.IsNullOrEmpty((string)requestData["region_uuid"])) + { + m_log.WarnFormat("[RADMIN]: Use of parameter region_uuid will be deprecated as of July 2012. Use region_id instead"); + + UUID regionID = (UUID)(string)requestData["region_uuid"]; + if (!m_application.SceneManager.TryGetScene(regionID, out scene)) + { + responseData["error"] = String.Format("Region ID {0} not found", regionID); + throw new Exception(String.Format("Region ID {0} not found", regionID)); + } + } + #endregion + else if (requestData.ContainsKey("region_name") && + !String.IsNullOrEmpty((string)requestData["region_name"])) + { + string regionName = (string)requestData["region_name"]; + if (!m_application.SceneManager.TryGetScene(regionName, out scene)) + { + responseData["error"] = String.Format("Region {0} not found", regionName); + throw new Exception(String.Format("Region {0} not found", regionName)); + } + } + else + { + responseData["error"] = "no region_name or region_id given"; + throw new Exception("no region_name or region_id given"); + } + return; + } + private bool GetBoolean(Hashtable requestData, string tag, bool defaultValue) { // If an access value has been provided, apply it. diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs new file mode 100644 index 0000000000..717a097c70 --- /dev/null +++ b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2Handler.cs @@ -0,0 +1,148 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OSDArray = OpenMetaverse.StructuredData.OSDArray; +using OSDMap = OpenMetaverse.StructuredData.OSDMap; + +namespace OpenSim.Capabilities.Handlers +{ + public class FetchInventory2Handler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private IInventoryService m_inventoryService; + + public FetchInventory2Handler(IInventoryService invService) + { + m_inventoryService = invService; + } + + public string FetchInventoryRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { +// m_log.DebugFormat("[FETCH INVENTORY HANDLER]: Received FetchInventory capabilty request"); + + OSDMap requestmap = (OSDMap)OSDParser.DeserializeLLSDXml(Utils.StringToBytes(request)); + OSDArray itemsRequested = (OSDArray)requestmap["items"]; + + string reply; + LLSDFetchInventory llsdReply = new LLSDFetchInventory(); + + foreach (OSDMap osdItemId in itemsRequested) + { + UUID itemId = osdItemId["item_id"].AsUUID(); + + InventoryItemBase item = m_inventoryService.GetItem(new InventoryItemBase(itemId)); + + if (item != null) + { + // We don't know the agent that this request belongs to so we'll use the agent id of the item + // which will be the same for all items. + llsdReply.agent_id = item.Owner; + + llsdReply.items.Array.Add(ConvertInventoryItem(item)); + } + } + + reply = LLSDHelpers.SerialiseLLSDReply(llsdReply); + + return reply; + } + + /// + /// Convert an internal inventory item object into an LLSD object. + /// + /// + /// + private LLSDInventoryItem ConvertInventoryItem(InventoryItemBase invItem) + { + LLSDInventoryItem llsdItem = new LLSDInventoryItem(); + llsdItem.asset_id = invItem.AssetID; + llsdItem.created_at = invItem.CreationDate; + llsdItem.desc = invItem.Description; + llsdItem.flags = (int)invItem.Flags; + llsdItem.item_id = invItem.ID; + llsdItem.name = invItem.Name; + llsdItem.parent_id = invItem.Folder; + + try + { + llsdItem.type = Utils.AssetTypeToString((AssetType)invItem.AssetType); + llsdItem.inv_type = Utils.InventoryTypeToString((InventoryType)invItem.InvType); + } + catch (Exception e) + { + m_log.ErrorFormat( + "[WEB FETCH INV DESC HANDLER]: Problem setting asset {0} inventory {1} types while converting inventory item {2}: {3}", + invItem.AssetType, invItem.InvType, invItem.Name, e.Message); + } + + llsdItem.permissions = new LLSDPermissions(); + llsdItem.permissions.creator_id = invItem.CreatorIdAsUuid; + llsdItem.permissions.base_mask = (int)invItem.CurrentPermissions; + llsdItem.permissions.everyone_mask = (int)invItem.EveryOnePermissions; + llsdItem.permissions.group_id = invItem.GroupID; + llsdItem.permissions.group_mask = (int)invItem.GroupPermissions; + llsdItem.permissions.is_owner_group = invItem.GroupOwned; + llsdItem.permissions.next_owner_mask = (int)invItem.NextPermissions; + llsdItem.permissions.owner_id = invItem.Owner; + llsdItem.permissions.owner_mask = (int)invItem.CurrentPermissions; + llsdItem.sale_info = new LLSDSaleInfo(); + llsdItem.sale_info.sale_price = invItem.SalePrice; + switch (invItem.SaleType) + { + default: + llsdItem.sale_info.sale_type = "not"; + break; + case 1: + llsdItem.sale_info.sale_type = "original"; + break; + case 2: + llsdItem.sale_info.sale_type = "copy"; + break; + case 3: + llsdItem.sale_info.sale_type = "contents"; + break; + } + + return llsdItem; + } + } +} diff --git a/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs new file mode 100644 index 0000000000..0ba89315e1 --- /dev/null +++ b/OpenSim/Capabilities/Handlers/FetchInventory2/FetchInventory2ServerConnector.cs @@ -0,0 +1,70 @@ +/* + * 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 Nini.Config; +using OpenSim.Server.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Server.Handlers.Base; +using OpenMetaverse; + +namespace OpenSim.Capabilities.Handlers +{ + public class FetchInventory2ServerConnector : ServiceConnector + { + private IInventoryService m_InventoryService; + private string m_ConfigName = "CapsService"; + + public FetchInventory2ServerConnector(IConfigSource config, IHttpServer server, string configName) + : base(config, server, configName) + { + if (configName != String.Empty) + m_ConfigName = configName; + + IConfig serverConfig = config.Configs[m_ConfigName]; + if (serverConfig == null) + throw new Exception(String.Format("No section '{0}' in config file", m_ConfigName)); + + string invService = serverConfig.GetString("InventoryService", String.Empty); + + if (invService == String.Empty) + throw new Exception("No InventoryService in config file"); + + Object[] args = new Object[] { config }; + m_InventoryService = ServerUtils.LoadPlugin(invService, args); + + if (m_InventoryService == null) + throw new Exception(String.Format("Failed to load InventoryService from {0}; config is {1}", invService, m_ConfigName)); + + FetchInventory2Handler fiHandler = new FetchInventory2Handler(m_InventoryService); + IRequestHandler reqHandler + = new RestStreamHandler("POST", "/CAPS/FetchInventory/", fiHandler.FetchInventoryRequest); + server.AddStreamHandler(reqHandler); + } + } +} diff --git a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs index 3ce4e667c6..8b44f72421 100644 --- a/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs +++ b/OpenSim/Capabilities/Handlers/WebFetchInventoryDescendents/WebFetchInvDescHandler.cs @@ -245,7 +245,7 @@ namespace OpenSim.Capabilities.Handlers // containingFolder.Name, containingFolder.ID, agentID); version = containingFolder.Version; -// + // if (fetchItems) // { // List linkedItemsToAdd = new List(); diff --git a/OpenSim/Capabilities/LLSDInventoryItem.cs b/OpenSim/Capabilities/LLSDInventoryItem.cs index cce18d7498..426a6cbaf5 100644 --- a/OpenSim/Capabilities/LLSDInventoryItem.cs +++ b/OpenSim/Capabilities/LLSDInventoryItem.cs @@ -95,4 +95,11 @@ namespace OpenSim.Framework.Capabilities public UUID owner_id; public int version; } -} + + [OSDMap] + public class LLSDFetchInventory + { + public UUID agent_id; + public OSDArray items = new OSDArray(); + } +} \ No newline at end of file diff --git a/OpenSim/Data/MySQL/MySQLEstateData.cs b/OpenSim/Data/MySQL/MySQLEstateData.cs index 3d647ca38c..3dd46cbdf6 100644 --- a/OpenSim/Data/MySQL/MySQLEstateData.cs +++ b/OpenSim/Data/MySQL/MySQLEstateData.cs @@ -210,7 +210,6 @@ namespace OpenSim.Data.MySQL } LoadBanList(es); - es.EstateManagers = LoadUUIDList(es.EstateID, "estate_managers"); es.EstateAccess = LoadUUIDList(es.EstateID, "estate_users"); es.EstateGroups = LoadUUIDList(es.EstateID, "estate_groups"); diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 6d14b82075..3123edfe7b 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -846,6 +846,8 @@ namespace OpenSim.Data.MySQL } } + LoadSpawnPoints(rs); + return rs; } @@ -994,7 +996,9 @@ namespace OpenSim.Data.MySQL "use_estate_sun, fixed_sun, sun_position, " + "covenant, Sandbox, sunvectorx, sunvectory, " + "sunvectorz, loaded_creation_datetime, " + - "loaded_creation_id, map_tile_ID) values (?RegionUUID, ?BlockTerraform, " + + "loaded_creation_id, map_tile_ID, " + + "TelehubObject, parcel_tile_ID) " + + "values (?RegionUUID, ?BlockTerraform, " + "?BlockFly, ?AllowDamage, ?RestrictPushing, " + "?AllowLandResell, ?AllowLandJoinDivide, " + "?BlockShowInSearch, ?AgentLimit, ?ObjectBonus, " + @@ -1009,7 +1013,7 @@ namespace OpenSim.Data.MySQL "?SunPosition, ?Covenant, ?Sandbox, " + "?SunVectorX, ?SunVectorY, ?SunVectorZ, " + "?LoadedCreationDateTime, ?LoadedCreationID, " + - "?TerrainImageID)"; + "?TerrainImageID, ?TelehubObject, ?ParcelImageID) "; FillRegionSettingsCommand(cmd, rs); @@ -1017,6 +1021,7 @@ namespace OpenSim.Data.MySQL } } } + SaveSpawnPoints(rs); } public List LoadLandObjects(UUID regionUUID) @@ -1296,6 +1301,8 @@ namespace OpenSim.Data.MySQL newSettings.LoadedCreationID = (String) row["loaded_creation_id"]; newSettings.TerrainImageID = DBGuid.FromDB(row["map_tile_ID"]); + newSettings.ParcelImageID = DBGuid.FromDB(row["parcel_tile_ID"]); + newSettings.TelehubObject = DBGuid.FromDB(row["TelehubObject"]); return newSettings; } @@ -1626,7 +1633,8 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("LoadedCreationDateTime", settings.LoadedCreationDateTime); cmd.Parameters.AddWithValue("LoadedCreationID", settings.LoadedCreationID); cmd.Parameters.AddWithValue("TerrainImageID", settings.TerrainImageID); - + cmd.Parameters.AddWithValue("ParcelImageID", settings.ParcelImageID); + cmd.Parameters.AddWithValue("TelehubObject", settings.TelehubObject); } /// @@ -1828,5 +1836,72 @@ namespace OpenSim.Data.MySQL } } } + + private void LoadSpawnPoints(RegionSettings rs) + { + rs.ClearSpawnPoints(); + + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "select Yaw, Pitch, Distance from spawn_points where RegionID = ?RegionID"; + cmd.Parameters.AddWithValue("?RegionID", rs.RegionUUID.ToString()); + + using (IDataReader r = cmd.ExecuteReader()) + { + while (r.Read()) + { + SpawnPoint sp = new SpawnPoint(); + + sp.Yaw = (float)r["Yaw"]; + sp.Pitch = (float)r["Pitch"]; + sp.Distance = (float)r["Distance"]; + + rs.AddSpawnPoint(sp); + } + } + } + } + } + } + + private void SaveSpawnPoints(RegionSettings rs) + { + lock (m_dbLock) + { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) + { + cmd.CommandText = "delete from spawn_points where RegionID = ?RegionID"; + cmd.Parameters.AddWithValue("?RegionID", rs.RegionUUID.ToString()); + + cmd.ExecuteNonQuery(); + + cmd.Parameters.Clear(); + + cmd.CommandText = "insert into spawn_points (RegionID, Yaw, Pitch, Distance) values ( ?RegionID, ?Yaw, ?Pitch, ?Distance)"; + + foreach (SpawnPoint p in rs.SpawnPoints()) + { + cmd.Parameters.AddWithValue("?RegionID", rs.RegionUUID.ToString()); + cmd.Parameters.AddWithValue("?Yaw", p.Yaw); + cmd.Parameters.AddWithValue("?Pitch", p.Pitch); + cmd.Parameters.AddWithValue("?Distance", p.Distance); + + cmd.ExecuteNonQuery(); + cmd.Parameters.Clear(); + } + } + } + } + } } } diff --git a/OpenSim/Data/MySQL/Resources/GridStore.migrations b/OpenSim/Data/MySQL/Resources/GridStore.migrations index eda6dbb2a3..98ba8c5604 100644 --- a/OpenSim/Data/MySQL/Resources/GridStore.migrations +++ b/OpenSim/Data/MySQL/Resources/GridStore.migrations @@ -94,3 +94,12 @@ BEGIN; alter table regions modify column regionName varchar(128) default NULL; COMMIT; + +:VERSION 9 # ------------ + +BEGIN; + +alter table regions add column `parcelMapTexture` varchar(36) default NULL; + +COMMIT; + diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index 987625bbf0..f9b5737c78 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -841,4 +841,25 @@ alter table regionban ENGINE = MyISAM; alter table regionsettings ENGINE = MyISAM; alter table terrain ENGINE = MyISAM; -COMMIT; \ No newline at end of file +COMMIT; + +:VERSION 39 #--------------- Telehub support + +BEGIN; +CREATE TABLE IF NOT EXISTS `spawn_points` ( + `RegionID` varchar(36) COLLATE utf8_unicode_ci NOT NULL, + `Yaw` float NOT NULL, + `Pitch` float NOT NULL, + `Distance` float NOT NULL, + KEY `RegionID` (`RegionID`) +) ENGINE=Innodb; + +ALTER TABLE `regionsettings` ADD COLUMN `TelehubObject` varchar(36) NOT NULL; +COMMIT; + +:VERSION 40 #---------------- Parcels for sale + +BEGIN; +ALTER TABLE `regionsettings` ADD COLUMN `parcel_tile_ID` char(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; +COMMIT; + diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 1b93176df6..1d806fc5eb 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -685,7 +685,7 @@ namespace OpenSim.Data.Tests SceneObjectGroup sog = GetMySOG("object1"); InventoryItemBase i = NewItem(item1, zero, zero, itemname1, zero); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, i, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, i, zero), Is.True); TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, item1); Assert.That(t.Name, Is.EqualTo(itemname1), "Assert.That(t.Name, Is.EqualTo(itemname1))"); @@ -762,7 +762,7 @@ namespace OpenSim.Data.Tests i.CreationDate = creationd; SceneObjectGroup sog = GetMySOG("object1"); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, i, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, i, zero), Is.True); TaskInventoryItem t = sog.GetInventoryItem(sog.RootPart.LocalId, id); Assert.That(t.Name, Is.EqualTo(name), "Assert.That(t.Name, Is.EqualTo(name))"); @@ -807,10 +807,10 @@ namespace OpenSim.Data.Tests SceneObjectGroup sog = FindSOG("object1", region1); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib1, zero), Is.True); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib2, zero), Is.True); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib3, zero), Is.True); - Assert.That(sog.AddInventoryItem(null, sog.RootPart.LocalId, ib4, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib1, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib2, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib3, zero), Is.True); + Assert.That(sog.AddInventoryItem(zero, sog.RootPart.LocalId, ib4, zero), Is.True); TaskInventoryItem t1 = sog.GetInventoryItem(sog.RootPart.LocalId, i1); Assert.That(t1.Name, Is.EqualTo(ib1.Name), "Assert.That(t1.Name, Is.EqualTo(ib1.Name))"); diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs index 2a495b0e8c..98604f27ba 100644 --- a/OpenSim/Framework/EstateSettings.cs +++ b/OpenSim/Framework/EstateSettings.cs @@ -373,5 +373,11 @@ namespace OpenSim.Framework return l_EstateAccess.Contains(user); } + + public bool GroupAccess(UUID groupID) + { + return l_EstateGroups.Contains(groupID); + } + } } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 258b3ebb59..1326fe9dd6 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -358,6 +358,8 @@ namespace OpenSim.Framework public delegate void EstateChangeInfo(IClientAPI client, UUID invoice, UUID senderID, UInt32 param1, UInt32 param2); + public delegate void EstateManageTelehub(IClientAPI client, UUID invoice, UUID senderID, string cmd, UInt32 param1); + public delegate void RequestTerrain(IClientAPI remoteClient, string clientFileName); public delegate void BakeTerrain(IClientAPI remoteClient); @@ -769,6 +771,7 @@ namespace OpenSim.Framework event ModifyTerrain OnModifyTerrain; event BakeTerrain OnBakeTerrain; event EstateChangeInfo OnEstateChangeInfo; + event EstateManageTelehub OnEstateManageTelehub; // [Obsolete("LLClientView Specific.")] event SetAppearance OnSetAppearance; // [Obsolete("LLClientView Specific - Replace and rename OnAvatarUpdate. Difference from SetAppearance?")] @@ -1074,7 +1077,15 @@ namespace OpenSim.Framework void SendWindData(Vector2[] windSpeeds); void SendCloudData(float[] cloudCover); + /// + /// Sent when an agent completes its movement into a region. + /// + /// + /// This packet marks completion of the arrival of a root avatar in a region, whether through login, region + /// crossing or direct teleport. + /// void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look); + void InformClientOfNeighbour(ulong neighbourHandle, IPEndPoint neighbourExternalEndPoint); /// @@ -1133,6 +1144,8 @@ namespace OpenSim.Framework void SendTaskInventory(UUID taskID, short serial, byte[] fileName); + void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List SpawnPoint); + /// /// Used by the server to inform the client of new inventory items and folders. /// diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index 0316944072..f75a9908c9 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs @@ -130,5 +130,11 @@ namespace OpenSim.Framework /// /// void SetMusicUrl(string url); + + /// + /// Get the music url for this land parcel + /// + /// The music url. + string GetMusicUrl(); } } diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs index 3d4873df0c..1e097285c9 100644 --- a/OpenSim/Framework/IMoneyModule.cs +++ b/OpenSim/Framework/IMoneyModule.cs @@ -36,8 +36,8 @@ namespace OpenSim.Framework int amount); int GetBalance(UUID agentID); - bool UploadCovered(IClientAPI client, int amount); - bool AmountCovered(IClientAPI client, int amount); + bool UploadCovered(UUID agentID, int amount); + bool AmountCovered(UUID agentID, int amount); void ApplyCharge(UUID agentID, int amount, string text); void ApplyUploadCharge(UUID agentID, int amount, string text); diff --git a/OpenSim/Framework/RegionSettings.cs b/OpenSim/Framework/RegionSettings.cs index 673cf203f8..91e07df678 100644 --- a/OpenSim/Framework/RegionSettings.cs +++ b/OpenSim/Framework/RegionSettings.cs @@ -26,11 +26,53 @@ */ using System; +using System.Collections.Generic; using System.IO; using OpenMetaverse; namespace OpenSim.Framework { + public struct SpawnPoint + { + public float Yaw; + public float Pitch; + public float Distance; + + public void SetLocation(Vector3 pos, Quaternion rot, Vector3 point) + { + // The point is an absolute position, so we need the relative + // location to the spawn point + Vector3 offset = point - pos; + Distance = Vector3.Mag(offset); + + // Next we need to rotate this vector into the spawn point's + // coordinate system + rot.W = -rot.W; + offset = offset * rot; + + Vector3 dir = Vector3.Normalize(offset); + + // Get the bearing (yaw) + Yaw = (float)Math.Atan2(dir.Y, dir.X); + + // Get the elevation (pitch) + Pitch = (float)-Math.Atan2(dir.Z, Math.Sqrt(dir.X * dir.X + dir.Y * dir.Y)); + } + + public Vector3 GetLocation(Vector3 pos, Quaternion rot) + { + Quaternion y = Quaternion.CreateFromEulers(0, 0, Yaw); + Quaternion p = Quaternion.CreateFromEulers(0, Pitch, 0); + + Vector3 dir = new Vector3(1, 0, 0) * p * y; + Vector3 offset = dir * (float)Distance; + + offset *= rot; + + return pos + offset; + } + } + public class RegionSettings { public delegate void SaveDelegate(RegionSettings rs); @@ -331,6 +373,14 @@ namespace OpenSim.Framework set { m_SunVector = value; } } + private UUID m_ParcelImageID; + + public UUID ParcelImageID + { + get { return m_ParcelImageID; } + set { m_ParcelImageID = value; } + } + private UUID m_TerrainImageID; public UUID TerrainImageID @@ -397,5 +447,49 @@ namespace OpenSim.Framework set { m_LoadedCreationID = value; } } + // Connected Telehub object + private UUID m_TelehubObject; + public UUID TelehubObject + { + get + { + return m_TelehubObject; + } + set + { + m_TelehubObject = value; + } + } + + // Our Connected Telehub's SpawnPoints + public List l_SpawnPoints = new List(); + + // Add a SpawnPoint + // ** These are not region coordinates ** + // They are relative to the Telehub coordinates + // + public void AddSpawnPoint(SpawnPoint point) + { + l_SpawnPoints.Add(point); + } + + // Remove a SpawnPoint + public void RemoveSpawnPoint(int point_index) + { + l_SpawnPoints.RemoveAt(point_index); + } + + // Return the List of SpawnPoints + public List SpawnPoints() + { + return l_SpawnPoints; + + } + + // Clear the SpawnPoints List of all entries + public void ClearSpawnPoints() + { + l_SpawnPoints.Clear(); + } } } diff --git a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs index 6e8c2ee173..7447ac28ea 100644 --- a/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs +++ b/OpenSim/Framework/Serialization/External/ExternalRepresentationUtils.cs @@ -44,13 +44,13 @@ namespace OpenSim.Framework.Serialization.External /// with creator data added to it. /// /// The SceneObjectPart represented in XML2 - /// The URL of the profile service for the creator + /// The URL of the user agents service (home) for the creator /// The service for retrieving user account information /// The scope of the user account information (Grid ID) /// The SceneObjectPart represented in XML2 - public static string RewriteSOP(string xml, string profileURL, IUserAccountService userService, UUID scopeID) + public static string RewriteSOP(string xml, string homeURL, IUserAccountService userService, UUID scopeID) { - if (xml == string.Empty || profileURL == string.Empty || userService == null) + if (xml == string.Empty || homeURL == string.Empty || userService == null) return xml; XmlDocument doc = new XmlDocument(); @@ -83,7 +83,7 @@ namespace OpenSim.Framework.Serialization.External if (!hasCreatorData && creator != null) { XmlElement creatorData = doc.CreateElement("CreatorData"); - creatorData.InnerText = profileURL + "/" + creator.PrincipalID + ";" + creator.FirstName + " " + creator.LastName; + creatorData.InnerText = homeURL + ";" + creator.FirstName + " " + creator.LastName; sop.AppendChild(creatorData); } } diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 4c381d0f86..545e76c85c 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -251,7 +251,7 @@ namespace OpenSim.Framework.Servers sb.Append(threads.Length + " threads are being tracked:" + Environment.NewLine); - int timeNow = Util.EnvironmentTickCount(); + int timeNow = Environment.TickCount & Int32.MaxValue; sb.AppendFormat(reportFormat, "ID", "NAME", "LAST UPDATE (MS)", "LIFETIME (MS)", "PRIORITY", "STATE"); sb.Append(Environment.NewLine); diff --git a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs b/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs index 544975791b..a506e3ba4d 100644 --- a/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Statistics/SimExtraStatsCollector.cs @@ -42,15 +42,15 @@ namespace OpenSim.Framework.Statistics { private long abnormalClientThreadTerminations; - private long assetsInCache; - private long texturesInCache; - private long assetCacheMemoryUsage; - private long textureCacheMemoryUsage; - private TimeSpan assetRequestTimeAfterCacheMiss; - private long blockedMissingTextureRequests; +// private long assetsInCache; +// private long texturesInCache; +// private long assetCacheMemoryUsage; +// private long textureCacheMemoryUsage; +// private TimeSpan assetRequestTimeAfterCacheMiss; +// private long blockedMissingTextureRequests; - private long assetServiceRequestFailures; - private long inventoryServiceRetrievalFailures; +// private long assetServiceRequestFailures; +// private long inventoryServiceRetrievalFailures; private volatile float timeDilation; private volatile float simFps; @@ -79,27 +79,27 @@ namespace OpenSim.Framework.Statistics /// public long AbnormalClientThreadTerminations { get { return abnormalClientThreadTerminations; } } - /// - /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the - /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these - /// haven't yet been implemented... - /// - public long AssetsInCache { get { return assetsInCache; } } - - /// - /// Currently unused - /// - public long TexturesInCache { get { return texturesInCache; } } - - /// - /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit - /// - public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } - - /// - /// Currently unused - /// - public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } } +// /// +// /// These statistics are being collected by push rather than pull. Pull would be simpler, but I had the +// /// notion of providing some flow statistics (which pull wouldn't give us). Though admittedly these +// /// haven't yet been implemented... +// /// +// public long AssetsInCache { get { return assetsInCache; } } +// +// /// +// /// Currently unused +// /// +// public long TexturesInCache { get { return texturesInCache; } } +// +// /// +// /// Currently misleading since we can't currently subtract removed asset memory usage without a performance hit +// /// +// public long AssetCacheMemoryUsage { get { return assetCacheMemoryUsage; } } +// +// /// +// /// Currently unused +// /// +// public long TextureCacheMemoryUsage { get { return textureCacheMemoryUsage; } } public float TimeDilation { get { return timeDilation; } } public float SimFps { get { return simFps; } } @@ -123,32 +123,33 @@ namespace OpenSim.Framework.Statistics public float ActiveScripts { get { return activeScripts; } } public float ScriptLinesPerSecond { get { return scriptLinesPerSecond; } } - /// - /// This is the time it took for the last asset request made in response to a cache miss. - /// - public TimeSpan AssetRequestTimeAfterCacheMiss { get { return assetRequestTimeAfterCacheMiss; } } - - /// - /// Number of persistent requests for missing textures we have started blocking from clients. To some extent - /// this is just a temporary statistic to keep this problem in view - the root cause of this lies either - /// in a mishandling of the reply protocol, related to avatar appearance or may even originate in graphics - /// driver bugs on clients (though this seems less likely). - /// - public long BlockedMissingTextureRequests { get { return blockedMissingTextureRequests; } } - - /// - /// Record the number of times that an asset request has failed. Failures are effectively exceptions, such as - /// request timeouts. If an asset service replies that a particular asset cannot be found, this is not counted - /// as a failure - /// - public long AssetServiceRequestFailures { get { return assetServiceRequestFailures; } } +// /// +// /// This is the time it took for the last asset request made in response to a cache miss. +// /// +// public TimeSpan AssetRequestTimeAfterCacheMiss { get { return assetRequestTimeAfterCacheMiss; } } +// +// /// +// /// Number of persistent requests for missing textures we have started blocking from clients. To some extent +// /// this is just a temporary statistic to keep this problem in view - the root cause of this lies either +// /// in a mishandling of the reply protocol, related to avatar appearance or may even originate in graphics +// /// driver bugs on clients (though this seems less likely). +// /// +// public long BlockedMissingTextureRequests { get { return blockedMissingTextureRequests; } } +// +// /// +// /// Record the number of times that an asset request has failed. Failures are effectively exceptions, such as +// /// request timeouts. If an asset service replies that a particular asset cannot be found, this is not counted +// /// as a failure +// /// +// public long AssetServiceRequestFailures { get { return assetServiceRequestFailures; } } /// /// Number of known failures to retrieve avatar inventory from the inventory service. This does not /// cover situations where the inventory service accepts the request but never returns any data, since /// we do not yet timeout this situation. /// - public long InventoryServiceRetrievalFailures { get { return inventoryServiceRetrievalFailures; } } + /// Commented out because we do not cache inventory at this point +// public long InventoryServiceRetrievalFailures { get { return inventoryServiceRetrievalFailures; } } /// /// Retrieve the total frame time (in ms) of the last frame @@ -171,58 +172,58 @@ namespace OpenSim.Framework.Statistics abnormalClientThreadTerminations++; } - public void AddAsset(AssetBase asset) - { - assetsInCache++; - //assetCacheMemoryUsage += asset.Data.Length; - } - - public void RemoveAsset(UUID uuid) - { - assetsInCache--; - } +// public void AddAsset(AssetBase asset) +// { +// assetsInCache++; +// //assetCacheMemoryUsage += asset.Data.Length; +// } +// +// public void RemoveAsset(UUID uuid) +// { +// assetsInCache--; +// } +// +// public void AddTexture(AssetBase image) +// { +// if (image.Data != null) +// { +// texturesInCache++; +// +// // This could have been a pull stat, though there was originally a nebulous idea to measure flow rates +// textureCacheMemoryUsage += image.Data.Length; +// } +// } +// +// /// +// /// Signal that the asset cache has been cleared. +// /// +// public void ClearAssetCacheStatistics() +// { +// assetsInCache = 0; +// assetCacheMemoryUsage = 0; +// texturesInCache = 0; +// textureCacheMemoryUsage = 0; +// } +// +// public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) +// { +// assetRequestTimeAfterCacheMiss = ts; +// } +// +// public void AddBlockedMissingTextureRequest() +// { +// blockedMissingTextureRequests++; +// } +// +// public void AddAssetServiceRequestFailure() +// { +// assetServiceRequestFailures++; +// } - public void AddTexture(AssetBase image) - { - if (image.Data != null) - { - texturesInCache++; - - // This could have been a pull stat, though there was originally a nebulous idea to measure flow rates - textureCacheMemoryUsage += image.Data.Length; - } - } - - /// - /// Signal that the asset cache has been cleared. - /// - public void ClearAssetCacheStatistics() - { - assetsInCache = 0; - assetCacheMemoryUsage = 0; - texturesInCache = 0; - textureCacheMemoryUsage = 0; - } - - public void AddAssetRequestTimeAfterCacheMiss(TimeSpan ts) - { - assetRequestTimeAfterCacheMiss = ts; - } - - public void AddBlockedMissingTextureRequest() - { - blockedMissingTextureRequests++; - } - - public void AddAssetServiceRequestFailure() - { - assetServiceRequestFailures++; - } - - public void AddInventoryServiceRetrievalFailure() - { - inventoryServiceRetrievalFailures++; - } +// public void AddInventoryServiceRetrievalFailure() +// { +// inventoryServiceRetrievalFailures++; +// } /// /// Register as a packet queue stats provider @@ -290,8 +291,8 @@ namespace OpenSim.Framework.Statistics public override string Report() { StringBuilder sb = new StringBuilder(Environment.NewLine); - sb.Append("ASSET STATISTICS"); - sb.Append(Environment.NewLine); +// sb.Append("ASSET STATISTICS"); +// sb.Append(Environment.NewLine); /* sb.Append( @@ -307,7 +308,8 @@ Asset service request failures: {6}"+ Environment.NewLine, BlockedMissingTextureRequests, AssetServiceRequestFailures)); */ - + + /* sb.Append( string.Format( @"Asset cache contains {0,6} assets @@ -318,7 +320,7 @@ Asset service request failures: {3}" + Environment.NewLine, assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0, BlockedMissingTextureRequests, AssetServiceRequestFailures)); - + */ sb.Append(Environment.NewLine); sb.Append("CONNECTION STATISTICS"); @@ -328,13 +330,13 @@ Asset service request failures: {3}" + Environment.NewLine, "Abnormal client thread terminations: {0}" + Environment.NewLine, abnormalClientThreadTerminations)); - sb.Append(Environment.NewLine); - sb.Append("INVENTORY STATISTICS"); - sb.Append(Environment.NewLine); - sb.Append( - string.Format( - "Initial inventory caching failures: {0}" + Environment.NewLine, - InventoryServiceRetrievalFailures)); +// sb.Append(Environment.NewLine); +// sb.Append("INVENTORY STATISTICS"); +// sb.Append(Environment.NewLine); +// sb.Append( +// string.Format( +// "Initial inventory caching failures: {0}" + Environment.NewLine, +// InventoryServiceRetrievalFailures)); sb.Append(Environment.NewLine); sb.Append("FRAME STATISTICS"); @@ -390,17 +392,17 @@ Asset service request failures: {3}" + Environment.NewLine, public override string XReport(string uptime, string version) { OSDMap args = new OSDMap(30); - args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); - args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", - assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0)); - args["BlockedMissingTextureRequests"] = OSD.FromString (String.Format ("{0:0.##}", - BlockedMissingTextureRequests)); - args["AssetServiceRequestFailures"] = OSD.FromString (String.Format ("{0:0.##}", - AssetServiceRequestFailures)); - args["abnormalClientThreadTerminations"] = OSD.FromString (String.Format ("{0:0.##}", - abnormalClientThreadTerminations)); - args["InventoryServiceRetrievalFailures"] = OSD.FromString (String.Format ("{0:0.##}", - InventoryServiceRetrievalFailures)); +// args["AssetsInCache"] = OSD.FromString (String.Format ("{0:0.##}", AssetsInCache)); +// args["TimeAfterCacheMiss"] = OSD.FromString (String.Format ("{0:0.##}", +// assetRequestTimeAfterCacheMiss.Milliseconds / 1000.0)); +// args["BlockedMissingTextureRequests"] = OSD.FromString (String.Format ("{0:0.##}", +// BlockedMissingTextureRequests)); +// args["AssetServiceRequestFailures"] = OSD.FromString (String.Format ("{0:0.##}", +// AssetServiceRequestFailures)); +// args["abnormalClientThreadTerminations"] = OSD.FromString (String.Format ("{0:0.##}", +// abnormalClientThreadTerminations)); +// args["InventoryServiceRetrievalFailures"] = OSD.FromString (String.Format ("{0:0.##}", +// InventoryServiceRetrievalFailures)); args["Dilatn"] = OSD.FromString (String.Format ("{0:0.##}", timeDilation)); args["SimFPS"] = OSD.FromString (String.Format ("{0:0.##}", simFps)); args["PhyFPS"] = OSD.FromString (String.Format ("{0:0.##}", physicsFps)); diff --git a/OpenSim/Region/Application/ConfigurationLoader.cs b/OpenSim/Region/Application/ConfigurationLoader.cs index 4a7c8b083b..8d95c41ca2 100644 --- a/OpenSim/Region/Application/ConfigurationLoader.cs +++ b/OpenSim/Region/Application/ConfigurationLoader.cs @@ -107,15 +107,13 @@ namespace OpenSim } else { - m_log.ErrorFormat("Master ini file {0} not found", masterFilePath); + m_log.ErrorFormat("Master ini file {0} not found", Path.GetFullPath(masterFilePath)); Environment.Exit(1); } } } - - string iniFileName = - startupConfig.GetString("inifile", "OpenSim.ini"); + string iniFileName = startupConfig.GetString("inifile", "OpenSim.ini"); if (IsUri(iniFileName)) { @@ -131,8 +129,7 @@ namespace OpenSim if (!File.Exists(Application.iniFilePath)) { iniFileName = "OpenSim.xml"; - Application.iniFilePath = Path.GetFullPath( - Path.Combine(Util.configDir(), iniFileName)); + Application.iniFilePath = Path.GetFullPath(Path.Combine(Util.configDir(), iniFileName)); } if (File.Exists(Application.iniFilePath)) @@ -142,15 +139,12 @@ namespace OpenSim } } - string iniDirName = - startupConfig.GetString("inidirectory", "config"); - string iniDirPath = - Path.Combine(Util.configDir(), iniDirName); + string iniDirName = startupConfig.GetString("inidirectory", "config"); + string iniDirPath = Path.Combine(Util.configDir(), iniDirName); if (Directory.Exists(iniDirPath)) { - m_log.InfoFormat("Searching folder {0} for config ini files", - iniDirPath); + m_log.InfoFormat("Searching folder {0} for config ini files", iniDirPath); string[] fileEntries = Directory.GetFiles(iniDirName); foreach (string filePath in fileEntries) @@ -172,7 +166,6 @@ namespace OpenSim if (sources.Count == 0) { m_log.FatalFormat("[CONFIG]: Could not load any configuration"); - m_log.FatalFormat("[CONFIG]: Did you copy the OpenSimDefaults.ini.example file to OpenSimDefaults.ini?"); Environment.Exit(1); } diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 3a1a8c7c53..145875b601 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -250,8 +250,10 @@ namespace OpenSim + "If level <= 0 then no extra http logging is done.\n", Debug); + m_console.Commands.AddCommand("region", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); + m_console.Commands.AddCommand("region", false, "debug scene", - "debug scene ", + "debug scene ", "Turn on scene debugging", Debug); m_console.Commands.AddCommand("region", false, "change region", @@ -289,12 +291,16 @@ namespace OpenSim m_console.Commands.AddCommand("region", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-p|--profile=] [--noassets] [--perm=] []", + "save oar [-h|--home=] [--noassets] [--publish] [--perm=] []", "Save a region's data to an OAR archive.", // "-v|--version= generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine - "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + "-h|--home= adds the url of the profile service to the saved user information." + Environment.NewLine + "--noassets stops assets being saved to the OAR." + Environment.NewLine - + "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine + + "--publish saves an OAR stripped of owner and last owner information." + Environment.NewLine + + " on reload, the estate owner will be the owner of all objects" + Environment.NewLine + + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published" + Environment.NewLine + + " this option is EXPERIMENTAL" + Environment.NewLine + + "--perm= stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine + " can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine + "The OAR path must be a filesystem path." + " If this is not given then the oar is saved to region.oar in the current directory.", @@ -948,6 +954,21 @@ namespace OpenSim break; + case "teleport": + foreach(Scene s in m_sceneManager.Scenes) + { + if (s.DEBUG) + { + s.DEBUG = false; + MainConsole.Instance.Output("Teleport debugging is disabled!"); + } + else{ + s.DEBUG = true; + MainConsole.Instance.Output("Teleport debugging is enabled!"); + } + } + break; + default: MainConsole.Instance.Output("Unknown debug command"); break; diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 9f9b4f04e1..f482d8f93c 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -202,16 +202,16 @@ namespace OpenSim // Load the simulation data service IConfig simDataConfig = m_config.Source.Configs["SimulationDataStore"]; if (simDataConfig == null) - throw new Exception("Configuration file is missing the [SimulationDataStore] section"); + throw new Exception("Configuration file is missing the [SimulationDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); string module = simDataConfig.GetString("LocalServiceModule", String.Empty); if (String.IsNullOrEmpty(module)) - throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section"); + throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [SimulationDataStore] section."); m_simulationDataService = ServerUtils.LoadPlugin(module, new object[] { m_config.Source }); // Load the estate data service IConfig estateDataConfig = m_config.Source.Configs["EstateDataStore"]; if (estateDataConfig == null) - throw new Exception("Configuration file is missing the [EstateDataStore] section"); + throw new Exception("Configuration file is missing the [EstateDataStore] section. Have you copied OpenSim.ini.example to OpenSim.ini to reference config-include/ files?"); module = estateDataConfig.GetString("LocalServiceModule", String.Empty); if (String.IsNullOrEmpty(module)) throw new Exception("Configuration file is missing the LocalServiceModule parameter in the [EstateDataStore] section"); @@ -383,6 +383,9 @@ namespace OpenSim // TODO : Try setting resource for region xstats here on scene MainServer.Instance.AddStreamHandler(new Region.Framework.Scenes.RegionStatsHandler(regionInfo)); + scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); + scene.EventManager.TriggerParcelPrimCountUpdate(); + try { scene.RegisterRegionWithGrid(); @@ -398,9 +401,6 @@ namespace OpenSim Environment.Exit(1); } - scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); - scene.EventManager.TriggerParcelPrimCountUpdate(); - // We need to do this after we've initialized the // scripting engines. scene.CreateScriptInstances(); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 2347cf2791..cf0c28b8a8 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -94,6 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden private static readonly string m_notecardUpdatePath = "0004/"; private static readonly string m_notecardTaskUpdatePath = "0005/"; // private static readonly string m_fetchInventoryPath = "0006/"; + private static readonly string m_copyFromNotecardPath = "0007/"; // private static readonly string m_remoteParcelRequestPath = "0009/";// This is in the LandManagementModule. @@ -180,6 +181,7 @@ namespace OpenSim.Region.ClientStack.Linden m_HostCapsObj.RegisterHandler("UpdateNotecardAgentInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptAgentInventory", req); m_HostCapsObj.RegisterHandler("UpdateScriptAgent", req); + m_HostCapsObj.RegisterHandler("CopyInventoryFromNotecard", new RestStreamHandler("POST", capsBase + m_copyFromNotecardPath, CopyInventoryFromNotecard)); // As of RC 1.22.9 of the Linden client this is // supported @@ -366,7 +368,7 @@ namespace OpenSim.Region.ClientStack.Linden if (mm != null) { - if (!mm.UploadCovered(client, mm.UploadCharge)) + if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) { if (client != null) client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); @@ -723,6 +725,75 @@ namespace OpenSim.Region.ClientStack.Linden return LLSDHelpers.SerialiseLLSDReply(uploadResponse); } + + /// + /// Called by the CopyInventoryFromNotecard caps handler. + /// + /// + /// + /// + public string CopyInventoryFromNotecard(string request, string path, string param, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + Hashtable response = new Hashtable(); + response["int_response_code"] = 404; + response["content_type"] = "text/plain"; + response["keepalive"] = false; + response["str_response_string"] = ""; + + try + { + OSDMap content = (OSDMap)OSDParser.DeserializeLLSDXml(request); + UUID objectID = content["object-id"].AsUUID(); + UUID notecardID = content["notecard-id"].AsUUID(); + UUID folderID = content["folder-id"].AsUUID(); + UUID itemID = content["item-id"].AsUUID(); + + // m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, FolderID:{0}, ItemID:{1}, NotecardID:{2}, ObjectID:{3}", folderID, itemID, notecardID, objectID); + + if (objectID != UUID.Zero) + { + SceneObjectPart part = m_Scene.GetSceneObjectPart(objectID); + if (part != null) + { + TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(notecardID); + if (!m_Scene.Permissions.CanCopyObjectInventory(notecardID, objectID, m_HostCapsObj.AgentID)) + { + return LLSDHelpers.SerialiseLLSDReply(response); + } + } + } + + InventoryItemBase item = null; + InventoryItemBase copyItem = null; + IClientAPI client = null; + + m_Scene.TryGetClient(m_HostCapsObj.AgentID, out client); + item = m_Scene.InventoryService.GetItem(new InventoryItemBase(itemID)); + if (item != null) + { + copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID); + if (copyItem != null && client != null) + { + m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder); + client.SendBulkUpdateInventory(copyItem); + } + } + else + { + m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID); + if (client != null) + client.SendAlertMessage("Failed to retrieve item"); + } + } + catch (Exception e) + { + m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard : {0}", e.ToString()); + } + + response["int_response_code"] = 200; + return LLSDHelpers.SerialiseLLSDReply(response); + } } public class AssetUploader @@ -1018,4 +1089,4 @@ namespace OpenSim.Region.ClientStack.Linden fs.Close(); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs new file mode 100644 index 0000000000..14501c7314 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/FetchInventory2Module.cs @@ -0,0 +1,151 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Reflection; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OpenSim.Capabilities.Handlers; + +namespace OpenSim.Region.ClientStack.Linden +{ + /// + /// This module implements both WebFetchInventoryDescendents and FetchInventoryDescendents2 capabilities. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] + public class FetchInventory2Module : INonSharedRegionModule + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + public bool Enabled { get; private set; } + + private Scene m_scene; + + private IInventoryService m_inventoryService; + + private string m_fetchInventory2Url; + + private FetchInventory2Handler m_fetchHandler; + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + IConfig config = source.Configs["ClientStack.LindenCaps"]; + if (config == null) + return; + + m_fetchInventory2Url = config.GetString("Cap_FetchInventory2", string.Empty); + + if (m_fetchInventory2Url != string.Empty) + Enabled = true; + } + + public void AddRegion(Scene s) + { + if (!Enabled) + return; + + m_scene = s; + } + + public void RemoveRegion(Scene s) + { + if (!Enabled) + return; + + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene = null; + } + + public void RegionLoaded(Scene s) + { + if (!Enabled) + return; + + m_inventoryService = m_scene.InventoryService; + + // We'll reuse the same handler for all requests. + if (m_fetchInventory2Url == "localhost") + m_fetchHandler = new FetchInventory2Handler(m_inventoryService); + + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void PostInitialise() {} + + public void Close() {} + + public string Name { get { return "FetchInventory2Module"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + private void RegisterCaps(UUID agentID, Caps caps) + { + RegisterFetchCap(agentID, caps, "FetchInventory2", m_fetchInventory2Url); + } + + private void RegisterFetchCap(UUID agentID, Caps caps, string capName, string url) + { + string capUrl; + + if (url == "localhost") + { + capUrl = "/CAPS/" + UUID.Random(); + + IRequestHandler reqHandler + = new RestStreamHandler("POST", capUrl, m_fetchHandler.FetchInventoryRequest); + + caps.RegisterHandler(capName, reqHandler); + } + else + { + capUrl = url; + + caps.RegisterHandler(capName, capUrl); + } + +// m_log.DebugFormat( +// "[FETCH INVENTORY2 MODULE]: Registered capability {0} at {1} in region {2} for {3}", +// capName, capUrl, m_scene.RegionInfo.RegionName, agentID); + } + } +} diff --git a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs index b2f04f96f8..aed03b39c1 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/NewFileAgentInventoryVariablePriceModule.cs @@ -147,7 +147,7 @@ namespace OpenSim.Region.ClientStack.Linden { if (m_scene.TryGetClient(agentID, out client)) { - if (!mm.UploadCovered(client, mm.UploadCharge)) + if (!mm.UploadCovered(client.AgentId, mm.UploadCharge)) { if (client != null) client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); @@ -268,4 +268,4 @@ namespace OpenSim.Region.ClientStack.Linden } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs index cb9692a77b..afbe56b093 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/J2KImage.cs @@ -45,6 +45,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP private const int IMAGE_PACKET_SIZE = 1000; private const int FIRST_PACKET_SIZE = 600; + /// + /// If we've requested an asset but not received it in this ticks timeframe, then allow a duplicate + /// request from the client to trigger a fresh asset request. + /// + /// + /// There are 10,000 ticks in a millisecond + /// + private const int ASSET_REQUEST_TIMEOUT = 100000000; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public uint LastSequence; @@ -57,8 +66,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP public UUID AgentID; public IInventoryAccessModule InventoryAccessModule; private OpenJPEG.J2KLayerInfo[] m_layers; + + /// + /// Has this request decoded the asset data? + /// public bool IsDecoded { get; private set; } + + /// + /// Has this request received the required asset data? + /// public bool HasAsset { get; private set; } + + /// + /// Time in milliseconds at which the asset was requested. + /// + public long AssetRequestTime { get; private set; } + public C5.IPriorityQueueHandle PriorityQueueHandle; private uint m_currentPacket; @@ -82,7 +105,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Maximum number of packets to send during this call /// Number of packets sent during this call /// True if the transfer completes at the current discard level, otherwise false - public bool SendPackets(LLClientView client, int packetsToSend, out int packetsSent) + public bool SendPackets(IClientAPI client, int packetsToSend, out int packetsSent) { packetsSent = 0; @@ -102,7 +125,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_currentPacket = 2; } - + while (sendMore && packetsSent < packetsToSend && m_currentPacket <= m_stopPacket) { sendMore = SendPacket(client); @@ -114,17 +137,24 @@ namespace OpenSim.Region.ClientStack.LindenUDP return (m_currentPacket > m_stopPacket); } + /// + /// This is where we decide what we need to update + /// and assign the real discardLevel and packetNumber + /// assuming of course that the connected client might be bonkers + /// public void RunUpdate() { - //This is where we decide what we need to update - //and assign the real discardLevel and packetNumber - //assuming of course that the connected client might be bonkers - if (!HasAsset) { - if (!m_assetRequested) + if (!m_assetRequested || DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT) { +// m_log.DebugFormat( +// "[J2KIMAGE]: Requesting asset {0} from request in packet {1}, already requested? {2}, due to timeout? {3}", +// TextureID, LastSequence, m_assetRequested, DateTime.UtcNow.Ticks > AssetRequestTime + ASSET_REQUEST_TIMEOUT); + m_assetRequested = true; + AssetRequestTime = DateTime.UtcNow.Ticks; + AssetService.Get(TextureID.ToString(), this, AssetReceived); } } @@ -137,6 +167,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { //Request decode m_decodeRequested = true; + +// m_log.DebugFormat("[J2KIMAGE]: Requesting decode of asset {0}", TextureID); + // Do we have a jpeg decoder? if (J2KDecoder != null) { @@ -149,7 +182,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Send it off to the jpeg decoder J2KDecoder.BeginDecode(TextureID, m_asset, J2KDecodedCallback); } - } else { @@ -208,7 +240,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - private bool SendFirstPacket(LLClientView client) + private bool SendFirstPacket(IClientAPI client) { if (client == null) return false; @@ -243,7 +275,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return false; } - private bool SendPacket(LLClientView client) + private bool SendPacket(IClientAPI client) { if (client == null) return false; @@ -328,14 +360,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (m_currentPacket == 0) return 0; + if (m_currentPacket == 1) return FIRST_PACKET_SIZE; int result = FIRST_PACKET_SIZE + ((int)m_currentPacket - 2) * IMAGE_PACKET_SIZE; + if (result < 0) - { result = FIRST_PACKET_SIZE; - } + return result; } @@ -372,9 +405,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void AssetReceived(string id, Object sender, AssetBase asset) { +// m_log.DebugFormat( +// "[J2KIMAGE]: Received asset {0} ({1} bytes)", id, asset != null ? asset.Data.Length.ToString() : "n/a"); + UUID assetID = UUID.Zero; if (asset != null) + { assetID = asset.FullID; + } else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule)) { // Unfortunately we need this here, there's no other way. @@ -395,7 +433,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } AssetDataCallback(assetID, asset); - } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index fe28ba3f28..a7bf06d7a2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -219,6 +219,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public event BakeTerrain OnBakeTerrain; public event RequestTerrain OnUploadTerrain; public event EstateChangeInfo OnEstateChangeInfo; + public event EstateManageTelehub OnEstateManageTelehub; public event EstateRestartSimRequest OnEstateRestartSimRequest; public event EstateChangeCovenantRequest OnEstateChangeCovenantRequest; public event UpdateEstateAccessDeltaRequest OnUpdateEstateAccessDeltaRequest; @@ -304,6 +305,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected static Dictionary PacketHandlers = new Dictionary(); //Global/static handlers for all clients + /// + /// Handles UDP texture download. + /// + public LLImageManager ImageManager { get; private set; } + private readonly LLUDPServer m_udpServer; private readonly LLUDPClient m_udpClient; private readonly UUID m_sessionId; @@ -348,7 +354,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers protected Scene m_scene; - private LLImageManager m_imageManager; protected string m_firstName; protected string m_lastName; protected Thread m_clientThread; @@ -459,7 +464,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_assetService = m_scene.RequestModuleInterface(); m_GroupsModule = scene.RequestModuleInterface(); - m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); + ImageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion()); m_agentId = agentId; m_sessionId = sessionId; @@ -499,7 +504,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP IsActive = false; // Shutdown the image manager - m_imageManager.Close(); + ImageManager.Close(); // Fire the callback for this connection closing if (OnConnectionClosed != null) @@ -577,7 +582,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Add a handler for the given packet type. /// /// - /// The packet is handled on its own thread. If packets must be handled in the order in which thye + /// The packet is handled on its own thread. If packets must be handled in the order in which they /// are received then please use the synchronous version of this method. /// /// @@ -758,9 +763,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(handshake, ThrottleOutPacketType.Task); } - /// - /// - /// public void MoveAgentIntoRegion(RegionInfo regInfo, Vector3 pos, Vector3 look) { AgentMovementCompletePacket mov = (AgentMovementCompletePacket)PacketPool.Instance.GetPacket(PacketType.AgentMovementComplete); @@ -3476,6 +3478,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendAppearance(UUID agentID, byte[] visualParams, byte[] textureEntry) { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending avatar appearance for {0} with {1} bytes to {2} {3}", +// agentID, textureEntry.Length, Name, AgentId); + AvatarAppearancePacket avp = (AvatarAppearancePacket)PacketPool.Instance.GetPacket(PacketType.AvatarAppearance); // TODO: don't create new blocks if recycling an old packet avp.VisualParam = new AvatarAppearancePacket.VisualParamBlock[218]; @@ -3497,7 +3503,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendAnimations(UUID[] animations, int[] seqs, UUID sourceAgentId, UUID[] objectIDs) { - //m_log.DebugFormat("[CLIENT]: Sending animations to {0}", Name); +// m_log.DebugFormat("[LLCLIENTVIEW]: Sending animations for {0} to {1}", sourceAgentId, Name); AvatarAnimationPacket ani = (AvatarAnimationPacket)PacketPool.Instance.GetPacket(PacketType.AvatarAnimation); // TODO: don't create new blocks if recycling an old packet @@ -3532,6 +3538,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void SendAvatarDataImmediate(ISceneEntity avatar) { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", +// avatar.Name, avatar.UUID, Name, AgentId); + ScenePresence presence = avatar as ScenePresence; if (presence == null) return; @@ -3541,7 +3551,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP objupdate.RegionData.RegionHandle = presence.RegionHandle; objupdate.RegionData.TimeDilation = ushort.MaxValue; - + objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); @@ -3939,7 +3949,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if ((categories & ThrottleOutPacketTypeFlags.Texture) != 0) - m_imageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); + ImageManager.ProcessImageQueue(m_udpServer.TextureSendLimit); } public void SendAssetUploadCompleteMessage(sbyte AssetType, bool Success, UUID AssetFullID) @@ -4473,6 +4483,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(packet, ThrottleOutPacketType.Task); } + public void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List SpawnPoint) + { + TelehubInfoPacket packet = (TelehubInfoPacket)PacketPool.Instance.GetPacket(PacketType.TelehubInfo); + packet.TelehubBlock.ObjectID = ObjectID; + packet.TelehubBlock.ObjectName = Utils.StringToBytes(ObjectName); + packet.TelehubBlock.TelehubPos = ObjectPos; + packet.TelehubBlock.TelehubRot = ObjectRot; + + packet.SpawnPointBlock = new TelehubInfoPacket.SpawnPointBlockBlock[SpawnPoint.Count]; + for (int n = 0; n < SpawnPoint.Count; n++) + { + packet.SpawnPointBlock[n] = new TelehubInfoPacket.SpawnPointBlockBlock{SpawnPointPos = SpawnPoint[n]}; + } + + OutPacket(packet, ThrottleOutPacketType.Task); + } + #endregion #region Land Data Sending Methods @@ -7470,7 +7497,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((ImageType)block.Type == ImageType.Baked) args.Priority *= 2.0f; - m_imageManager.EnqueueReq(args); + ImageManager.EnqueueReq(args); } return true; @@ -8911,7 +8938,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool HandleEstateOwnerMessage(IClientAPI sender, Packet Pack) { EstateOwnerMessagePacket messagePacket = (EstateOwnerMessagePacket)Pack; - //m_log.Debug(messagePacket.ToString()); + // m_log.InfoFormat("[LLCLIENTVIEW]: Packet: {0}", Utils.BytesToString(messagePacket.MethodData.Method)); GodLandStatRequest handlerLandStatRequest; #region Packet Session and User Check @@ -9210,6 +9237,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP } return true; + case "telehub": + if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) + { + UUID invoice = messagePacket.MethodData.Invoice; + UUID SenderID = messagePacket.AgentData.AgentID; + UInt32 param1 = 0u; + + string command = (string)Utils.BytesToString(messagePacket.ParamList[0].Parameter); + + if (command != "info ui") + { + try + { + param1 = Convert.ToUInt32(Utils.BytesToString(messagePacket.ParamList[1].Parameter)); + } + catch + { + } + } + + EstateManageTelehub handlerEstateManageTelehub = OnEstateManageTelehub; + if (handlerEstateManageTelehub != null) + { + handlerEstateManageTelehub(this, invoice, SenderID, command, param1); + } + } + return true; + default: m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); return true; @@ -9221,8 +9276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP //lsrp.RequestData.ReportType; // 1 = colliders, 0 = scripts //lsrp.RequestData.RequestFlags; //lsrp.RequestData.Filter; - -// return true; } private bool HandleRequestRegionInfo(IClientAPI sender, Packet Pack) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs index e3a881f790..073c357d1a 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLImageManager.cs @@ -55,18 +55,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private bool m_shuttingdown; private AssetBase m_missingImage; - private LLClientView m_client; //Client we're assigned to - private IAssetService m_assetCache; //Asset Cache - private IJ2KDecoder m_j2kDecodeModule; //Our J2K module + private IAssetService m_assetCache; + private IJ2KDecoder m_j2kDecodeModule; + + /// + /// Priority queue for determining which image to send first. + /// private C5.IntervalHeap m_priorityQueue = new C5.IntervalHeap(10, new J2KImageComparer()); + + /// + /// Used to control thread access to the priority queue. + /// private object m_syncRoot = new object(); - public LLClientView Client { get { return m_client; } } + /// + /// Client served by this image manager + /// + public IClientAPI Client { get; private set; } + public AssetBase MissingImage { get { return m_missingImage; } } - public LLImageManager(LLClientView client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) + public LLImageManager(IClientAPI client, IAssetService pAssetCache, IJ2KDecoder pJ2kDecodeModule) { - m_client = client; + Client = client; m_assetCache = pAssetCache; if (pAssetCache != null) @@ -84,7 +95,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void EnqueueReq(TextureRequestArgs newRequest) { - //Make sure we're not shutting down.. if (!m_shuttingdown) { J2KImage imgrequest; @@ -99,19 +109,23 @@ namespace OpenSim.Region.ClientStack.LindenUDP { //m_log.Debug("[TEX]: (CAN) ID=" + newRequest.RequestedAssetID); - try + try { lock (m_syncRoot) - m_priorityQueue.Delete(imgrequest.PriorityQueueHandle); + m_priorityQueue.Delete(imgrequest.PriorityQueueHandle); } catch (Exception) { } } else { - //m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", - // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Received duplicate of existing request for {0}, start packet {1} from {2}", +// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); - //Check the packet sequence to make sure this isn't older than +// m_log.DebugFormat("[TEX]: (UPD) ID={0}: D={1}, S={2}, P={3}", +// newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); + + //Check the packet sequence to make sure this isn't older than //one we've already received if (newRequest.requestSequence > imgrequest.LastSequence) { @@ -126,11 +140,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Update the requested priority imgrequest.Priority = newRequest.Priority; + UpdateImageInQueue(imgrequest); - //Run an update imgrequest.RunUpdate(); + +// J2KImage imgrequest2 = new J2KImage(this); +// imgrequest2.J2KDecoder = m_j2kDecodeModule; +// imgrequest2.AssetService = m_assetCache; +// imgrequest2.AgentID = m_client.AgentId; +// imgrequest2.InventoryAccessModule = m_client.Scene.RequestModuleInterface(); +// imgrequest2.DiscardLevel = newRequest.DiscardLevel; +// imgrequest2.StartPacket = Math.Max(1, newRequest.PacketNumber); +// imgrequest2.Priority = newRequest.Priority; +// imgrequest2.TextureID = newRequest.RequestedAssetID; +// imgrequest2.Priority = newRequest.Priority; +// +// //Add this download to the priority queue +// AddImageToQueue(imgrequest2); +// +// imgrequest2.RunUpdate(); + } +// else +// { +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Ignoring duplicate of existing request for {0} (sequence {1}) from {2} as its request sequence {3} is not greater", +// newRequest.RequestedAssetID, imgrequest.LastSequence, m_client.Name, newRequest.requestSequence); +// } } } else @@ -142,14 +179,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else { +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Received request for {0}, start packet {1} from {2}", +// newRequest.RequestedAssetID, newRequest.PacketNumber, m_client.Name); + //m_log.DebugFormat("[TEX]: (NEW) ID={0}: D={1}, S={2}, P={3}", // newRequest.RequestedAssetID, newRequest.DiscardLevel, newRequest.PacketNumber, newRequest.Priority); imgrequest = new J2KImage(this); imgrequest.J2KDecoder = m_j2kDecodeModule; imgrequest.AssetService = m_assetCache; - imgrequest.AgentID = m_client.AgentId; - imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface(); + imgrequest.AgentID = Client.AgentId; + imgrequest.InventoryAccessModule = Client.Scene.RequestModuleInterface(); imgrequest.DiscardLevel = newRequest.DiscardLevel; imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); imgrequest.Priority = newRequest.Priority; @@ -159,7 +200,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP //Add this download to the priority queue AddImageToQueue(imgrequest); - //Run an update imgrequest.RunUpdate(); } } @@ -176,12 +216,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If null was returned, the texture priority queue is currently empty if (image == null) - return false; + break; if (image.IsDecoded) { int sent; - bool imageDone = image.SendPackets(m_client, packetsToSend - packetsSent, out sent); + bool imageDone = image.SendPackets(Client, packetsToSend - packetsSent, out sent); packetsSent += sent; // If the send is complete, destroy any knowledge of this transfer @@ -194,10 +234,17 @@ namespace OpenSim.Region.ClientStack.LindenUDP // written. Undecoded textures should not be going into the priority // queue, because a high priority undecoded texture will clog up the // pipeline for a client - return true; +// m_log.DebugFormat( +// "[LL IMAGE MANAGER]: Exiting image queue processing early on encountering undecoded image {0}", +// image.TextureID); + + break; } } +// if (packetsSent != 0) +// m_log.DebugFormat("[LL IMAGE MANAGER]: Processed {0} packets from image queue", packetsSent); + return m_priorityQueue.Count > 0; } @@ -209,6 +256,36 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_shuttingdown = true; } + /// + /// Clear the image queue. + /// + /// The number of requests cleared. + public int ClearImageQueue() + { + int requestsDeleted; + + lock (m_priorityQueue) + { + requestsDeleted = m_priorityQueue.Count; + + // Surprisingly, there doesn't seem to be a clear method at this time. + while (!m_priorityQueue.IsEmpty) + m_priorityQueue.DeleteMax(); + } + + return requestsDeleted; + } + + /// + /// Returns an array containing all the images in the queue. + /// + /// + public J2KImage[] GetImages() + { + lock (m_priorityQueue) + return m_priorityQueue.ToArray(); + } + #region Priority Queue Helpers private J2KImage GetHighestPriorityImage() @@ -219,7 +296,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (m_priorityQueue.Count > 0) { - try { image = m_priorityQueue.FindMax(); } + try + { + image = m_priorityQueue.FindMax(); + } catch (Exception) { } } } @@ -232,7 +312,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_syncRoot) { - try { m_priorityQueue.Add(ref image.PriorityQueueHandle, image); } + try + { + m_priorityQueue.Add(ref image.PriorityQueueHandle, image); + } catch (Exception) { } } } @@ -241,7 +324,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (m_syncRoot) { - try { m_priorityQueue.Delete(image.PriorityQueueHandle); } + try + { + m_priorityQueue.Delete(image.PriorityQueueHandle); + } catch (Exception) { } } } @@ -250,7 +336,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP { lock (m_syncRoot) { - try { m_priorityQueue.Replace(image.PriorityQueueHandle, image); } + try + { + m_priorityQueue.Replace(image.PriorityQueueHandle, image); + } catch (Exception) { image.PriorityQueueHandle = null; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index 5610c099eb..7b1aa2cf90 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -492,6 +492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((Environment.TickCount & Int32.MaxValue) - udpClient.TickLastPacketReceived > 1000 * 60) { m_log.Warn("[LLUDPSERVER]: Ack timeout, disconnecting " + udpClient.AgentID); + StatsManager.SimExtraStats.AddAbnormalClientThreadTermination(); RemoveClient(udpClient); return; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs new file mode 100644 index 0000000000..1b68d68765 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/LLImageManagerTests.cs @@ -0,0 +1,160 @@ +/* + * 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.IO; +using System.Net; +using System.Reflection; +using log4net.Config; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Packets; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Agent.TextureSender; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.ClientStack.LindenUDP.Tests +{ + [TestFixture] + public class LLImageManagerTests + { + private AssetBase m_testImageAsset; + private Scene scene; + private LLImageManager llim; + private TestClient tc; + + [TestFixtureSetUp] + public void FixtureInit() + { + using ( + Stream resource + = GetType().Assembly.GetManifestResourceStream( + "OpenSim.Region.ClientStack.LindenUDP.Tests.Resources.4-tile2.jp2")) + { + using (BinaryReader br = new BinaryReader(resource)) + { + m_testImageAsset + = new AssetBase( + TestHelpers.ParseTail(0x1), + "Test Image", + (sbyte)AssetType.Texture, + TestHelpers.ParseTail(0x2).ToString()); + + m_testImageAsset.Data = br.ReadBytes(99999999); + } + } + } + + [SetUp] + public void SetUp() + { + UUID userId = TestHelpers.ParseTail(0x3); + + J2KDecoderModule j2kdm = new J2KDecoderModule(); + + scene = SceneHelpers.SetupScene(); + SceneHelpers.SetupSceneModules(scene, j2kdm); + + tc = new TestClient(SceneHelpers.GenerateAgentData(userId), scene); + llim = new LLImageManager(tc, scene.AssetService, j2kdm); + } + + [Test] + public void TestSendImage() + { + TestHelpers.InMethod(); +// XmlConfigurator.Configure(); + + scene.AssetService.Store(m_testImageAsset); + + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = m_testImageAsset.FullID; + args.DiscardLevel = 0; + args.PacketNumber = 1; + args.Priority = 5; + args.requestSequence = 1; + + llim.EnqueueReq(args); + llim.ProcessImageQueue(20); + + Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(1)); + } + + [Test] + public void TestDiscardImage() + { + TestHelpers.InMethod(); +// XmlConfigurator.Configure(); + + scene.AssetService.Store(m_testImageAsset); + + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = m_testImageAsset.FullID; + args.DiscardLevel = 0; + args.PacketNumber = 1; + args.Priority = 5; + args.requestSequence = 1; + llim.EnqueueReq(args); + + // Now create a discard request + TextureRequestArgs discardArgs = new TextureRequestArgs(); + discardArgs.RequestedAssetID = m_testImageAsset.FullID; + discardArgs.DiscardLevel = -1; + discardArgs.PacketNumber = 1; + discardArgs.Priority = 0; + discardArgs.requestSequence = 2; + llim.EnqueueReq(discardArgs); + + llim.ProcessImageQueue(20); + + Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); + } + + [Test] + public void TestMissingImage() + { + TestHelpers.InMethod(); +// XmlConfigurator.Configure(); + + TextureRequestArgs args = new TextureRequestArgs(); + args.RequestedAssetID = m_testImageAsset.FullID; + args.DiscardLevel = 0; + args.PacketNumber = 1; + args.Priority = 5; + args.requestSequence = 1; + + llim.EnqueueReq(args); + llim.ProcessImageQueue(20); + + Assert.That(tc.SentImageDataPackets.Count, Is.EqualTo(0)); + Assert.That(tc.SentImageNotInDatabasePackets.Count, Is.EqualTo(1)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/Resources/4-tile2.jp2 b/OpenSim/Region/ClientStack/Linden/UDP/Tests/Resources/4-tile2.jp2 new file mode 100644 index 0000000000..8c631046e8 Binary files /dev/null and b/OpenSim/Region/ClientStack/Linden/UDP/Tests/Resources/4-tile2.jp2 differ diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index a28d5d7611..95e3aeceb1 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -246,7 +246,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (mm != null) { - if (!mm.UploadCovered(remoteClient, mm.UploadCharge)) + if (!mm.UploadCovered(remoteClient.AgentId, mm.UploadCharge)) { remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); return; diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs index 7dd90874b6..a1a250176d 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs @@ -103,6 +103,10 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender // If it's cached, return the cached results if (m_decodedCache.TryGetValue(assetID, out result)) { +// m_log.DebugFormat( +// "[J2KDecoderModule]: Returning existing cached {0} layers j2k decode for {1}", +// result.Length, assetID); + callback(assetID, result); } else @@ -129,18 +133,20 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender // Do Decode! if (decode) - DoJ2KDecode(assetID, j2kData); + Decode(assetID, j2kData); } } - /// - /// Provides a synchronous decode so that caller can be assured that this executes before the next line - /// - /// - /// - public void Decode(UUID assetID, byte[] j2kData) + public bool Decode(UUID assetID, byte[] j2kData) { - DoJ2KDecode(assetID, j2kData); + OpenJPEG.J2KLayerInfo[] layers; + int components; + return Decode(assetID, j2kData, out layers, out components); + } + + public bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components) + { + return DoJ2KDecode(assetID, j2kData, out layers, out components); } #endregion IJ2KDecoder @@ -150,14 +156,21 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender /// /// UUID of Asset /// JPEG2000 data - private void DoJ2KDecode(UUID assetID, byte[] j2kData) + /// layer data + /// number of components + /// true if decode was successful. false otherwise. + private bool DoJ2KDecode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components) { // m_log.DebugFormat( // "[J2KDecoderModule]: Doing J2K decoding of {0} bytes for asset {1}", j2kData.Length, assetID); + bool decodedSuccessfully = true; + //int DecodeTime = 0; //DecodeTime = Environment.TickCount; - OpenJPEG.J2KLayerInfo[] layers; + + // We don't get this from CSJ2K. Is it relevant? + components = 0; if (!TryLoadCacheForAsset(assetID, out layers)) { @@ -192,14 +205,15 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender catch (Exception ex) { m_log.Warn("[J2KDecoderModule]: CSJ2K threw an exception decoding texture " + assetID + ": " + ex.Message); + decodedSuccessfully = false; } } else { - int components; if (!OpenJPEG.DecodeLayerBoundaries(j2kData, out layers, out components)) { m_log.Warn("[J2KDecoderModule]: OpenJPEG failed to decode texture " + assetID); + decodedSuccessfully = false; } } @@ -208,6 +222,7 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender m_log.Warn("[J2KDecoderModule]: Failed to decode layer data for texture " + assetID + ", guessing sane defaults"); // Layer decoding completely failed. Guess at sane defaults for the layer boundaries layers = CreateDefaultLayers(j2kData.Length); + decodedSuccessfully = false; } // Cache Decoded layers @@ -227,6 +242,8 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender m_notifyList.Remove(assetID); } } + + return decodedSuccessfully; } private OpenJPEG.J2KLayerInfo[] CreateDefaultLayers(int j2kLength) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 280fdc7adb..7086e6c331 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -148,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } - public void SaveChangedAttachments(IScenePresence sp) + public void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted) { // m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); @@ -157,13 +157,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments foreach (SceneObjectGroup grp in sp.GetAttachments()) { -// if (grp.HasGroupChanged) // Resizer scripts? -// { - grp.IsAttachment = false; - grp.AbsolutePosition = grp.RootPart.AttachedPos; - UpdateKnownItem(sp, grp); - grp.IsAttachment = true; -// } + grp.IsAttachment = false; + grp.AbsolutePosition = grp.RootPart.AttachedPos; + UpdateKnownItem(sp, grp, saveAllScripted); + grp.IsAttachment = true; } } @@ -460,9 +457,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments /// /// /// - private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp) + private void UpdateKnownItem(IScenePresence sp, SceneObjectGroup grp, bool saveAllScripted) { - if (grp.HasGroupChanged || grp.ContainsScripts()) + // Saving attachments for NPCs messes them up for the real owner! + INPCModule module = m_scene.RequestModuleInterface(); + if (module != null) + { + if (module.IsNPC(sp.UUID, m_scene)) + return; + } + + if (grp.HasGroupChanged || (saveAllScripted && grp.ContainsScripts())) { m_log.DebugFormat( "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", @@ -495,6 +500,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (sp.ControllingClient != null) sp.ControllingClient.SendInventoryItemCreateUpdate(item, 0); } + grp.HasGroupChanged = false; // Prevent it being saved over and over } else { @@ -688,7 +694,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments group.IsAttachment = false; group.AbsolutePosition = group.RootPart.AttachedPos; - UpdateKnownItem(sp, group); + UpdateKnownItem(sp, group, true); m_scene.DeleteSceneObject(group, false); return; diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index e8aee3eafe..8d503bd7e6 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -149,14 +149,15 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Process the baked texture array if (textureEntry != null) { - m_log.InfoFormat("[AVFACTORY]: received texture update for {0}", sp.UUID); + m_log.InfoFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); // WriteBakedTexturesReport(sp, m_log.DebugFormat); changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; // WriteBakedTexturesReport(sp, m_log.DebugFormat); - ValidateBakedTextureCache(sp, false); + if (!ValidateBakedTextureCache(sp)) + RequestRebake(sp, true); // This appears to be set only in the final stage of the appearance // update transaction. In theory, we should be able to do an immediate @@ -250,15 +251,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return true; } - /// - /// Check for the existence of the baked texture assets. - /// - /// - public bool ValidateBakedTextureCache(IScenePresence sp) - { - return ValidateBakedTextureCache(sp, true); - } - /// /// Queue up a request to send appearance. /// @@ -292,17 +284,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory } } - #endregion - - #region AvatarFactoryModule private methods - - /// - /// Check for the existence of the baked texture assets. Request a rebake - /// unless checkonly is true. - /// - /// - /// - private bool ValidateBakedTextureCache(IScenePresence sp, bool checkonly) + public bool ValidateBakedTextureCache(IScenePresence sp) { bool defonly = true; // are we only using default textures @@ -330,24 +312,66 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory defonly = false; // found a non-default texture reference if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - { - if (checkonly) - return false; - - m_log.DebugFormat( - "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", - face.TextureID, idx, sp.Name); - - sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID); - } + return false; } - m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0}", sp.UUID); + m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); // If we only found default textures, then the appearance is not cached return (defonly ? false : true); } + public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) + { + int texturesRebaked = 0; + + for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) + { + int idx = AvatarAppearance.BAKE_INDICES[i]; + Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; + + // if there is no texture entry, skip it + if (face == null) + continue; + +// m_log.DebugFormat( +// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", +// face.TextureID, idx, client.Name, client.AgentId); + + // if the texture is one of the "defaults" then skip it + // this should probably be more intelligent (skirt texture doesnt matter + // if the avatar isnt wearing a skirt) but if any of the main baked + // textures is default then the rest should be as well + if (face.TextureID == UUID.Zero || face.TextureID == AppearanceManager.DEFAULT_AVATAR_TEXTURE) + continue; + + if (missingTexturesOnly) + { + if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + continue; + else + m_log.DebugFormat( + "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", + face.TextureID, idx, sp.Name); + } + else + { + m_log.DebugFormat( + "[AVFACTORY]: Requesting rebake of {0} ({1}) for {2}.", + face.TextureID, idx, sp.Name); + } + + texturesRebaked++; + sp.ControllingClient.SendRebakeAvatarTextures(face.TextureID); + } + + return texturesRebaked; + } + + #endregion + + #region AvatarFactoryModule private methods + private Dictionary GetBakedTextureFaces(ScenePresence sp) { if (sp.IsChildAgent) @@ -602,4 +626,4 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory outputAction("{0} baked appearance texture is {1}", sp.Name, bakedTextureValid ? "OK" : "corrupt"); } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index a77646c2e9..9c53fc4ac8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -496,13 +496,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends string agentFriendService = string.Empty; string friendFriendService = string.Empty; - if (agentIsLocal) + if (agentClient != null) { agentClientCircuit = ((Scene)(agentClient.Scene)).AuthenticateHandler.GetAgentCircuitData(agentClient.CircuitCode); agentUUI = Util.ProduceUserUniversalIdentifier(agentClientCircuit); agentFriendService = agentClientCircuit.ServiceURLs["FriendsServerURI"].ToString(); } - if (friendIsLocal) + if (friendClient != null) { friendClientCircuit = ((Scene)(friendClient.Scene)).AuthenticateHandler.GetAgentCircuitData(friendClient.CircuitCode); friendUUI = Util.ProduceUserUniversalIdentifier(friendClientCircuit); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 6b247180d8..ee10d04ee1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -493,7 +493,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } else { - sceneObjects.Add(SceneObjectSerializer.FromOriginalXmlFormat(xmlData)); + SceneObjectGroup deserializedObject = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + + if (deserializedObject != null) + sceneObjects.Add(deserializedObject); } foreach (SceneObjectGroup sog in sceneObjects) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index e0b02aac46..150d913a0a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -122,12 +122,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "save iar", - "save iar [--p|-profile=] [--noassets] [] [--v|-verbose]", + "save iar [-h|--home=] [--noassets] [] [--v|-verbose]", "Save user inventory archive (IAR).", " is the user's first name." + Environment.NewLine + " is the user's last name." + Environment.NewLine + " is the path inside the user's inventory for the folder/item to be saved." + Environment.NewLine - + "-p|--profile= adds the url of the profile service to the saved user information." + Environment.NewLine + + "-h|--home= adds the url of the profile service to the saved user information." + Environment.NewLine + "-c|--creators preserves information about foreign creators." + Environment.NewLine + "-v|--verbose extra debug messages." + Environment.NewLine + "--noassets stops assets being saved to the IAR." diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index cbef6ce47b..928bcd0c81 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -208,8 +208,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer foreach (SceneObjectGroup grp in sp.GetAttachments()) { - if (grp.IsDeleted) - sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); + sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); } } else // Another region possibly in another simulator diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 8d41728880..38a7805b3d 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -348,7 +348,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer region.ExternalHostName = uri.Host; region.HttpPort = (uint)uri.Port; - region.ServerURI = uri.ToString(); + region.ServerURI = aCircuit.ServiceURLs["HomeURI"].ToString(); region.RegionName = string.Empty; region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), (int)0); return region; diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index d20c9eb0a0..eaadc1b8be 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -55,16 +55,16 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // private Dictionary m_inventoryServers = new Dictionary(); private Scene m_scene; - private string m_ProfileServerURI; + private string m_HomeURI; #endregion #region Constructor - public HGAssetMapper(Scene scene, string profileURL) + public HGAssetMapper(Scene scene, string homeURL) { m_scene = scene; - m_ProfileServerURI = profileURL; + m_HomeURI = homeURL; } #endregion @@ -150,7 +150,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess UUID.TryParse(meta.CreatorID, out uuid); UserAccount creator = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); if (creator != null) - meta.CreatorID = m_ProfileServerURI + "/" + meta.CreatorID + ";" + creator.FirstName + " " + creator.LastName; + meta.CreatorID = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName; } } @@ -193,7 +193,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (!hasCreatorData && creator != null) { XmlElement creatorData = doc.CreateElement("CreatorData"); - creatorData.InnerText = m_ProfileServerURI + "/" + creator.PrincipalID + ";" + creator.FirstName + " " + creator.LastName; + creatorData.InnerText = m_HomeURI + ";" + creator.FirstName + " " + creator.LastName; sop.AppendChild(creatorData); } } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index bf24ebc66a..0c4ff7f81d 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -54,7 +54,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess get { return m_assMapper; } } - private string m_ProfileServerURI; + private string m_HomeURI; private bool m_OutboundPermission; private string m_ThisGatekeeper; @@ -84,7 +84,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess IConfig thisModuleConfig = source.Configs["HGInventoryAccessModule"]; if (thisModuleConfig != null) { - m_ProfileServerURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); + // legacy configuration [obsolete] + m_HomeURI = thisModuleConfig.GetString("ProfileServerURI", string.Empty); + // preferred + m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); } @@ -100,7 +103,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return; base.AddRegion(scene); - m_assMapper = new HGAssetMapper(scene, m_ProfileServerURI); + m_assMapper = new HGAssetMapper(scene, m_HomeURI); scene.EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem; } diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 37292d66fd..b4f6b5acc6 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -50,9 +50,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public string LastName { get; set; } public string HomeURL { get; set; } public Dictionary ServerURLs { get; set; } - public string Title { get; set; } - public int Flags { get; set; } - public int Created { get; set; } } public class UserManagementModule : ISharedRegionModule, IUserManagement @@ -284,94 +281,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement return string.Empty; } - public int GetUserFlags(UUID userID) - { - UserData userdata; - lock (m_UserCache) - m_UserCache.TryGetValue(userID, out userdata); - - if (userdata.Flags == -1) - GetUserInfo(userID); - - if (userdata.Flags != -1) - return userdata.Flags; - - return 0; - } - - public int GetUserCreated(UUID userID) - { - UserData userdata; - lock (m_UserCache) - m_UserCache.TryGetValue(userID, out userdata); - - if (userdata.Flags == -1) - GetUserInfo(userID); - - if (userdata.Created != -1) - return userdata.Created; - - return 0; - } - - public string GetUserTitle(UUID userID) - { - UserData userdata; - lock (m_UserCache) - m_UserCache.TryGetValue(userID, out userdata); - - if (userdata.Flags == -1) - GetUserInfo(userID); - - if (userdata.Created != -1) - return userdata.Title; - - return string.Empty; - } - - // This will cache the user data - // Change this to return bool - private bool GetUserInfo(UUID userID) - { - UserData userdata; - lock (m_UserCache) - m_UserCache.TryGetValue(userID, out userdata); - - if (userdata != null) - { -// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Requested url type {0} for {1}", serverType, userID); - - if (userdata.Flags >= 0) - { - // This is already populated - return true; - } - - if (userdata.HomeURL != null && userdata.HomeURL != string.Empty) - { - m_log.DebugFormat( - "[USER MANAGEMENT MODULE]: Requesting user flags from '{0}' for {1}", - userdata.HomeURL, userID); - - UserAgentServiceConnector uConn = new UserAgentServiceConnector(userdata.HomeURL); - Dictionary info = uConn.GetUserInfo(userID); - - // Pull our data now - if (info["result"].ToString() == "success") - { - userdata.Flags = (int)info["user_flags"]; - userdata.Created = (int)info["user_created"]; - userdata.Title = (string)info["user_title"]; - - return true; - } - } - } - - return false; - } - - public string GetUserUUI(UUID userID) { UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, userID); @@ -413,68 +322,85 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement user.Id = uuid; user.FirstName = first; user.LastName = last; - // user.ProfileURL = we should initialize this to the default AddUserInternal(user); } - public void AddUser(UUID uuid, string first, string last, string profileURL) + public void AddUser(UUID uuid, string first, string last, string homeURL) { - AddUser(uuid, profileURL + ";" + first + " " + last); + AddUser(uuid, homeURL + ";" + first + " " + last); } - public void AddUser(UUID id, string creatorData) + public void AddUser (UUID id, string creatorData) { + UserData oldUser; + //lock the whole block - prevent concurrent update lock (m_UserCache) { - if (m_UserCache.ContainsKey(id)) - return; - } - -// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, craetorData {1}", id, creatorData); - - UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, id); - - if (account != null) - { - AddUser(id, account.FirstName, account.LastName); - } - else - { - UserData user = new UserData(); - user.Id = id; - user.Flags = -1; - user.Created = -1; - - if (creatorData != null && creatorData != string.Empty) + m_UserCache.TryGetValue (id, out oldUser); + if (oldUser != null) { - //creatorData = ; - - string[] parts = creatorData.Split(';'); - if (parts.Length >= 1) + if (creatorData == null || creatorData == String.Empty) { - user.HomeURL = parts[0]; - try - { - Uri uri = new Uri(parts[0]); - user.LastName = "@" + uri.Authority; - } - catch (UriFormatException) - { - m_log.DebugFormat("[SCENE]: Unable to parse Uri {0}", parts[0]); - user.LastName = "@unknown"; - } + //ignore updates without creator data + return; } - if (parts.Length >= 2) - user.FirstName = parts[1].Replace(' ', '.'); + //try update unknown users + //and creator's home URL's + if ((oldUser.FirstName == "Unknown" && !creatorData.Contains ("Unknown")) || (oldUser.HomeURL != null && !creatorData.StartsWith (oldUser.HomeURL))) + { + m_UserCache.Remove (id); +// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Re-adding user with id {0}, creatorData [{1}] and old HomeURL {2}", id, creatorData,oldUser.HomeURL); + } + else + { + //we have already a valid user within the cache + return; + } + } +// m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, creatorData {1}", id, creatorData); + + UserAccount account = m_Scenes [0].UserAccountService.GetUserAccount (m_Scenes [0].RegionInfo.ScopeID, id); + + if (account != null) + { + AddUser (id, account.FirstName, account.LastName); } else { - user.FirstName = "Unknown"; - user.LastName = "User"; - } + UserData user = new UserData (); + user.Id = id; - AddUserInternal(user); + if (creatorData != null && creatorData != string.Empty) + { + //creatorData = ; + + string[] parts = creatorData.Split (';'); + if (parts.Length >= 1) + { + user.HomeURL = parts [0]; + try + { + Uri uri = new Uri (parts [0]); + user.LastName = "@" + uri.Authority; + } + catch (UriFormatException) + { + m_log.DebugFormat ("[SCENE]: Unable to parse Uri {0}", parts [0]); + user.LastName = "@unknown"; + } + } + if (parts.Length >= 2) + user.FirstName = parts [1].Replace (' ', '.'); + } + else + { + user.FirstName = "Unknown"; + user.LastName = "User"; + } + + AddUserInternal (user); + } } } @@ -488,36 +414,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement // user.Id, user.FirstName, user.LastName, user.HomeURL); } - //public void AddUser(UUID uuid, string userData) - //{ - // if (m_UserCache.ContainsKey(uuid)) - // return; - - // UserData user = new UserData(); - // user.Id = uuid; - - // // userData = ; - // string[] parts = userData.Split(';'); - // if (parts.Length >= 1) - // user.ProfileURL = parts[0].Trim(); - // if (parts.Length >= 2) - // { - // string[] name = parts[1].Trim().Split(' '); - // if (name.Length >= 1) - // user.FirstName = name[0]; - // if (name.Length >= 2) - // user.LastName = name[1]; - // else - // user.LastName = "?"; - // } - - // lock (m_UserCache) - // m_UserCache.Add(uuid, user); - - // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", user.Id, user.FirstName, user.LastName, user.ProfileURL); - - //} - public bool IsLocalGridUser(UUID uuid) { UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid); diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 8fb5d75aec..d328eb37dc 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -29,6 +29,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Net; +using System.Net.Mail; using System.Net.Security; using System.Text; using System.Threading; @@ -111,21 +112,36 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest X509Chain chain, SslPolicyErrors sslPolicyErrors) { - HttpWebRequest Request = (HttpWebRequest)sender; - - if (Request.Headers.Get("NoVerifyCert") != null) + // If this is a web request we need to check the headers first + // We may want to ignore SSL + if (sender is HttpWebRequest) { + HttpWebRequest Request = (HttpWebRequest)sender; + ServicePoint sp = Request.ServicePoint; + + // We don't case about encryption, get out of here + if (Request.Headers.Get("NoVerifyCert") != null) + { + return true; + } + + // If there was an upstream cert verification error, bail + if ((((int)sslPolicyErrors) & ~4) != 0) + return false; + + // Check for policy and execute it if defined + if (ServicePointManager.CertificatePolicy != null) + { + return ServicePointManager.CertificatePolicy.CheckValidationResult (sp, certificate, Request, 0); + } + return true; } - + + // If it's not HTTP, trust .NET to check it if ((((int)sslPolicyErrors) & ~4) != 0) return false; - if (ServicePointManager.CertificatePolicy != null) - { - ServicePoint sp = Request.ServicePoint; - return ServicePointManager.CertificatePolicy.CheckValidationResult (sp, certificate, Request, 0); - } return true; } #region IHttpRequestModule Members diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 67d99e027a..93e75b3622 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -131,6 +131,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void RegionLoaded(Scene scene) { + IScriptModule[] scriptModules = scene.RequestModuleInterfaces(); + foreach (IScriptModule scriptModule in scriptModules) + { + scriptModule.OnScriptRemoved += ScriptRemoved; + scriptModule.OnObjectRemoved += ObjectRemoved; + } } public void RemoveRegion(Scene scene) @@ -160,7 +166,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp urlData.url = url; urlData.urlcode = urlcode; urlData.requests = new Dictionary(); - m_UrlMap[url] = urlData; @@ -276,6 +281,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void ScriptRemoved(UUID itemID) { +// m_log.DebugFormat("[URL MODULE]: Removing script {0}", itemID); + lock (m_UrlMap) { List removeURLs = new List(); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs index 985aceca5d..90fe69e18c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/LocalGridUserServiceConnector.cs @@ -171,6 +171,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser { return m_GridUserService.GetGridUserInfo(userID); } + public GridUserInfo[] GetGridUserInfo(string[] userID) + { + return m_GridUserService.GetGridUserInfo(userID); + } #endregion diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs index 95b3591ab4..badb5527fa 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs @@ -147,6 +147,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser return m_RemoteConnector.GetGridUserInfo(userID); } + public GridUserInfo[] GetGridUserInfo(string[] userID) + { + return m_RemoteConnector.GetGridUserInfo(userID); + } + #endregion } diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 587d260583..a6dbaba7d7 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -116,6 +116,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_merge = merge; m_skipAssets = skipAssets; m_requestId = requestId; + + // Zero can never be a valid user id + m_validUserUuids[UUID.Zero] = false; } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) @@ -125,6 +128,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_merge = merge; m_skipAssets = skipAssets; m_requestId = requestId; + + // Zero can never be a valid user id + m_validUserUuids[UUID.Zero] = false; } /// @@ -368,16 +374,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!m_validUserUuids.ContainsKey(uuid)) { UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); - if (account != null) - m_validUserUuids.Add(uuid, true); - else - m_validUserUuids.Add(uuid, false); + m_validUserUuids.Add(uuid, account != null); } - if (m_validUserUuids[uuid]) - return true; - else - return false; + return m_validUserUuids[uuid]; } /// @@ -404,6 +404,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver string extension = filename.Substring(i); string uuid = filename.Remove(filename.Length - extension.Length); + if (m_scene.AssetService.GetMetadata(uuid) != null) + { + // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); + return true; + } + if (ArchiveConstants.EXTENSION_TO_ASSET_TYPE.ContainsKey(extension)) { sbyte assetType = ArchiveConstants.EXTENSION_TO_ASSET_TYPE[extension]; diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index b895afe85d..ffcf063121 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -282,10 +282,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. if (permissionClass != PermissionClass.Owner) - { canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; - } - bool partPermitted = true; if (checkPermissions.Contains("C") && !canCopy) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index f44a3bac05..f5a5a8d1be 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -98,6 +98,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver OptionSet options = new OptionSet().Add("m|merge", delegate (string v) { mergeOar = v != null; }); options.Add("s|skip-assets", delegate (string v) { skipAssets = v != null; }); + + // Send a message to the region ready module + /* bluewall* Disable this for the time being + IRegionReadyModule rready = m_scene.RequestModuleInterface(); + + if (rready != null) + { + rready.OarLoadingAlert("load"); + } + */ List mainParams = options.Parse(cmdparams); @@ -125,9 +135,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver Dictionary options = new Dictionary(); OptionSet ops = new OptionSet(); -// ops.Add("v|version=", delegate(string v) { options["version"] = v; }); - ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); + + // legacy argument [obsolete] + ops.Add("p|profile=", delegate(string v) { Console.WriteLine("\n WARNING: -profile option is obsolete and it will not work. Use -home instead.\n"); }); + // preferred + ops.Add("h|home=", delegate(string v) { options["home"] = v; }); + ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); + ops.Add("publish", v => options["wipe-owners"] = v != null); ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); List mainParams = ops.Parse(cmdparams); diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index e798e5e361..63f1363729 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -248,9 +248,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Dictionary options = new Dictionary(); options.Add("noassets", true); m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); - //AssetServerBase assetServer = (AssetServerBase)scene.CommsManager.AssetCache.AssetServer; - //while (assetServer.HasWaitingRequests()) - // assetServer.ProcessNextRequest(); // Don't wait for completion - with --noassets save oar happens synchronously // Monitor.Wait(this, 60000); @@ -344,7 +341,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests { using (BinaryReader br = new BinaryReader(resource)) { - // FIXME: Use the inspector insteadthere are so many forums and lists already, though admittedly none of them are suitable for cross virtual-enivornemnt discussion + // FIXME: Use the inspector instead soundData = br.ReadBytes(99999999); UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); string soundAssetFileName @@ -409,6 +406,86 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); } + /// + /// Test loading an OpenSim Region Archive saved with the --publish option. + /// + [Test] + public void TestLoadPublishedOar() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + SceneObjectPart part1 = CreateSceneObjectPart1(); + SceneObjectGroup sog1 = new SceneObjectGroup(part1); + m_scene.AddNewSceneObject(sog1, false); + + SceneObjectPart part2 = CreateSceneObjectPart2(); + + AssetNotecard nc = new AssetNotecard(); + nc.BodyText = "Hello World!"; + nc.Encode(); + UUID ncAssetUuid = new UUID("00000000-0000-0000-1000-000000000000"); + UUID ncItemUuid = new UUID("00000000-0000-0000-1100-000000000000"); + AssetBase ncAsset + = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); + m_scene.AssetService.Store(ncAsset); + SceneObjectGroup sog2 = new SceneObjectGroup(part2); + TaskInventoryItem ncItem + = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; + part2.Inventory.AddInventoryItem(ncItem, true); + + m_scene.AddNewSceneObject(sog2, false); + + MemoryStream archiveWriteStream = new MemoryStream(); + m_scene.EventManager.OnOarFileSaved += SaveCompleted; + + Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); + + lock (this) + { + m_archiverModule.ArchiveRegion( + archiveWriteStream, requestId, new Dictionary() { { "wipe-owners", Boolean.TrueString } }); + + Monitor.Wait(this, 60000); + } + + Assert.That(m_lastRequestId, Is.EqualTo(requestId)); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + + { + UUID estateOwner = TestHelpers.ParseTail(0x4747); + UUID objectOwner = TestHelpers.ParseTail(0x15); + + // Reload to new scene + ArchiverModule archiverModule = new ArchiverModule(); + SerialiserModule serialiserModule = new SerialiserModule(); + TerrainModule terrainModule = new TerrainModule(); + + TestScene scene2 = SceneHelpers.SetupScene(); + SceneHelpers.SetupSceneModules(scene2, archiverModule, serialiserModule, terrainModule); + + // Make sure there's a valid owner for the owner we saved (this should have been wiped if the code is + // behaving correctly + UserAccountHelpers.CreateUserWithInventory(scene2, objectOwner); + + scene2.RegionInfo.EstateSettings.EstateOwner = estateOwner; + + lock (this) + { + scene2.EventManager.OnOarFileLoaded += LoadCompleted; + archiverModule.DearchiveRegion(archiveReadStream); + } + + Assert.That(m_lastErrorMessage, Is.Null); + + SceneObjectGroup loadedSog = scene2.GetSceneObjectGroup(part1.Name); + Assert.That(loadedSog.OwnerID, Is.EqualTo(estateOwner)); + Assert.That(loadedSog.LastOwnerID, Is.EqualTo(estateOwner)); + } + } + /// /// Test loading the region settings of an OpenSim Region Archive. /// diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 58d94557e7..2e1487f42b 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -53,6 +53,7 @@ namespace OpenSim.Region.CoreModules.World.Estate protected EstateManagementCommands m_commands; private EstateTerrainXferHandler TerrainUploader; + public TelehubManager m_Telehub; public event ChangeDelegate OnRegionInfoChange; public event ChangeDelegate OnEstateInfoChange; @@ -599,6 +600,50 @@ namespace OpenSim.Region.CoreModules.World.Estate } } + public void handleOnEstateManageTelehub (IClientAPI client, UUID invoice, UUID senderID, string cmd, uint param1) + { + uint ObjectLocalID; + SceneObjectPart part; + + switch (cmd) + { + case "info ui": + break; + + case "connect": + // Add the Telehub + part = Scene.GetSceneObjectPart((uint)param1); + if (part == null) + return; + SceneObjectGroup grp = part.ParentGroup; + + m_Telehub.Connect(grp); + break; + + case "delete": + // Disconnect Telehub + m_Telehub.Disconnect(); + break; + + case "spawnpoint add": + // Add SpawnPoint to the Telehub + part = Scene.GetSceneObjectPart((uint)param1); + if (part == null) + return; + m_Telehub.AddSpawnPoint(part.AbsolutePosition); + break; + + case "spawnpoint remove": + // Remove SpawnPoint from Telehub + m_Telehub.RemoveSpawnPoint((int)param1); + break; + + default: + break; + } + SendTelehubInfo(client); + } + private void SendSimulatorBlueBoxMessage( IClientAPI remote_client, UUID invoice, UUID senderID, UUID sessionID, string senderName, string message) { @@ -1055,7 +1100,9 @@ namespace OpenSim.Region.CoreModules.World.Estate Scene.RegisterModuleInterface(this); Scene.EventManager.OnNewClient += EventManager_OnNewClient; Scene.EventManager.OnRequestChangeWaterHeight += changeWaterHeight; - + + m_Telehub = new TelehubManager(scene); + m_commands = new EstateManagementCommands(this); m_commands.Initialise(); } @@ -1109,6 +1156,7 @@ namespace OpenSim.Region.CoreModules.World.Estate client.OnEstateRestartSimRequest += handleEstateRestartSimRequest; client.OnEstateChangeCovenantRequest += handleChangeEstateCovenantRequest; client.OnEstateChangeInfo += handleEstateChangeInfo; + client.OnEstateManageTelehub += handleOnEstateManageTelehub; client.OnUpdateEstateAccessDeltaRequest += handleEstateAccessDeltaRequest; client.OnSimulatorBlueBoxMessageRequest += SendSimulatorBlueBoxMessage; client.OnEstateBlueBoxMessageRequest += SendEstateBlueBoxMessage; @@ -1243,5 +1291,39 @@ namespace OpenSim.Region.CoreModules.World.Estate if (onmessage != null) onmessage(Scene.RegionInfo.RegionID, fromID, fromName, message); } + + + private void SendTelehubInfo(IClientAPI client) + { + RegionSettings settings = + this.Scene.RegionInfo.RegionSettings; + + SceneObjectGroup telehub = null; + if (settings.TelehubObject != UUID.Zero && + (telehub = Scene.GetSceneObjectGroup(settings.TelehubObject)) != null) + { + List spawnPoints = new List(); + + foreach (SpawnPoint sp in settings.SpawnPoints()) + { + spawnPoints.Add(sp.GetLocation(Vector3.Zero, Quaternion.Identity)); + } + + client.SendTelehubInfo(settings.TelehubObject, + telehub.Name, + telehub.AbsolutePosition, + telehub.GroupRotation, + spawnPoints); + } + else + { + client.SendTelehubInfo(UUID.Zero, + String.Empty, + Vector3.Zero, + Quaternion.Identity, + new List()); + } + } } } + diff --git a/OpenSim/Region/CoreModules/World/Estate/TelehubManager.cs b/OpenSim/Region/CoreModules/World/Estate/TelehubManager.cs new file mode 100644 index 0000000000..8bc831f221 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/TelehubManager.cs @@ -0,0 +1,95 @@ +/* + * 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 OpenMetaverse; +using System.Collections.Generic; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using log4net; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + public class TelehubManager + { + // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + Scene m_Scene; + + public TelehubManager(Scene scene) + { + m_Scene = scene; + } + + // Connect the Telehub + public void Connect(SceneObjectGroup grp) + { + m_Scene.RegionInfo.RegionSettings.ClearSpawnPoints(); + + m_Scene.RegionInfo.RegionSettings.TelehubObject = grp.UUID; + m_Scene.RegionInfo.RegionSettings.Save(); + } + + // Disconnect the Telehub: + public void Disconnect() + { + if (m_Scene.RegionInfo.RegionSettings.TelehubObject == UUID.Zero) + return; + + m_Scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; + m_Scene.RegionInfo.RegionSettings.ClearSpawnPoints(); + m_Scene.RegionInfo.RegionSettings.Save(); + } + + // Add a SpawnPoint to the Telehub + public void AddSpawnPoint(Vector3 point) + { + if (m_Scene.RegionInfo.RegionSettings.TelehubObject == UUID.Zero) + return; + + SceneObjectGroup grp = m_Scene.GetSceneObjectGroup(m_Scene.RegionInfo.RegionSettings.TelehubObject); + if (grp == null) + return; + + SpawnPoint sp = new SpawnPoint(); + sp.SetLocation(grp.AbsolutePosition, grp.GroupRotation, point); + m_Scene.RegionInfo.RegionSettings.AddSpawnPoint(sp); + m_Scene.RegionInfo.RegionSettings.Save(); + } + + // Remove a SpawnPoint from the Telehub + public void RemoveSpawnPoint(int spawnpoint) + { + if (m_Scene.RegionInfo.RegionSettings.TelehubObject == UUID.Zero) + return; + + m_Scene.RegionInfo.RegionSettings.RemoveSpawnPoint(spawnpoint); + m_Scene.RegionInfo.RegionSettings.Save(); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 0da0de3b64..79b13c3779 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -1094,7 +1094,16 @@ namespace OpenSim.Region.CoreModules.World.Land LandData.MusicURL = url; SendLandUpdateToAvatarsOverMe(); } - + + /// + /// Get the music url for this land parcel + /// + /// The music url. + public string GetMusicUrl() + { + return LandData.MusicURL; + } + #endregion } } diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs new file mode 100644 index 0000000000..e3d04cd669 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -0,0 +1,410 @@ +/* + * 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 System.Text; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Objects.Commands +{ + /// + /// A module that holds commands for manipulating objects in the scene. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "ObjectCommandsModule")] + public class ObjectCommandsModule : INonSharedRegionModule + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private ICommandConsole m_console; + + public string Name { get { return "Object Commands Module"; } } + + public Type ReplaceableInterface { get { return null; } } + + public void Initialise(IConfigSource source) + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: INITIALIZED MODULE"); + } + + public void PostInitialise() + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: POST INITIALIZED MODULE"); + } + + public void Close() + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: CLOSED MODULE"); + } + + public void AddRegion(Scene scene) + { +// m_log.DebugFormat("[OBJECT COMMANDS MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); + + m_scene = scene; + m_console = MainConsole.Instance; + + m_console.Commands.AddCommand("region", false, "delete object owner", + "delete object owner ", + "Delete a scene object by owner", HandleDeleteObject); + m_console.Commands.AddCommand("region", false, "delete object creator", + "delete object creator ", + "Delete a scene object by creator", HandleDeleteObject); + m_console.Commands.AddCommand("region", false, "delete object uuid", + "delete object uuid ", + "Delete a scene object by uuid", HandleDeleteObject); + m_console.Commands.AddCommand("region", false, "delete object name", + "delete object name ", + "Delete a scene object by name", HandleDeleteObject); + m_console.Commands.AddCommand("region", false, "delete object outside", + "delete object outside", + "Delete all scene objects outside region boundaries", HandleDeleteObject); + + m_console.Commands.AddCommand( + "region", + false, + "show object uuid", + "show object uuid ", + "Show details of a scene object with the given UUID", HandleShowObjectByUuid); + + m_console.Commands.AddCommand( + "region", + false, + "show object name", + "show object name ", + "Show details of scene objects with the given name", HandleShowObjectByName); + + m_console.Commands.AddCommand( + "region", + false, + "show part uuid", + "show part uuid ", + "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); + + m_console.Commands.AddCommand( + "region", + false, + "show part name", + "show part name ", + "Show details of scene object parts with the given name", HandleShowPartByName); + } + + public void RemoveRegion(Scene scene) + { +// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); + } + + public void RegionLoaded(Scene scene) + { +// m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); + } + + private void HandleShowObjectByUuid(string module, string[] cmd) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmd.Length < 4) + { + m_console.OutputFormat("Usage: show object uuid "); + return; + } + + UUID objectUuid; + if (!UUID.TryParse(cmd[3], out objectUuid)) + { + m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); + return; + } + + SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); + + if (so == null) + { +// m_console.OutputFormat("No part found with uuid {0}", objectUuid); + return; + } + + StringBuilder sb = new StringBuilder(); + AddSceneObjectReport(sb, so); + + m_console.OutputFormat(sb.ToString()); + } + + private void HandleShowObjectByName(string module, string[] cmd) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmd.Length < 4) + { + m_console.OutputFormat("Usage: show object name "); + return; + } + + string name = cmd[3]; + + List sceneObjects = new List(); + + m_scene.ForEachSOG(so => { if (so.Name == name) { sceneObjects.Add(so); }}); + + if (sceneObjects.Count == 0) + { + m_console.OutputFormat("No objects with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); + return; + } + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectGroup so in sceneObjects) + { + AddSceneObjectReport(sb, so); + sb.Append("\n"); + } + + m_console.OutputFormat(sb.ToString()); + } + + private void HandleShowPartByUuid(string module, string[] cmd) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmd.Length < 4) + { + m_console.OutputFormat("Usage: show part uuid "); + return; + } + + UUID objectUuid; + if (!UUID.TryParse(cmd[3], out objectUuid)) + { + m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); + return; + } + + SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); + + if (sop == null) + { +// m_console.OutputFormat("No part found with uuid {0}", objectUuid); + return; + } + + StringBuilder sb = new StringBuilder(); + AddScenePartReport(sb, sop); + + m_console.OutputFormat(sb.ToString()); + } + + private void HandleShowPartByName(string module, string[] cmd) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmd.Length < 4) + { + m_console.OutputFormat("Usage: show part name "); + return; + } + + string name = cmd[3]; + + List parts = new List(); + + m_scene.ForEachSOG(so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } })); + + if (parts.Count == 0) + { + m_console.OutputFormat("No parts with name {0} found in {1}", name, m_scene.RegionInfo.RegionName); + return; + } + + StringBuilder sb = new StringBuilder(); + + foreach (SceneObjectPart part in parts) + { + AddScenePartReport(sb, part); + sb.Append("\n"); + } + + m_console.OutputFormat(sb.ToString()); + } + + private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) + { + sb.AppendFormat("Name: {0}\n", so.Name); + sb.AppendFormat("Description: {0}\n", so.Description); + sb.AppendFormat("Location: {0} @ {1}\n", so.AbsolutePosition, so.Scene.RegionInfo.RegionName); + sb.AppendFormat("Parts: {0}\n", so.PrimCount); + + return sb; + } + + private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) + { + sb.AppendFormat("Name: {0}\n", sop.Name); + sb.AppendFormat("Description: {0}\n", sop.Description); + sb.AppendFormat("Location: {0} @ {1}\n", sop.AbsolutePosition, sop.ParentGroup.Scene.RegionInfo.RegionName); + sb.AppendFormat("Parent: {0}", + sop.IsRoot ? "Is Root\n" : string.Format("{0} {1}\n", sop.ParentGroup.Name, sop.ParentGroup.UUID)); + sb.AppendFormat("Parts: {0}\n", !sop.IsRoot ? "1" : sop.ParentGroup.PrimCount.ToString());; + + return sb; + } + + private void HandleDeleteObject(string module, string[] cmd) + { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return; + + if (cmd.Length < 3) + return; + + string mode = cmd[2]; + string o = ""; + + if (mode != "outside") + { + if (cmd.Length < 4) + return; + + o = cmd[3]; + } + + List deletes = new List(); + + UUID match; + + switch (mode) + { + case "owner": + if (!UUID.TryParse(o, out match)) + return; + + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.OwnerID == match && !g.IsAttachment) + deletes.Add(g); + }); + +// if (deletes.Count == 0) +// m_console.OutputFormat("No objects were found with owner {0}", match); + + break; + + case "creator": + if (!UUID.TryParse(o, out match)) + return; + + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.RootPart.CreatorID == match && !g.IsAttachment) + deletes.Add(g); + }); + +// if (deletes.Count == 0) +// m_console.OutputFormat("No objects were found with creator {0}", match); + + break; + + case "uuid": + if (!UUID.TryParse(o, out match)) + return; + + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.UUID == match && !g.IsAttachment) + deletes.Add(g); + }); + +// if (deletes.Count == 0) +// m_console.OutputFormat("No objects were found with uuid {0}", match); + + break; + + case "name": + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + if (g.RootPart.Name == o && !g.IsAttachment) + deletes.Add(g); + }); + +// if (deletes.Count == 0) +// m_console.OutputFormat("No objects were found with name {0}", o); + + break; + + case "outside": + m_scene.ForEachSOG(delegate (SceneObjectGroup g) + { + SceneObjectPart rootPart = g.RootPart; + bool delete = false; + + if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) + { + delete = true; + } + else + { + ILandObject parcel + = m_scene.LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y); + + if (parcel == null || parcel.LandData.Name == "NO LAND") + delete = true; + } + + if (delete && !g.IsAttachment && !deletes.Contains(g)) + deletes.Add(g); + }); + +// if (deletes.Count == 0) +// m_console.OutputFormat("No objects were found outside region bounds"); + + break; + } + + m_console.OutputFormat("Deleting {0} objects in {1}", deletes.Count, m_scene.RegionInfo.RegionName); + + foreach (SceneObjectGroup g in deletes) + { + m_console.OutputFormat("Deleting object {0} {1}", g.UUID, g.Name); + m_scene.DeleteSceneObject(g, false); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 9b0e2ffc79..6c6aa373a2 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -213,7 +213,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap UUID agentID, Caps caps) { //try - //{ + // //m_log.DebugFormat("[MAPLAYER]: path: {0}, param: {1}, agent:{2}", // path, param, agentID.ToString()); @@ -263,7 +263,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap foreach (GridRegion r in regions) { MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); + MapBlockFromGridRegion(block, r, 0); mapBlocks.Add(block); } avatarPresence.ControllingClient.SendMapBlock(mapBlocks, 0); @@ -373,7 +373,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap public virtual void HandleMapItemRequest(IClientAPI remoteClient, uint flags, uint EstateID, bool godlike, uint itemtype, ulong regionhandle) { -// m_log.DebugFormat("[WORLD MAP]: Handle MapItem request {0} {1}", regionhandle, itemtype); + m_log.DebugFormat("[WORLD MAP]: Handle MapItem request {0} {1}", regionhandle, itemtype); lock (m_rootAgents) { @@ -429,7 +429,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap // ensures that the blockingqueue doesn't get borked if the GetAgents() timing changes. RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); } - } else if (itemtype == 7) // Service 7 (MAP_ITEM_LAND_FOR_SALE) + } + else if (itemtype == 7) // Service 7 (MAP_ITEM_LAND_FOR_SALE) { if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) { @@ -463,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap mapitem.x = (uint)(xstart + x); mapitem.y = (uint)(ystart + y); // mapitem.z = (uint)m_scene.GetGroundHeight(x,y); - mapitem.id = UUID.Zero; + mapitem.id = parcel.GlobalID; mapitem.name = parcel.Name; mapitem.Extra = parcel.Area; mapitem.Extra2 = parcel.SalePrice; @@ -481,6 +482,34 @@ namespace OpenSim.Region.CoreModules.World.WorldMap RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); } } + else if (itemtype == 1) // Service 1 (MAP_ITEM_TELEHUB) + { + if (regionhandle == 0 || regionhandle == m_scene.RegionInfo.RegionHandle) + { + List mapitems = new List(); + mapItemReply mapitem = new mapItemReply(); + + SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject); + if (sog != null) + { + mapitem = new mapItemReply(); + mapitem.x = (uint)(xstart + sog.AbsolutePosition.X); + mapitem.y = (uint)(ystart + sog.AbsolutePosition.Y); + mapitem.id = UUID.Zero; + mapitem.name = sog.Name; + mapitem.Extra = 0; // color (not used) + mapitem.Extra2 = 0; // 0 = telehub / 1 = infohub + mapitems.Add(mapitem); + + remoteClient.SendMapItemReply(mapitems.ToArray(), itemtype, flags); + } + } + else + { + // Remote Map Item Request + RequestMapItems("",remoteClient.AgentId,flags,EstateID,godlike,itemtype,regionhandle); + } + } } private int nAsyncRequests = 0; @@ -620,6 +649,28 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); } + + // Service 1 (MAP_ITEM_TELEHUB) + itemtype = 1; + + if (response.ContainsKey(itemtype.ToString())) + { + List returnitems = new List(); + OSDArray itemarray = (OSDArray)response[itemtype.ToString()]; + for (int i = 0; i < itemarray.Count; i++) + { + OSDMap mapitem = (OSDMap)itemarray[i]; + mapItemReply mi = new mapItemReply(); + mi.x = (uint)mapitem["X"].AsInteger(); + mi.y = (uint)mapitem["Y"].AsInteger(); + mi.id = mapitem["ID"].AsUUID(); + mi.Extra = mapitem["Extra"].AsInteger(); + mi.Extra2 = mapitem["Extra2"].AsInteger(); + mi.name = mapitem["Name"].AsString(); + returnitems.Add(mi); + } + av.ControllingClient.SendMapItemReply(returnitems.ToArray(), itemtype, mrs.flags); + } } } } @@ -904,8 +955,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { List response = new List(); - // this should return one mapblock at most. - // (diva note: why?? in that case we should GetRegionByPosition) + // this should return one mapblock at most. It is triggered by a click + // on an unloaded square. // But make sure: Look whether the one we requested is in there List regions = m_scene.GridService.GetRegionRange(m_scene.RegionInfo.ScopeID, minX * (int)Constants.RegionSize, @@ -922,7 +973,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { // found it => add it to response MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); + MapBlockFromGridRegion(block, r, flag); response.Add(block); break; } @@ -938,10 +989,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap block.Access = 254; // means 'simulator is offline' response.Add(block); } - if ((flag & 2) == 2) // V2 !!! - remoteClient.SendMapBlock(response, 2); - else - remoteClient.SendMapBlock(response, 0); + // The lower 16 bits are an unsigned int16 + remoteClient.SendMapBlock(response, flag & 0xffff); } else { @@ -961,21 +1010,29 @@ namespace OpenSim.Region.CoreModules.World.WorldMap foreach (GridRegion r in regions) { MapBlockData block = new MapBlockData(); - MapBlockFromGridRegion(block, r); + MapBlockFromGridRegion(block, r, flag); mapBlocks.Add(block); } - if ((flag & 2) == 2) // V2 !!! - remoteClient.SendMapBlock(mapBlocks, 2); - else - remoteClient.SendMapBlock(mapBlocks, 0); + remoteClient.SendMapBlock(mapBlocks, flag & 0xffff); return mapBlocks; } - protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r) + protected void MapBlockFromGridRegion(MapBlockData block, GridRegion r, uint flag) { block.Access = r.Access; - block.MapImageId = r.TerrainImage; + switch (flag & 0xffff) + { + case 0: + block.MapImageId = r.TerrainImage; + break; + case 2: + block.MapImageId = r.ParcelImage; + break; + default: + block.MapImageId = UUID.Zero; + break; + } block.Name = r.RegionName; block.X = (ushort)(r.RegionLocX / Constants.RegionSize); block.Y = (ushort)(r.RegionLocY / Constants.RegionSize); @@ -1109,7 +1166,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap foreach (GridRegion r in regions) { MapBlockData mapBlock = new MapBlockData(); - MapBlockFromGridRegion(mapBlock, r); + MapBlockFromGridRegion(mapBlock, r, 0); AssetBase texAsset = m_scene.AssetService.Get(mapBlock.MapImageId.ToString()); if (texAsset != null) @@ -1240,7 +1297,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap responsemapdata["X"] = OSD.FromInteger((int)(xstart + x)); responsemapdata["Y"] = OSD.FromInteger((int)(ystart + y)); // responsemapdata["Z"] = OSD.FromInteger((int)m_scene.GetGroundHeight(x,y)); - responsemapdata["ID"] = OSD.FromUUID(UUID.Zero); + responsemapdata["ID"] = OSD.FromUUID(parcel.GlobalID); responsemapdata["Name"] = OSD.FromString(parcel.Name); responsemapdata["Extra"] = OSD.FromInteger(parcel.Area); responsemapdata["Extra2"] = OSD.FromInteger(parcel.SalePrice); @@ -1250,6 +1307,26 @@ namespace OpenSim.Region.CoreModules.World.WorldMap responsemap["7"] = responsearr; } + if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero) + { + SceneObjectGroup sog = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject); + if (sog != null) + { + OSDArray responsearr = new OSDArray(); + OSDMap responsemapdata = new OSDMap(); + responsemapdata["X"] = OSD.FromInteger((int)(xstart + sog.AbsolutePosition.X)); + responsemapdata["Y"] = OSD.FromInteger((int)(ystart + sog.AbsolutePosition.Y)); + // responsemapdata["Z"] = OSD.FromInteger((int)m_scene.GetGroundHeight(x,y)); + responsemapdata["ID"] = OSD.FromUUID(sog.UUID); + responsemapdata["Name"] = OSD.FromString(sog.Name); + responsemapdata["Extra"] = OSD.FromInteger(0); // color (unused) + responsemapdata["Extra2"] = OSD.FromInteger(0); // 0 = telehub / 1 = infohub + responsearr.Add(responsemapdata); + + responsemap["1"] = responsearr; + } + } + return responsemap; } @@ -1268,9 +1345,12 @@ namespace OpenSim.Region.CoreModules.World.WorldMap if (data == null) return; + byte[] overlay = GenerateOverlay(); + m_log.Debug("[WORLDMAP]: STORING MAPTILE IMAGE"); UUID terrainImageID = UUID.Random(); + UUID parcelImageID = UUID.Zero; AssetBase asset = new AssetBase( terrainImageID, @@ -1286,14 +1366,35 @@ namespace OpenSim.Region.CoreModules.World.WorldMap m_log.DebugFormat("[WORLDMAP]: Storing map tile {0}", asset.ID); m_scene.AssetService.Store(asset); + if (overlay != null) + { + parcelImageID = UUID.Random(); + + AssetBase parcels = new AssetBase( + parcelImageID, + "parcelImage_" + m_scene.RegionInfo.RegionID.ToString(), + (sbyte)AssetType.Texture, + m_scene.RegionInfo.RegionID.ToString()); + parcels.Data = overlay; + parcels.Description = m_scene.RegionInfo.RegionName; + parcels.Temporary = false; + parcels.Flags = AssetFlags.Maptile; + + m_scene.AssetService.Store(parcels); + } + // Switch to the new one - UUID lastMapRegionUUID = m_scene.RegionInfo.RegionSettings.TerrainImageID; + UUID lastTerrainImageID = m_scene.RegionInfo.RegionSettings.TerrainImageID; + UUID lastParcelImageID = m_scene.RegionInfo.RegionSettings.ParcelImageID; m_scene.RegionInfo.RegionSettings.TerrainImageID = terrainImageID; + m_scene.RegionInfo.RegionSettings.ParcelImageID = parcelImageID; m_scene.RegionInfo.RegionSettings.Save(); // Delete the old one - m_log.DebugFormat("[WORLDMAP]: Deleting old map tile {0}", lastMapRegionUUID); - m_scene.AssetService.Delete(lastMapRegionUUID.ToString()); + // m_log.DebugFormat("[WORLDMAP]: Deleting old map tile {0}", lastTerrainImageID); + m_scene.AssetService.Delete(lastTerrainImageID.ToString()); + if (lastParcelImageID != UUID.Zero) + m_scene.AssetService.Delete(lastParcelImageID.ToString()); } private void MakeRootAgent(ScenePresence avatar) @@ -1339,6 +1440,66 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } } + private Byte[] GenerateOverlay() + { + Bitmap overlay = new Bitmap(256, 256); + + bool[,] saleBitmap = new bool[64, 64]; + for (int x = 0 ; x < 64 ; x++) + { + for (int y = 0 ; y < 64 ; y++) + saleBitmap[x, y] = false; + } + + bool landForSale = false; + + List parcels = m_scene.LandChannel.AllParcels(); + + Color background = Color.FromArgb(0, 0, 0, 0); + SolidBrush transparent = new SolidBrush(background); + Graphics g = Graphics.FromImage(overlay); + g.FillRectangle(transparent, 0, 0, 256, 256); + + SolidBrush yellow = new SolidBrush(Color.FromArgb(255, 249, 223, 9)); + + foreach (ILandObject land in parcels) + { + // m_log.DebugFormat("[WORLD MAP]: Parcel {0} flags {1}", land.LandData.Name, land.LandData.Flags); + if ((land.LandData.Flags & (uint)ParcelFlags.ForSale) != 0) + { + landForSale = true; + + saleBitmap = land.MergeLandBitmaps(saleBitmap, land.GetLandBitmap()); + } + } + + if (!landForSale) + { + m_log.DebugFormat("[WORLD MAP]: Region {0} has no parcels for sale, not geenrating overlay", m_scene.RegionInfo.RegionName); + return null; + } + + m_log.DebugFormat("[WORLD MAP]: Region {0} has parcels for sale, genrating overlay", m_scene.RegionInfo.RegionName); + + for (int x = 0 ; x < 64 ; x++) + { + for (int y = 0 ; y < 64 ; y++) + { + if (saleBitmap[x, y]) + g.FillRectangle(yellow, x * 4, 252 - (y * 4), 4, 4); + } + } + + try + { + return OpenJPEG.EncodeFromImage(overlay, true); + } + catch (Exception e) + { + m_log.DebugFormat("[WORLD MAP]: Error creating parcel overlay: " + e.ToString()); + } + return null; + } } public struct MapRequestState diff --git a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs index b7604546eb..93648d6430 100644 --- a/OpenSim/Region/DataSnapshot/DataRequestHandler.cs +++ b/OpenSim/Region/DataSnapshot/DataRequestHandler.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.DataSnapshot public void OnRegisterCaps(UUID agentID, Caps caps) { - m_log.Info("[DATASNAPSHOT]: Registering service discovery capability for " + agentID); +// m_log.InfoFormat("[DATASNAPSHOT]: Registering service discovery capability for {0}", agentID); string capsBase = "/CAPS/" + caps.CapsObjectPath; caps.RegisterHandler("PublicSnapshotDataInfo", new RestStreamHandler("POST", capsBase + m_discoveryPath, OnDiscoveryAttempt)); diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index e668daebe8..eb071650bc 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -46,7 +46,7 @@ namespace OpenSim.Region.Framework.Interfaces /// Save the attachments that have change on this presence. /// /// - void SaveChangedAttachments(IScenePresence sp); + void SaveChangedAttachments(IScenePresence sp, bool saveAllScripted); /// /// Delete all the presence's attachments from the scene diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs index 8670229e8b..39a760cbf4 100644 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs @@ -61,7 +61,32 @@ namespace OpenSim.Region.Framework.Interfaces /// true if a valid agent was found, false otherwise bool SaveBakedTextures(UUID agentId); + /// + /// Validate that OpenSim can find the baked textures need to display a given avatar + /// + /// + /// + /// + /// true if all the baked textures referenced by the texture IDs exist or the appearance is only using default textures. false otherwise. + /// bool ValidateBakedTextureCache(IScenePresence sp); + + /// + /// Request a rebake of textures for an avatar. + /// + /// + /// This will send the request to the viewer, since it's there that the rebake is done. + /// + /// Avatar to rebake. + /// + /// If true, only request a rebake for the textures that are missing. + /// If false then we request a rebake of all textures for which we already have references. + /// + /// + /// Number of rebake requests made. This will depend upon whether we've previously received texture IDs. + /// + int RequestRebake(IScenePresence sp, bool missingTexturesOnly); + void QueueAppearanceSend(UUID agentid); void QueueAppearanceSave(UUID agentid); diff --git a/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs b/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs index 856eb119ab..46d03b3742 100644 --- a/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs +++ b/OpenSim/Region/Framework/Interfaces/IJ2KDecoder.cs @@ -35,6 +35,23 @@ namespace OpenSim.Region.Framework.Interfaces public interface IJ2KDecoder { void BeginDecode(UUID assetID, byte[] j2kData, DecodedCallback callback); - void Decode(UUID assetID, byte[] j2kData); + + /// + /// Provides a synchronous decode so that caller can be assured that this executes before the next line + /// + /// + /// + /// true if decode was successful. false otherwise. + bool Decode(UUID assetID, byte[] j2kData); + + /// + /// Provides a synchronous decode so that caller can be assured that this executes before the next line + /// + /// + /// + /// layer data + /// number of components + /// true if decode was successful. false otherwise. + bool Decode(UUID assetID, byte[] j2kData, out OpenJPEG.J2KLayerInfo[] layers, out int components); } } diff --git a/OpenSim/Region/Framework/Interfaces/INPCModule.cs b/OpenSim/Region/Framework/Interfaces/INPCModule.cs index b65f82c5ed..2731291ea0 100644 --- a/OpenSim/Region/Framework/Interfaces/INPCModule.cs +++ b/OpenSim/Region/Framework/Interfaces/INPCModule.cs @@ -31,6 +31,19 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.Framework.Interfaces { + /// + /// Temporary interface. More methods to come at some point to make NPCs more object oriented rather than + /// controlling purely through module level interface calls (e.g. sit/stand). + /// + public interface INPC + { + /// + /// Should this NPC be sensed by LSL sensors as an 'agent' (interpreted here to mean a normal user) + /// rather than an OpenSim specific NPC extension? + /// + bool SenseAsAgent { get; } + } + public interface INPCModule { /// @@ -39,10 +52,21 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// + /// + /// Make the NPC show up as an agent on LSL sensors. The default is that they + /// show up as the NPC type instead, but this is currently an OpenSim-only extension. + /// /// /// The avatar appearance to use for the new NPC. /// The UUID of the ScenePresence created. - UUID CreateNPC(string firstname, string lastname, Vector3 position, Scene scene, AvatarAppearance appearance); + UUID CreateNPC( + string firstname, + string lastname, + Vector3 position, + UUID owner, + bool senseAsAgent, + Scene scene, + AvatarAppearance appearance); /// /// Check if the agent is an NPC. @@ -52,6 +76,22 @@ namespace OpenSim.Region.Framework.Interfaces /// True if the agent is an NPC in the given scene. False otherwise. bool IsNPC(UUID agentID, Scene scene); + /// + /// Get the NPC. This is not currently complete - manipulation of NPCs still occurs through the region interface + /// + /// + /// + /// The NPC. null if it does not exist. + INPC GetNPC(UUID agentID, Scene scene); + + /// + /// Check if the caller has permission to manipulate the given NPC. + /// + /// + /// + /// true if they do, false if they don't or if there's no NPC with the given ID. + bool CheckPermissions(UUID npcID, UUID callerID); + /// /// Set the appearance for an NPC. /// @@ -118,5 +158,12 @@ namespace OpenSim.Region.Framework.Interfaces /// /// True if the operation succeeded, false if there was no such agent or the agent was not an NPC bool DeleteNPC(UUID agentID, Scene scene); + + /// + /// Get the owner of a NPC + /// + /// The UUID of the NPC + /// UUID of owner if the NPC exists, UUID.Zero if there was no such agent, the agent is unowned or the agent was not an NPC + UUID GetOwner(UUID agentID); } } \ No newline at end of file diff --git a/OpenSim/Framework/IProfileModule.cs b/OpenSim/Region/Framework/Interfaces/IProfileModule.cs similarity index 100% rename from OpenSim/Framework/IProfileModule.cs rename to OpenSim/Region/Framework/Interfaces/IProfileModule.cs diff --git a/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.cs new file mode 100644 index 0000000000..aa4a757420 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IRegionReadyModule.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.Region.Framework.Interfaces +{ + public interface IRegionReadyModule + { + void OarLoadingAlert(string msg); + } +} + diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs index 950e4b0df2..18c45dde6e 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs @@ -31,8 +31,21 @@ using OpenMetaverse; namespace OpenSim.Region.Framework.Interfaces { + public delegate void ScriptRemoved(UUID script); + public delegate void ObjectRemoved(UUID prim); + public interface IScriptModule: INonSharedRegionModule { + /// + /// Triggered when a script is removed from the script module. + /// + event ScriptRemoved OnScriptRemoved; + + /// + /// Triggered when an object is removed via the script module. + /// + event ObjectRemoved OnObjectRemoved; + string ScriptEngineName { get; } string GetXMLState(UUID itemID); diff --git a/OpenSim/Region/Framework/Interfaces/ISearchModule.cs b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs new file mode 100644 index 0000000000..64bf72cf86 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/ISearchModule.cs @@ -0,0 +1,36 @@ +/* + * 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 OpenMetaverse; + +namespace OpenSim.Framework +{ + public interface ISearchModule + { + + } +} diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index 54dfaf4c63..bfb8369437 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -14,9 +14,6 @@ namespace OpenSim.Region.Framework.Interfaces string GetUserHomeURL(UUID uuid); string GetUserUUI(UUID uuid); string GetUserServerURL(UUID uuid, string serverType); - int GetUserFlags(UUID userID); - int GetUserCreated(UUID userID); - string GetUserTitle(UUID userID); /// /// Add a user. @@ -50,7 +47,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// /// - void AddUser(UUID uuid, string firstName, string lastName, string profileURL); + void AddUser(UUID uuid, string firstName, string lastName, string homeURL); bool IsLocalGridUser(UUID uuid); } diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index eda085f47f..3584cda015 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -61,11 +61,12 @@ namespace OpenSim.Region.Framework.Scenes.Animation public bool m_jumping = false; public float m_jumpVelocity = 0f; // private int m_landing = 0; - public bool Falling - { - get { return m_falling; } - } - private bool m_falling = false; + + /// + /// Is the avatar falling? + /// + public bool Falling { get; private set; } + private float m_fallHeight; /// @@ -223,7 +224,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation m_animTickFall = 0; m_animTickJump = 0; m_jumping = false; - m_falling = true; + Falling = false; m_jumpVelocity = 0f; actor.Selected = false; m_fallHeight = actor.Position.Z; // save latest flying height @@ -238,10 +239,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation } else if (move.Z < 0f) { - if (actor != null && actor.IsColliding) - { + if (actor != null && actor.IsColliding) return "LAND"; - } else return "HOVER_DOWN"; } @@ -260,7 +259,8 @@ namespace OpenSim.Region.Framework.Scenes.Animation float fallElapsed = (float)(Environment.TickCount - m_animTickFall); float fallVelocity = (actor != null) ? actor.Velocity.Z : 0.0f; - if (!m_jumping && (fallVelocity < -3.0f) ) m_falling = true; + if (!m_jumping && (fallVelocity < -3.0f)) + Falling = true; if (m_animTickFall == 0 || (fallVelocity >= 0.0f)) { @@ -290,20 +290,20 @@ namespace OpenSim.Region.Framework.Scenes.Animation // Start jumping, prejump m_animTickFall = 0; m_jumping = true; - m_falling = false; + Falling = false; actor.Selected = true; // borrowed for jumping flag m_animTickJump = Environment.TickCount; m_jumpVelocity = 0.35f; return "PREJUMP"; } - if(m_jumping) + if (m_jumping) { - if ( (jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) + if ((jumptime > (JUMP_PERIOD * 1.5f)) && actor.IsColliding) { // end jumping m_jumping = false; - m_falling = false; + Falling = false; actor.Selected = false; // borrowed for jumping flag m_jumpVelocity = 0f; m_animTickFall = Environment.TickCount; @@ -330,7 +330,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation if (CurrentMovementAnimation == "FALLDOWN") { - m_falling = false; + Falling = false; m_animTickFall = Environment.TickCount; // TODO: SOFT_LAND support float fallHeight = m_fallHeight - actor.Position.Z; @@ -364,7 +364,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation if (move.X != 0f || move.Y != 0f) { m_fallHeight = actor.Position.Z; // save latest flying height - m_falling = false; + Falling = false; // Walking / crouchwalking / running if (move.Z < 0f) return "CROUCHWALK"; @@ -375,7 +375,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation } else if (!m_jumping) { - m_falling = false; + Falling = false; // Not walking if (move.Z < 0) return "CROUCH"; @@ -388,7 +388,7 @@ namespace OpenSim.Region.Framework.Scenes.Animation } #endregion Ground Movement - m_falling = false; + Falling = false; return CurrentMovementAnimation; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index b62023bcde..dd3208acb1 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -979,25 +979,40 @@ namespace OpenSim.Region.Framework.Scenes public void RemoveTaskInventory(IClientAPI remoteClient, UUID itemID, uint localID) { SceneObjectPart part = GetSceneObjectPart(localID); - if (part == null) - return; - - SceneObjectGroup group = part.ParentGroup; - if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) - return; - - TaskInventoryItem item = group.GetInventoryItem(localID, itemID); - if (item == null) - return; - - if (item.Type == 10) + SceneObjectGroup group = null; + if (part != null) { - part.RemoveScriptEvents(itemID); - EventManager.TriggerRemoveScript(localID, itemID); + group = part.ParentGroup; + } + if (part != null && group != null) + { + if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) + return; + + TaskInventoryItem item = group.GetInventoryItem(localID, itemID); + if (item == null) + return; + + InventoryFolderBase destFolder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.TrashFolder); + + // Move the item to trash. If this is a copiable item, only + // a copy will be moved and we will still need to delete + // the item from the prim. If it was no copy, is will be + // deleted by this method. + MoveTaskInventoryItem(remoteClient, destFolder.ID, part, itemID); + + if (group.GetInventoryItem(localID, itemID) != null) + { + if (item.Type == 10) + { + part.RemoveScriptEvents(itemID); + EventManager.TriggerRemoveScript(localID, itemID); + } + + group.RemoveInventoryItem(localID, itemID); + } + part.SendPropertiesToClient(remoteClient); } - - group.RemoveInventoryItem(localID, itemID); - part.SendPropertiesToClient(remoteClient); } private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) @@ -1058,7 +1073,15 @@ namespace OpenSim.Region.Framework.Scenes if (!Permissions.BypassPermissions()) { if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + { + if (taskItem.Type == 10) + { + part.RemoveScriptEvents(itemId); + EventManager.TriggerRemoveScript(part.LocalId, itemId); + } + part.Inventory.RemoveInventoryItem(itemId); + } } return agentItem; @@ -1421,7 +1444,7 @@ namespace OpenSim.Region.Framework.Scenes // If we've found the item in the user's inventory or in the library if (item != null) { - part.ParentGroup.AddInventoryItem(remoteClient, primLocalID, item, copyID); + part.ParentGroup.AddInventoryItem(remoteClient.AgentId, primLocalID, item, copyID); m_log.InfoFormat( "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", item.Name, primLocalID, remoteClient.Name); @@ -1449,20 +1472,27 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()", // currentItem.Name, part.Name); - - IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); - if (agentTransactions != null) - { - agentTransactions.HandleTaskItemUpdateFromTransaction( - remoteClient, part, transactionID, currentItem); - if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) - remoteClient.SendAgentAlertMessage("Notecard saved", false); - else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) - remoteClient.SendAgentAlertMessage("Script saved", false); - else - remoteClient.SendAgentAlertMessage("Item saved", false); - } + // Viewers from at least Linden Lab 1.23 onwards use a capability to update script contents rather + // than UDP. With viewers from at least 1.23 onwards, changing properties on scripts (e.g. renaming) causes + // this to spew spurious errors and "thing saved" messages. + // Rather than retaining complexity in the code and removing useful error messages, I'm going to + // comment this section out. If this was still working for very old viewers and there is + // a large population using them which cannot upgrade to 1.23 or derivatives then we can revisit + // this - justincc +// IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); +// if (agentTransactions != null) +// { +// agentTransactions.HandleTaskItemUpdateFromTransaction( +// remoteClient, part, transactionID, currentItem); +// +// if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) +// remoteClient.SendAgentAlertMessage("Notecard saved", false); +// else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) +// remoteClient.SendAgentAlertMessage("Script saved", false); +// else +// remoteClient.SendAgentAlertMessage("Item saved", false); +// } // Base ALWAYS has move currentItem.BasePermissions |= (uint)PermissionMask.Move; @@ -1537,104 +1567,141 @@ namespace OpenSim.Region.Framework.Scenes /// Rez a script into a prim's inventory, either ex nihilo or from an existing avatar inventory /// /// - /// + /// + /// /// public void RezScript(IClientAPI remoteClient, InventoryItemBase itemBase, UUID transactionID, uint localID) { - UUID itemID = itemBase.ID; + SceneObjectPart partWhereRezzed; + + if (itemBase.ID != UUID.Zero) + partWhereRezzed = RezScriptFromAgentInventory(remoteClient.AgentId, itemBase.ID, localID); + else + partWhereRezzed = RezNewScript(remoteClient.AgentId, itemBase); + + if (partWhereRezzed != null) + partWhereRezzed.SendPropertiesToClient(remoteClient); + } + + /// + /// Rez a script into a prim from an agent inventory. + /// + /// + /// + /// + /// The part where the script was rezzed if successful. False otherwise. + public SceneObjectPart RezScriptFromAgentInventory(UUID agentID, UUID fromItemID, uint localID) + { UUID copyID = UUID.Random(); + InventoryItemBase item = new InventoryItemBase(fromItemID, agentID); + item = InventoryService.GetItem(item); - if (itemID != UUID.Zero) // transferred from an avatar inventory to the prim's inventory + // Try library + // XXX clumsy, possibly should be one call + if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null) { - InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); - item = InventoryService.GetItem(item); + item = LibraryService.LibraryRootFolder.FindItem(fromItemID); + } - // Try library - // XXX clumsy, possibly should be one call - if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null) + if (item != null) + { + SceneObjectPart part = GetSceneObjectPart(localID); + if (part != null) { - item = LibraryService.LibraryRootFolder.FindItem(itemID); - } + if (!Permissions.CanEditObjectInventory(part.UUID, agentID)) + return null; - if (item != null) - { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) - { - if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) - return; + part.ParentGroup.AddInventoryItem(agentID, localID, item, copyID); + // TODO: switch to posting on_rez here when scripts + // have state in inventory + part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); - part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID); - // TODO: switch to posting on_rez here when scripts - // have state in inventory - part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); + // m_log.InfoFormat("[PRIMINVENTORY]: " + + // "Rezzed script {0} into prim local ID {1} for user {2}", + // item.inventoryName, localID, remoteClient.Name); + part.ParentGroup.ResumeScripts(); - // m_log.InfoFormat("[PRIMINVENTORY]: " + - // "Rezzed script {0} into prim local ID {1} for user {2}", - // item.inventoryName, localID, remoteClient.Name); - part.SendPropertiesToClient(remoteClient); - part.ParentGroup.ResumeScripts(); - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Could not rez script {0} into prim local ID {1} for user {2}" - + " because the prim could not be found in the region!", - item.Name, localID, remoteClient.Name); - } + return part; } else { m_log.ErrorFormat( - "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!", - itemID, remoteClient.Name); + "[PRIM INVENTORY]: " + + "Could not rez script {0} into prim local ID {1} for user {2}" + + " because the prim could not be found in the region!", + item.Name, localID, agentID); } } - else // script has been rezzed directly into a prim's inventory + else { - SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); - if (part == null) - return; - - if (!Permissions.CanCreateObjectInventory( - itemBase.InvType, part.UUID, remoteClient.AgentId)) - return; - - AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, - Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), - remoteClient.AgentId); - AssetService.Store(asset); - - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ResetIDs(itemBase.Folder); - taskItem.ParentID = itemBase.Folder; - taskItem.CreationDate = (uint)itemBase.CreationDate; - taskItem.Name = itemBase.Name; - taskItem.Description = itemBase.Description; - taskItem.Type = itemBase.AssetType; - taskItem.InvType = itemBase.InvType; - taskItem.OwnerID = itemBase.Owner; - taskItem.CreatorID = itemBase.CreatorIdAsUuid; - taskItem.BasePermissions = itemBase.BasePermissions; - taskItem.CurrentPermissions = itemBase.CurrentPermissions; - taskItem.EveryonePermissions = itemBase.EveryOnePermissions; - taskItem.GroupPermissions = itemBase.GroupPermissions; - taskItem.NextPermissions = itemBase.NextPermissions; - taskItem.GroupID = itemBase.GroupID; - taskItem.GroupPermissions = 0; - taskItem.Flags = itemBase.Flags; - taskItem.PermsGranter = UUID.Zero; - taskItem.PermsMask = 0; - taskItem.AssetID = asset.FullID; - - part.Inventory.AddInventoryItem(taskItem, false); - part.SendPropertiesToClient(remoteClient); - - part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); - part.ParentGroup.ResumeScripts(); + m_log.ErrorFormat( + "[PRIM INVENTORY]: Could not find script inventory item {0} to rez for {1}!", + fromItemID, agentID); } + + return null; + } + + /// + /// Rez a new script from nothing. + /// + /// + /// + /// The part where the script was rezzed if successful. False otherwise. + public SceneObjectPart RezNewScript(UUID agentID, InventoryItemBase itemBase) + { + // The part ID is the folder ID! + SceneObjectPart part = GetSceneObjectPart(itemBase.Folder); + if (part == null) + { +// m_log.DebugFormat( +// "[SCENE INVENTORY]: Could not find part with id {0} for {1} to rez new script", +// itemBase.Folder, agentID); + + return null; + } + + if (!Permissions.CanCreateObjectInventory(itemBase.InvType, part.UUID, agentID)) + { +// m_log.DebugFormat( +// "[SCENE INVENTORY]: No permission to create new script in {0} for {1}", part.Name, agentID); + + return null; + } + + AssetBase asset = CreateAsset(itemBase.Name, itemBase.Description, (sbyte)itemBase.AssetType, + Encoding.ASCII.GetBytes("default\n{\n state_entry()\n {\n llSay(0, \"Script running\");\n }\n}"), + agentID); + AssetService.Store(asset); + + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ResetIDs(itemBase.Folder); + taskItem.ParentID = itemBase.Folder; + taskItem.CreationDate = (uint)itemBase.CreationDate; + taskItem.Name = itemBase.Name; + taskItem.Description = itemBase.Description; + taskItem.Type = itemBase.AssetType; + taskItem.InvType = itemBase.InvType; + taskItem.OwnerID = itemBase.Owner; + taskItem.CreatorID = itemBase.CreatorIdAsUuid; + taskItem.BasePermissions = itemBase.BasePermissions; + taskItem.CurrentPermissions = itemBase.CurrentPermissions; + taskItem.EveryonePermissions = itemBase.EveryOnePermissions; + taskItem.GroupPermissions = itemBase.GroupPermissions; + taskItem.NextPermissions = itemBase.NextPermissions; + taskItem.GroupID = itemBase.GroupID; + taskItem.GroupPermissions = 0; + taskItem.Flags = itemBase.Flags; + taskItem.PermsGranter = UUID.Zero; + taskItem.PermsMask = 0; + taskItem.AssetID = asset.FullID; + + part.Inventory.AddInventoryItem(taskItem, false); + part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); + part.ParentGroup.ResumeScripts(); + + return part; } /// @@ -1643,7 +1710,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public void RezScript(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param) + public void RezScriptFromPrim(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param) { TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 3d8c7144d8..bfe8d2c008 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -65,6 +65,7 @@ namespace OpenSim.Region.Framework.Scenes #region Fields public bool EmergencyMonitoring = false; + public bool DEBUG = false; public SynchronizeSceneHandler SynchronizeScene; public SimStatsReporter StatsReporter; @@ -599,23 +600,6 @@ namespace OpenSim.Region.Framework.Scenes "reload estate", "Reload the estate data", HandleReloadEstate); - MainConsole.Instance.Commands.AddCommand("region", false, "delete object owner", - "delete object owner ", - "Delete object by owner", HandleDeleteObject); - MainConsole.Instance.Commands.AddCommand("region", false, "delete object creator", - "delete object creator ", - "Delete object by creator", HandleDeleteObject); - MainConsole.Instance.Commands.AddCommand("region", false, "delete object uuid", - "delete object uuid ", - "Delete object by uuid", HandleDeleteObject); - MainConsole.Instance.Commands.AddCommand("region", false, "delete object name", - "delete object name ", - "Delete object by name", HandleDeleteObject); - - MainConsole.Instance.Commands.AddCommand("region", false, "delete object outside", - "delete object outside", - "Delete all objects outside boundaries", HandleDeleteObject); - //Bind Storage Manager functions to some land manager functions for this scene EventManager.OnLandObjectAdded += new EventManager.LandObjectAdded(simDataService.StoreLandObject); @@ -1942,6 +1926,7 @@ namespace OpenSim.Region.Framework.Scenes /// If true, the object is made persistent into the scene. /// If false, the object will not persist over server restarts /// + /// true if the object was added. false if not public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup) { return AddNewSceneObject(sceneObject, attachToBackup, true); @@ -1959,6 +1944,7 @@ namespace OpenSim.Region.Framework.Scenes /// If true, updates for the new scene object are sent to all viewers in range. /// If false, it is left to the caller to schedule the update /// + /// true if the object was added. false if not public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates)) @@ -2528,7 +2514,7 @@ namespace OpenSim.Region.Framework.Scenes sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); m_eventManager.TriggerOnNewPresence(sp); - sp.TeleportFlags = (TeleportFlags)aCircuit.teleportFlags; + sp.TeleportFlags = (TPFlags)aCircuit.teleportFlags; // The first agent upon login is a root agent by design. // For this agent we will have to rez the attachments. @@ -3070,11 +3056,11 @@ namespace OpenSim.Region.Framework.Scenes public override void RemoveClient(UUID agentID, bool closeChildAgents) { CheckHeartbeat(); - bool childagentYN = false; + bool isChildAgent = false; ScenePresence avatar = GetScenePresence(agentID); if (avatar != null) { - childagentYN = avatar.IsChildAgent; + isChildAgent = avatar.IsChildAgent; if (avatar.ParentID != 0) { @@ -3085,9 +3071,9 @@ namespace OpenSim.Region.Framework.Scenes { m_log.DebugFormat( "[SCENE]: Removing {0} agent {1} from region {2}", - (childagentYN ? "child" : "root"), agentID, RegionInfo.RegionName); + (isChildAgent ? "child" : "root"), agentID, RegionInfo.RegionName); - m_sceneGraph.removeUserCount(!childagentYN); + m_sceneGraph.removeUserCount(!isChildAgent); // TODO: We shouldn't use closeChildAgents here - it's being used by the NPC module to stop // unnecessary operations. This should go away once NPCs have no accompanying IClientAPI @@ -3117,8 +3103,18 @@ namespace OpenSim.Region.Framework.Scenes { m_eventManager.TriggerOnRemovePresence(agentID); - if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) - AttachmentsModule.SaveChangedAttachments(avatar); + if (AttachmentsModule != null && !isChildAgent && avatar.PresenceType != PresenceType.Npc) + { + IUserManagement uMan = RequestModuleInterface(); + // Don't save attachments for HG visitors, it + // messes up their inventory. When a HG visitor logs + // out on a foreign grid, their attachments will be + // reloaded in the state they were in when they left + // the home grid. This is best anyway as the visited + // grid may use an incompatible script engine. + if (uMan == null || uMan.IsLocalGridUser(avatar.UUID)) + AttachmentsModule.SaveChangedAttachments(avatar, false); + } ForEachClient( delegate(IClientAPI client) @@ -3333,7 +3329,7 @@ namespace OpenSim.Region.Framework.Scenes { // Let the SP know how we got here. This has a lot of interesting // uses down the line. - sp.TeleportFlags = (TeleportFlags)teleportFlags; + sp.TeleportFlags = (TPFlags)teleportFlags; if (sp.IsChildAgent) { @@ -4867,93 +4863,6 @@ namespace OpenSim.Region.Framework.Scenes } } - private void HandleDeleteObject(string module, string[] cmd) - { - if (cmd.Length < 3) - return; - - string mode = cmd[2]; - string o = ""; - - if (mode != "outside") - { - if (cmd.Length < 4) - return; - - o = cmd[3]; - } - - List deletes = new List(); - - UUID match; - - switch (mode) - { - case "owner": - if (!UUID.TryParse(o, out match)) - return; - ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.OwnerID == match && !g.IsAttachment) - deletes.Add(g); - }); - break; - case "creator": - if (!UUID.TryParse(o, out match)) - return; - ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.RootPart.CreatorID == match && !g.IsAttachment) - deletes.Add(g); - }); - break; - case "uuid": - if (!UUID.TryParse(o, out match)) - return; - ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.UUID == match && !g.IsAttachment) - deletes.Add(g); - }); - break; - case "name": - ForEachSOG(delegate (SceneObjectGroup g) - { - if (g.RootPart.Name == o && !g.IsAttachment) - deletes.Add(g); - }); - break; - case "outside": - ForEachSOG(delegate (SceneObjectGroup g) - { - SceneObjectPart rootPart = g.RootPart; - bool delete = false; - - if (rootPart.GroupPosition.Z < 0.0 || rootPart.GroupPosition.Z > 10000.0) - { - delete = true; - } - else - { - ILandObject parcel = LandChannel.GetLandObject(rootPart.GroupPosition.X, rootPart.GroupPosition.Y); - - if (parcel == null || parcel.LandData.Name == "NO LAND") - delete = true; - } - - if (delete && !g.IsAttachment && !deletes.Contains(g)) - deletes.Add(g); - }); - break; - } - - foreach (SceneObjectGroup g in deletes) - { - m_log.InfoFormat("[SCENE]: Deleting object {0}", g.UUID); - DeleteSceneObject(g, false); - } - } - private void HandleReloadEstate(string module, string[] cmd) { if (MainConsole.Instance.ConsoleScene == null || @@ -5076,6 +4985,36 @@ namespace OpenSim.Region.Framework.Scenes } } + if (position == Vector3.Zero) // Teleport + { + if (!RegionInfo.EstateSettings.AllowDirectTeleport) + { + SceneObjectGroup telehub; + if (RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = GetSceneObjectGroup(RegionInfo.RegionSettings.TelehubObject)) != null) + { + List spawnPoints = RegionInfo.RegionSettings.SpawnPoints(); + bool banned = true; + foreach (SpawnPoint sp in spawnPoints) + { + Vector3 spawnPoint = sp.GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + ILandObject land = LandChannel.GetLandObject(spawnPoint.X, spawnPoint.Y); + if (land == null) + continue; + if (land.IsEitherBannedOrRestricted(agentID)) + continue; + banned = false; + break; + } + + if (banned) + { + reason = "No suitable landing point found"; + return false; + } + } + } + } + reason = String.Empty; return true; } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index f481e72737..1487facf00 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -41,12 +41,6 @@ namespace OpenSim.Region.Framework.Scenes { public delegate void PhysicsCrash(); - public delegate void ObjectDuplicateDelegate(EntityBase original, EntityBase clone); - - public delegate void ObjectCreateDelegate(EntityBase obj); - - public delegate void ObjectDeleteDelegate(EntityBase obj); - /// /// This class used to be called InnerScene and may not yet truly be a SceneGraph. The non scene graph components /// should be migrated out over time. @@ -60,10 +54,6 @@ namespace OpenSim.Region.Framework.Scenes protected internal event PhysicsCrash UnRecoverableError; private PhysicsCrash handlerPhysicsCrash = null; - public event ObjectDuplicateDelegate OnObjectDuplicate; - public event ObjectCreateDelegate OnObjectCreate; - public event ObjectDeleteDelegate OnObjectRemove; - #endregion #region Fields @@ -364,11 +354,23 @@ namespace OpenSim.Region.Framework.Scenes /// protected bool AddSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) { - if (sceneObject == null || sceneObject.RootPart.UUID == UUID.Zero) + if (sceneObject.UUID == UUID.Zero) + { + m_log.ErrorFormat( + "[SCENEGRAPH]: Tried to add scene object {0} to {1} with illegal UUID of {2}", + sceneObject.Name, m_parentScene.RegionInfo.RegionName, UUID.Zero); + return false; + } if (Entities.ContainsKey(sceneObject.UUID)) + { +// m_log.DebugFormat( +// "[SCENEGRAPH]: Scene graph for {0} already contains object {1} in AddSceneObject()", +// m_parentScene.RegionInfo.RegionName, sceneObject.UUID); + return false; + } // m_log.DebugFormat( // "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", @@ -405,9 +407,6 @@ namespace OpenSim.Region.Framework.Scenes if (attachToBackup) sceneObject.AttachToBackup(); - if (OnObjectCreate != null) - OnObjectCreate(sceneObject); - lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; @@ -456,9 +455,6 @@ namespace OpenSim.Region.Framework.Scenes if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) RemovePhysicalPrim(grp.PrimCount); } - - if (OnObjectRemove != null) - OnObjectRemove(Entities[uuid]); lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID.Remove(grp.UUID); @@ -1154,8 +1150,10 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void ForEachSOG(Action action) { - // FIXME: Need to lock here, really. - List objlist = new List(SceneObjectGroupsByFullID.Values); + List objlist; + lock (SceneObjectGroupsByFullID) + objlist = new List(SceneObjectGroupsByFullID.Values); + foreach (SceneObjectGroup obj in objlist) { try @@ -1164,7 +1162,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - // Catch it and move on. This includes situations where splist has inconsistent info + // Catch it and move on. This includes situations where objlist has inconsistent info m_log.WarnFormat( "[SCENEGRAPH]: Problem processing action in ForEachSOG: {0} {1}", e.Message, e.StackTrace); } @@ -1399,10 +1397,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// Update the texture entry of the given prim. /// - /// + /// /// A texture entry is an object that contains details of all the textures of the prim's face. In this case, /// the texture is given in its byte serialized form. - /// + /// /// /// /// @@ -1980,9 +1978,6 @@ namespace OpenSim.Region.Framework.Scenes // required for physics to update it's position copy.AbsolutePosition = copy.AbsolutePosition; - if (OnObjectDuplicate != null) - OnObjectDuplicate(original, copy); - return copy; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 905ecc9ff5..f173c95ed0 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -83,13 +83,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// Add an inventory item from a user's inventory to a prim in this scene object. /// - /// The client adding the item. + /// The agent adding the item. /// The local ID of the part receiving the add. /// The user inventory item being added. /// The item UUID that should be used by the new item. /// - public bool AddInventoryItem(IClientAPI remoteClient, uint localID, - InventoryItemBase item, UUID copyItemID) + public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID) { // m_log.DebugFormat( // "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", @@ -111,9 +110,7 @@ namespace OpenSim.Region.Framework.Scenes taskItem.Type = item.AssetType; taskItem.InvType = item.InvType; - if (remoteClient != null && - remoteClient.AgentId != part.OwnerID && - m_scene.Permissions.PropagatePermissions()) + if (agentID != part.OwnerID && m_scene.Permissions.PropagatePermissions()) { taskItem.BasePermissions = item.BasePermissions & item.NextPermissions; @@ -148,11 +145,7 @@ namespace OpenSim.Region.Framework.Scenes // taskItem.SaleType = item.SaleType; taskItem.CreationDate = (uint)item.CreationDate; - bool addFromAllowedDrop = false; - if (remoteClient != null) - { - addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; - } + bool addFromAllowedDrop = agentID != part.OwnerID; part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 886076499b..e7f2fdbd7f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -264,6 +264,12 @@ namespace OpenSim.Region.Framework.Scenes set { RootPart.Name = value; } } + public string Description + { + get { return RootPart.Description; } + set { RootPart.Description = value; } + } + /// /// Added because the Parcel code seems to use it /// but not sure a object should have this @@ -441,6 +447,12 @@ namespace OpenSim.Region.Framework.Scenes } } + public UUID LastOwnerID + { + get { return m_rootPart.LastOwnerID; } + set { m_rootPart.LastOwnerID = value; } + } + public UUID OwnerID { get { return m_rootPart.OwnerID; } @@ -1613,12 +1625,6 @@ namespace OpenSim.Region.Framework.Scenes RootPart.PhysActor.PIDActive = false; } - public void stopLookAt() - { - if (RootPart.PhysActor != null) - RootPart.PhysActor.APIDActive = false; - } - /// /// Uses a PID to attempt to clamp the object on the Z axis at the given height over tau seconds. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 8e59abfe8b..9b660b65d7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -217,11 +217,10 @@ namespace OpenSim.Region.Framework.Scenes public Quaternion SpinOldOrientation = Quaternion.Identity; - public Quaternion m_APIDTarget = Quaternion.Identity; - - public float m_APIDDamp = 0; - - public float m_APIDStrength = 0; + protected int m_APIDIterations = 0; + protected Quaternion m_APIDTarget = Quaternion.Identity; + protected float m_APIDDamp = 0; + protected float m_APIDStrength = 0; /// /// This part's inventory @@ -394,7 +393,7 @@ namespace OpenSim.Region.Framework.Scenes private string m_creatorData = string.Empty; /// - /// Data about the creator in the form profile_url;name + /// Data about the creator in the form home_url;name /// public string CreatorData { @@ -405,7 +404,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// Used by the DB layer to retrieve / store the entire user identification. /// The identification can either be a simple UUID or a string of the form - /// uuid[;profile_url[;name]] + /// uuid[;home_url[;name]] /// public string CreatorIdentification { @@ -563,22 +562,21 @@ namespace OpenSim.Region.Framework.Scenes } } - - public Quaternion APIDTarget + protected Quaternion APIDTarget { get { return m_APIDTarget; } set { m_APIDTarget = value; } } - public float APIDDamp + protected float APIDDamp { get { return m_APIDDamp; } set { m_APIDDamp = value; } } - public float APIDStrength + protected float APIDStrength { get { return m_APIDStrength; } set { m_APIDStrength = value; } @@ -1946,19 +1944,13 @@ namespace OpenSim.Region.Framework.Scenes public Vector3 GetWorldPosition() { Quaternion parentRot = ParentGroup.RootPart.RotationOffset; - Vector3 axPos = OffsetPosition; - axPos *= parentRot; Vector3 translationOffsetPosition = axPos; - -// m_log.DebugFormat("[SCENE OBJECT PART]: Found group pos {0} for part {1}", GroupPosition, Name); - - Vector3 worldPos = GroupPosition + translationOffsetPosition; - -// m_log.DebugFormat("[SCENE OBJECT PART]: Found world pos {0} for part {1}", worldPos, Name); - - return worldPos; + if(_parentID == 0) + return GroupPosition; + else + return ParentGroup.AbsolutePosition + translationOffsetPosition; } /// @@ -2688,11 +2680,6 @@ namespace OpenSim.Region.Framework.Scenes } public void RotLookAt(Quaternion target, float strength, float damping) - { - rotLookAt(target, strength, damping); - } - - public void rotLookAt(Quaternion target, float strength, float damping) { if (ParentGroup.IsAttachment) { @@ -2708,17 +2695,26 @@ namespace OpenSim.Region.Framework.Scenes APIDDamp = damping; APIDStrength = strength; APIDTarget = target; + + if (APIDStrength <= 0) + { + m_log.WarnFormat("[SceneObjectPart] Invalid rotation strength {0}",APIDStrength); + return; + } + + m_APIDIterations = 1 + (int)(Math.PI * APIDStrength); } + + // Necessary to get the lookat deltas applied + ParentGroup.QueueForUpdateCheck(); } - public void startLookAt(Quaternion rot, float damp, float strength) + public void StartLookAt(Quaternion target, float strength, float damping) { - APIDDamp = damp; - APIDStrength = strength; - APIDTarget = rot; + RotLookAt(target,strength,damping); } - public void stopLookAt() + public void StopLookAt() { APIDTarget = Quaternion.Identity; } @@ -3413,13 +3409,6 @@ namespace OpenSim.Region.Framework.Scenes } } - public void StopLookAt() - { - ParentGroup.stopLookAt(); - - ParentGroup.ScheduleGroupForTerseUpdate(); - } - /// /// Set the text displayed for this part. /// @@ -4521,10 +4510,18 @@ namespace OpenSim.Region.Framework.Scenes /// /// Update the texture entry for this part. /// - /// - public void UpdateTextureEntry(byte[] textureEntry) + /// + public void UpdateTextureEntry(byte[] serializedTextureEntry) + { + UpdateTextureEntry(new Primitive.TextureEntry(serializedTextureEntry, 0, serializedTextureEntry.Length)); + } + + /// + /// Update the texture entry for this part. + /// + /// + public void UpdateTextureEntry(Primitive.TextureEntry newTex) { - Primitive.TextureEntry newTex = new Primitive.TextureEntry(textureEntry, 0, textureEntry.Length); Primitive.TextureEntry oldTex = Shape.Textures; Changed changeFlags = 0; @@ -4556,7 +4553,7 @@ namespace OpenSim.Region.Framework.Scenes break; } - m_shape.TextureEntry = textureEntry; + m_shape.TextureEntry = newTex.GetBytes(); if (changeFlags != 0) TriggerScriptChangedEvent(changeFlags); UpdateFlag = UpdateRequired.FULL; @@ -4727,24 +4724,20 @@ namespace OpenSim.Region.Framework.Scenes { if (APIDTarget != Quaternion.Identity) { - if (Single.IsNaN(APIDTarget.W) == true) + if (m_APIDIterations <= 1) { + UpdateRotation(APIDTarget); APIDTarget = Quaternion.Identity; return; } - Quaternion rot = RotationOffset; - Quaternion dir = (rot - APIDTarget); - float speed = ((APIDStrength / APIDDamp) * (float)(Math.PI / 180.0f)); - if (dir.Z > speed) - { - rot.Z -= speed; - } - if (dir.Z < -speed) - { - rot.Z += speed; - } - rot.Normalize(); + + Quaternion rot = Quaternion.Slerp(RotationOffset,APIDTarget,1.0f/(float)m_APIDIterations); UpdateRotation(rot); + + m_APIDIterations--; + + // This ensures that we'll check this object on the next iteration + ParentGroup.QueueForUpdateCheck(); } } catch (Exception ex) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 42cd4be1e4..5c56150003 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -40,6 +40,7 @@ using OpenSim.Region.Framework.Scenes.Types; using OpenSim.Region.Physics.Manager; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Services.Interfaces; +using TeleportFlags = OpenSim.Framework.Constants.TeleportFlags; namespace OpenSim.Region.Framework.Scenes { @@ -892,6 +893,8 @@ namespace OpenSim.Region.Framework.Scenes pos.Y = crossedBorder.BorderLine.Z - 1; } + CheckAndAdjustLandingPoint(ref pos); + if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) { m_log.WarnFormat( @@ -1056,6 +1059,7 @@ namespace OpenSim.Region.Framework.Scenes bool isFlying = Flying; RemoveFromPhysicalScene(); Velocity = Vector3.Zero; + CheckLandingPoint(ref pos); AbsolutePosition = pos; AddToPhysicalScene(isFlying); @@ -1066,6 +1070,7 @@ namespace OpenSim.Region.Framework.Scenes { bool isFlying = Flying; RemoveFromPhysicalScene(); + CheckLandingPoint(ref pos); AbsolutePosition = pos; AddToPhysicalScene(isFlying); @@ -1180,6 +1185,7 @@ namespace OpenSim.Region.Framework.Scenes client.Name, Scene.RegionInfo.RegionName, AbsolutePosition); Vector3 look = Velocity; + if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) { look = new Vector3(0.99f, 0.042f, 0); @@ -1206,7 +1212,7 @@ namespace OpenSim.Region.Framework.Scenes m_callbackURI = null; } - //m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); +// m_log.DebugFormat("[SCENE PRESENCE] Completed movement"); ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); ValidateAndSendAppearanceAndAgentData(); @@ -1274,8 +1280,8 @@ namespace OpenSim.Region.Framework.Scenes public void HandleAgentUpdate(IClientAPI remoteClient, AgentUpdateArgs agentData) { // m_log.DebugFormat( -// "[SCENE PRESENCE]: In {0} received agent update from {1}", -// Scene.RegionInfo.RegionName, remoteClient.Name); +// "[SCENE PRESENCE]: In {0} received agent update from {1}, flags {2}", +// Scene.RegionInfo.RegionName, remoteClient.Name, agentData.ControlFlags); if (IsChildAgent) { @@ -2312,6 +2318,8 @@ namespace OpenSim.Region.Framework.Scenes /// The vector in which to move. This is relative to the rotation argument public void AddNewMovement(Vector3 vec) { +// m_log.DebugFormat("[SCENE PRESENCE]: Adding new movement {0} for {1}", vec, Name); + Vector3 direc = vec * Rotation; direc.Normalize(); @@ -3801,5 +3809,146 @@ namespace OpenSim.Region.Framework.Scenes m_reprioritization_called = false; } } + + private void CheckLandingPoint(ref Vector3 pos) + { + // Never constrain lures + if ((TeleportFlags & TeleportFlags.ViaLure) != 0) + return; + + if (m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) + return; + + ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + + if (land.LandData.LandingType == (byte)LandingType.LandingPoint && + land.LandData.UserLocation != Vector3.Zero && + land.LandData.OwnerID != m_uuid && + (!m_scene.Permissions.IsGod(m_uuid)) && + (!m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid))) + { + float curr = Vector3.Distance(AbsolutePosition, pos); + if (Vector3.Distance(land.LandData.UserLocation, pos) < curr) + pos = land.LandData.UserLocation; + else + ControllingClient.SendAlertMessage("Can't teleport closer to destination"); + } + } + + private void CheckAndAdjustTelehub(SceneObjectGroup telehub, ref Vector3 pos) + { + if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == + (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || + (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 || + (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || + (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0) + { + if (GodLevel < 200 && + ((!m_scene.Permissions.IsGod(m_uuid) && + !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || + (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || + (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) + { + SpawnPoint[] spawnPoints = m_scene.RegionInfo.RegionSettings.SpawnPoints().ToArray(); + if (spawnPoints.Length == 0) + return; + + float distance = 9999; + int closest = -1; + + for (int i = 0 ; i < spawnPoints.Length ; i++) + { + Vector3 spawnPosition = spawnPoints[i].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + Vector3 offset = spawnPosition - pos; + float d = Vector3.Mag(offset); + if (d >= distance) + continue; + ILandObject land = m_scene.LandChannel.GetLandObject(spawnPosition.X, spawnPosition.Y); + if (land == null) + continue; + if (land.IsEitherBannedOrRestricted(UUID)) + continue; + distance = d; + closest = i; + } + if (closest == -1) + return; + + pos = spawnPoints[closest].GetLocation(telehub.AbsolutePosition, telehub.GroupRotation); + } + } + } + + private void CheckAndAdjustLandingPoint(ref Vector3 pos) + { + SceneObjectGroup telehub = null; + if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) + { + if (!m_scene.RegionInfo.EstateSettings.AllowDirectTeleport) + { + CheckAndAdjustTelehub(telehub, ref pos); + return; + } + } + + ILandObject land = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (land != null) + { + if (Scene.DEBUG) + TeleportFlagsDebug(); + + // If we come in via login, landmark or map, we want to + // honor landing points. If we come in via Lure, we want + // to ignore them. + if ((m_teleportFlags & (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID)) == + (TeleportFlags.ViaLogin | TeleportFlags.ViaRegionID) || + (m_teleportFlags & TeleportFlags.ViaLandmark) != 0 || + (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || + (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0) + { + // Don't restrict gods, estate managers, or land owners to + // the TP point. This behaviour mimics agni. + if (land.LandData.LandingType == (byte)LandingType.LandingPoint && + land.LandData.UserLocation != Vector3.Zero && + GodLevel < 200 && + ((land.LandData.OwnerID != m_uuid && + !m_scene.Permissions.IsGod(m_uuid) && + !m_scene.RegionInfo.EstateSettings.IsEstateManager(m_uuid)) || + (m_teleportFlags & TeleportFlags.ViaLocation) != 0 || + (m_teleportFlags & Constants.TeleportFlags.ViaHGLogin) != 0)) + { + pos = land.LandData.UserLocation; + } + } + + land.SendLandUpdateToClient(ControllingClient); + } + } + + private void TeleportFlagsDebug() { + + // Some temporary debugging help to show all the TeleportFlags we have... + bool HG = false; + if((m_teleportFlags & TeleportFlags.ViaHGLogin) == TeleportFlags.ViaHGLogin) + HG = true; + + m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); + + uint i = 0u; + for (int x = 0; x <= 30 ; x++, i = 1u << x) + { + i = 1u << x; + + if((m_teleportFlags & (TeleportFlags)i) == (TeleportFlags)i) + if (HG == false) + m_log.InfoFormat("[SCENE PRESENCE]: Teleport Flags include {0}", ((TeleportFlags) i).ToString()); + else + m_log.InfoFormat("[SCENE PRESENCE]: HG Teleport Flags include {0}", ((TeleportFlags)i).ToString()); + } + + m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); + + } + } } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index bca49f74ca..3a08271c4f 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -54,7 +54,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization /// Deserialize a scene object from the original xml format /// /// - /// + /// The scene object deserialized. Null on failure. public static SceneObjectGroup FromOriginalXmlFormat(string xmlData) { //m_log.DebugFormat("[SOG]: Starting deserialization of SOG"); @@ -1134,12 +1134,12 @@ namespace OpenSim.Region.Framework.Scenes.Serialization if (sop.CreatorData != null && sop.CreatorData != string.Empty) writer.WriteElementString("CreatorData", sop.CreatorData); - else if (options.ContainsKey("profile")) + else if (options.ContainsKey("home")) { if (m_UserManagement == null) m_UserManagement = sop.ParentGroup.Scene.RequestModuleInterface(); string name = m_UserManagement.GetUserName(sop.CreatorID); - writer.WriteElementString("CreatorData", (string)options["profile"] + "/" + sop.CreatorID + ";" + name); + writer.WriteElementString("CreatorData", (string)options["home"] + ";" + name); } WriteUUID(writer, "FolderID", sop.FolderID, options); @@ -1192,8 +1192,13 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("ObjectSaleType", sop.ObjectSaleType.ToString()); writer.WriteElementString("OwnershipCost", sop.OwnershipCost.ToString()); WriteUUID(writer, "GroupID", sop.GroupID, options); - WriteUUID(writer, "OwnerID", sop.OwnerID, options); - WriteUUID(writer, "LastOwnerID", sop.LastOwnerID, options); + + UUID ownerID = options.ContainsKey("wipe-owners") ? UUID.Zero : sop.OwnerID; + WriteUUID(writer, "OwnerID", ownerID, options); + + UUID lastOwnerID = options.ContainsKey("wipe-owners") ? UUID.Zero : sop.LastOwnerID; + WriteUUID(writer, "LastOwnerID", lastOwnerID, options); + writer.WriteElementString("BaseMask", sop.BaseMask.ToString()); writer.WriteElementString("OwnerMask", sop.OwnerMask.ToString()); writer.WriteElementString("GroupMask", sop.GroupMask.ToString()); @@ -1277,17 +1282,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("BasePermissions", item.BasePermissions.ToString()); writer.WriteElementString("CreationDate", item.CreationDate.ToString()); - WriteUUID(writer, "CreatorID", item.CreatorID, options); if (item.CreatorData != null && item.CreatorData != string.Empty) writer.WriteElementString("CreatorData", item.CreatorData); - else if (options.ContainsKey("profile")) + else if (options.ContainsKey("home")) { if (m_UserManagement == null) m_UserManagement = scene.RequestModuleInterface(); string name = m_UserManagement.GetUserName(item.CreatorID); - writer.WriteElementString("CreatorData", (string)options["profile"] + "/" + item.CreatorID + ";" + name); + writer.WriteElementString("CreatorData", (string)options["home"] + ";" + name); } writer.WriteElementString("Description", item.Description); @@ -1298,10 +1302,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("InvType", item.InvType.ToString()); WriteUUID(writer, "ItemID", item.ItemID, options); WriteUUID(writer, "OldItemID", item.OldItemID, options); - WriteUUID(writer, "LastOwnerID", item.LastOwnerID, options); + + UUID lastOwnerID = options.ContainsKey("wipe-owners") ? UUID.Zero : item.LastOwnerID; + WriteUUID(writer, "LastOwnerID", lastOwnerID, options); + writer.WriteElementString("Name", item.Name); writer.WriteElementString("NextPermissions", item.NextPermissions.ToString()); - WriteUUID(writer, "OwnerID", item.OwnerID, options); + + UUID ownerID = options.ContainsKey("wipe-owners") ? UUID.Zero : item.OwnerID; + WriteUUID(writer, "OwnerID", ownerID, options); + writer.WriteElementString("CurrentPermissions", item.CurrentPermissions.ToString()); WriteUUID(writer, "ParentID", item.ParentID, options); WriteUUID(writer, "ParentPartID", item.ParentPartID, options); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.cs new file mode 100644 index 0000000000..6f99abd2d4 --- /dev/null +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectScriptTests.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 NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.Framework.Scenes.Tests +{ + [TestFixture] + public class SceneObjectScriptTests + { + [Test] + public void TestAddScript() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID userId = TestHelpers.ParseTail(0x1); + UUID itemId = TestHelpers.ParseTail(0x2); + string itemName = "Test Script Item"; + + Scene scene = SceneHelpers.SetupScene(); + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + scene.AddNewSceneObject(so, true); + + InventoryItemBase itemTemplate = new InventoryItemBase(); + itemTemplate.Name = itemName; + itemTemplate.Folder = so.UUID; + itemTemplate.InvType = (int)InventoryType.LSL; + + SceneObjectPart partWhereScriptAdded = scene.RezNewScript(userId, itemTemplate); + + Assert.That(partWhereScriptAdded, Is.Not.Null); + + IEntityInventory primInventory = partWhereScriptAdded.Inventory; + Assert.That(primInventory.GetInventoryList().Count, Is.EqualTo(1)); + Assert.That(primInventory.ContainsScripts(), Is.True); + + IList primItems = primInventory.GetInventoryItems(itemName); + Assert.That(primItems.Count, Is.EqualTo(1)); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 32de85f6ab..bbf3729114 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -658,6 +658,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public event ModifyTerrain OnModifyTerrain; public event BakeTerrain OnBakeTerrain; public event EstateChangeInfo OnEstateChangeInfo; + public event EstateManageTelehub OnEstateManageTelehub; public event SetAppearance OnSetAppearance; public event AvatarNowWearing OnAvatarNowWearing; public event RezSingleAttachmentFromInv OnRezSingleAttachmentFromInv; @@ -1530,6 +1531,11 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } + public void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List SpawnPoint) + { + + } + public void SendMapItemReply(mapItemReply[] replies, uint mapitemtype, uint flags) { diff --git a/OpenSim/Region/OptionalModules/Agent/TextureSender/J2KDecoderCommandModule.cs b/OpenSim/Region/OptionalModules/Agent/TextureSender/J2KDecoderCommandModule.cs new file mode 100644 index 0000000000..439096a09f --- /dev/null +++ b/OpenSim/Region/OptionalModules/Agent/TextureSender/J2KDecoderCommandModule.cs @@ -0,0 +1,155 @@ +/* + * 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.IO; +using System.Reflection; +using System.Text; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenMetaverse.Imaging; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Agent.TextureSender +{ + /// + /// Commands for the J2KDecoder module. For debugging purposes. + /// + /// + /// Placed here so that they can be removed if not required and to keep the J2KDecoder module itself simple. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "J2KDecoderCommandModule")] + public class J2KDecoderCommandModule : ISharedRegionModule + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + + public string Name { get { return "Asset Information Module"; } } + + public Type ReplaceableInterface { get { return null; } } + + public void Initialise(IConfigSource source) + { +// m_log.DebugFormat("[J2K DECODER COMMAND MODULE]: INITIALIZED MODULE"); + } + + public void PostInitialise() + { +// m_log.DebugFormat("[J2K DECODER COMMAND MODULE]: POST INITIALIZED MODULE"); + } + + public void Close() + { +// m_log.DebugFormat("[J2K DECODER COMMAND MODULE]: CLOSED MODULE"); + } + + public void AddRegion(Scene scene) + { +// m_log.DebugFormat("[J2K DECODER COMMAND MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); + } + + public void RemoveRegion(Scene scene) + { +// m_log.DebugFormat("[J2K DECODER COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); + } + + public void RegionLoaded(Scene scene) + { +// m_log.DebugFormat("[J2K DECODER COMMAND MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); + + if (m_scene == null) + m_scene = scene; + + MainConsole.Instance.Commands.AddCommand( + "j2k", + false, + "j2k decode", + "j2k decode ", + "Do JPEG2000 decoding of an asset.", + "This is for debugging purposes. The asset id given must contain JPEG2000 data.", + HandleDecode); + } + + void HandleDecode(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Usage is j2k decode "); + return; + } + + UUID assetId; + string rawAssetId = args[2]; + + if (!UUID.TryParse(rawAssetId, out assetId)) + { + MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid ID format", rawAssetId); + return; + } + + AssetBase asset = m_scene.AssetService.Get(assetId.ToString()); + if (asset == null) + { + MainConsole.Instance.OutputFormat("ERROR: No asset found with ID {0}", assetId); + return; + } + + if (asset.Type != (sbyte)AssetType.Texture) + { + MainConsole.Instance.OutputFormat("ERROR: Asset {0} is not a texture type", assetId); + return; + } + + IJ2KDecoder decoder = m_scene.RequestModuleInterface(); + if (decoder == null) + { + MainConsole.Instance.OutputFormat("ERROR: No IJ2KDecoder module available"); + return; + } + + OpenJPEG.J2KLayerInfo[] layers; + int components; + if (decoder.Decode(assetId, asset.Data, out layers, out components)) + { + MainConsole.Instance.OutputFormat( + "Successfully decoded asset {0} with {1} layers and {2} components", + assetId, layers.Length, components); + } + else + { + MainConsole.Instance.OutputFormat("Decode of asset {0} failed", assetId); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index c754019b1e..261029c091 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -79,7 +79,19 @@ namespace OpenSim.Region.CoreModules.UDP.Linden // m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); lock (m_scenes) - m_scenes[scene.RegionInfo.RegionID] = scene; + m_scenes[scene.RegionInfo.RegionID] = scene; + + scene.AddCommand( + this, "image queues clear", + "image queues clear ", + "Clear the image queues (textures downloaded via UDP) for a particular client.", + (mod, cmd) => MainConsole.Instance.Output(HandleImageQueuesClear(cmd))); + + scene.AddCommand( + this, "image queues show", + "image queues show ", + "Show the image queues (textures downloaded via UDP) for a particular client.", + (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); scene.AddCommand( this, "show pqueues", @@ -87,7 +99,7 @@ namespace OpenSim.Region.CoreModules.UDP.Linden "Show priority queue data for each client", "Without the 'full' option, only root agents are shown." + " With the 'full' option child agents are also shown.", - ShowPQueuesReport); + (mod, cmd) => MainConsole.Instance.Output(GetPQueuesReport(cmd))); scene.AddCommand( this, "show queues", @@ -95,7 +107,13 @@ namespace OpenSim.Region.CoreModules.UDP.Linden "Show queue data for each client", "Without the 'full' option, only root agents are shown." + " With the 'full' option child agents are also shown.", - ShowQueuesReport); + (mod, cmd) => MainConsole.Instance.Output(GetQueuesReport(cmd))); + + scene.AddCommand( + this, "show image queues", + "show image queues ", + "Show the image queues (textures downloaded via UDP) for a particular client.", + (mod, cmd) => MainConsole.Instance.Output(GetImageQueuesReport(cmd))); scene.AddCommand( this, "show throttles", @@ -103,14 +121,14 @@ namespace OpenSim.Region.CoreModules.UDP.Linden "Show throttle settings for each client and for the server overall", "Without the 'full' option, only root agents are shown." + " With the 'full' option child agents are also shown.", - ShowThrottlesReport); + (mod, cmd) => MainConsole.Instance.Output(GetThrottlesReport(cmd))); scene.AddCommand( this, "emergency-monitoring", "emergency-monitoring", "Go on/off emergency monitoring mode", "Go on/off emergency monitoring mode", - EmergencyMonitoring); + HandleEmergencyMonitoring); } public void RemoveRegion(Scene scene) @@ -124,24 +142,51 @@ namespace OpenSim.Region.CoreModules.UDP.Linden public void RegionLoaded(Scene scene) { // m_log.DebugFormat("[LINDEN UDP INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); - } + } - protected void ShowPQueuesReport(string module, string[] cmd) - { - MainConsole.Instance.Output(GetPQueuesReport(cmd)); - } - - protected void ShowQueuesReport(string module, string[] cmd) - { - MainConsole.Instance.Output(GetQueuesReport(cmd)); - } - - protected void ShowThrottlesReport(string module, string[] cmd) + protected string HandleImageQueuesClear(string[] cmd) { - MainConsole.Instance.Output(GetThrottlesReport(cmd)); + if (cmd.Length != 5) + return "Usage: image queues clear "; + + string firstName = cmd[3]; + string lastName = cmd[4]; + + List foundAgents = new List(); + + lock (m_scenes) + { + foreach (Scene scene in m_scenes.Values) + { + ScenePresence sp = scene.GetScenePresence(firstName, lastName); + if (sp != null) + foundAgents.Add(sp); + } + } + + if (foundAgents.Count == 0) + return string.Format("No agents found for {0} {1}", firstName, lastName); + + StringBuilder report = new StringBuilder(); + + foreach (ScenePresence agent in foundAgents) + { + LLClientView client = agent.ControllingClient as LLClientView; + + if (client == null) + return "This command is only supported for LLClientView"; + + int requestsDeleted = client.ImageManager.ClearImageQueue(); + + report.AppendFormat( + "In region {0} ({1} agent) cleared {2} requests\n", + agent.Scene.RegionInfo.RegionName, agent.IsChildAgent ? "child" : "root", requestsDeleted); + } + + return report.ToString(); } - protected void EmergencyMonitoring(string module, string[] cmd) + protected void HandleEmergencyMonitoring(string module, string[] cmd) { bool mode = true; if (cmd.Length == 1 || (cmd.Length > 1 && cmd[1] == "on")) @@ -166,7 +211,6 @@ namespace OpenSim.Region.CoreModules.UDP.Linden entry.Length > maxLength ? entry.Substring(0, maxLength) : entry, ""); } - /// /// Generate UDP Queue data report for each client @@ -240,6 +284,73 @@ namespace OpenSim.Region.CoreModules.UDP.Linden return report.ToString(); } + + /// + /// Generate an image queue report + /// + /// + /// + private string GetImageQueuesReport(string[] showParams) + { + if (showParams.Length < 5 || showParams.Length > 6) + return "Usage: image queues show [full]"; + + string firstName = showParams[3]; + string lastName = showParams[4]; + + bool showChildAgents = showParams.Length == 6; + + List foundAgents = new List(); + + lock (m_scenes) + { + foreach (Scene scene in m_scenes.Values) + { + ScenePresence sp = scene.GetScenePresence(firstName, lastName); + if (sp != null && (showChildAgents || !sp.IsChildAgent)) + foundAgents.Add(sp); + } + } + + if (foundAgents.Count == 0) + return string.Format("No agents found for {0} {1}", firstName, lastName); + + StringBuilder report = new StringBuilder(); + + foreach (ScenePresence agent in foundAgents) + { + LLClientView client = agent.ControllingClient as LLClientView; + + if (client == null) + return "This command is only supported for LLClientView"; + + J2KImage[] images = client.ImageManager.GetImages(); + + report.AppendFormat( + "In region {0} ({1} agent)\n", + agent.Scene.RegionInfo.RegionName, agent.IsChildAgent ? "child" : "root"); + report.AppendFormat("Images in queue: {0}\n", images.Length); + + if (images.Length > 0) + { + report.AppendFormat( + "{0,-36} {1,-8} {2,-10} {3,-9} {4,-9} {5,-7}\n", + "Texture ID", + "Last Seq", + "Priority", + "Start Pkt", + "Has Asset", + "Decoded"); + + foreach (J2KImage image in images) + report.AppendFormat( + "{0,36} {1,8} {2,10} {3,10} {4,9} {5,7}\n", + image.TextureID, image.LastSequence, image.Priority, image.StartPacket, image.HasAsset, image.IsDecoded); + } + } + + return report.ToString(); + } /// /// Generate UDP Queue data report for each client diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs new file mode 100644 index 0000000000..a5207ebcb0 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs @@ -0,0 +1,185 @@ +/* + * 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.IO; +using System.Reflection; +using System.Text; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.OptionalModules.Asset +{ + /// + /// A module that just holds commands for inspecting assets. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AssetInfoModule")] + public class AssetInfoModule : ISharedRegionModule + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + + public string Name { get { return "Asset Information Module"; } } + + public Type ReplaceableInterface { get { return null; } } + + public void Initialise(IConfigSource source) + { +// m_log.DebugFormat("[ASSET INFO MODULE]: INITIALIZED MODULE"); + } + + public void PostInitialise() + { +// m_log.DebugFormat("[ASSET INFO MODULE]: POST INITIALIZED MODULE"); + } + + public void Close() + { +// m_log.DebugFormat("[ASSET INFO MODULE]: CLOSED MODULE"); + } + + public void AddRegion(Scene scene) + { +// m_log.DebugFormat("[ASSET INFO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); + } + + public void RemoveRegion(Scene scene) + { +// m_log.DebugFormat("[ASSET INFO MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); + } + + public void RegionLoaded(Scene scene) + { +// m_log.DebugFormat("[ASSET INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); + + if (m_scene == null) + m_scene = scene; + + MainConsole.Instance.Commands.AddCommand( + "asset", + false, + "show asset", + "show asset ", + "Show asset information", + HandleShowAsset); + + MainConsole.Instance.Commands.AddCommand( + "asset", false, "dump asset", + "dump asset ", + "Dump an asset", + HandleDumpAsset); + } + + void HandleDumpAsset(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Usage is dump asset "); + return; + } + + UUID assetId; + string rawAssetId = args[2]; + + if (!UUID.TryParse(rawAssetId, out assetId)) + { + MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid ID format", rawAssetId); + return; + } + + AssetBase asset = m_scene.AssetService.Get(assetId.ToString()); + if (asset == null) + { + MainConsole.Instance.OutputFormat("ERROR: No asset found with ID {0}", assetId); + return; + } + + string fileName = rawAssetId; + + using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) + { + using (BinaryWriter bw = new BinaryWriter(fs)) + { + bw.Write(asset.Data); + } + } + + MainConsole.Instance.OutputFormat("Asset dumped to file {0}", fileName); + } + + void HandleShowAsset(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Syntax: show asset "); + return; + } + + AssetBase asset = m_scene.AssetService.Get(args[2]); + + if (asset == null || asset.Data.Length == 0) + { + MainConsole.Instance.Output("Asset not found"); + return; + } + + int i; + + MainConsole.Instance.OutputFormat("Name: {0}", asset.Name); + MainConsole.Instance.OutputFormat("Description: {0}", asset.Description); + MainConsole.Instance.OutputFormat("Type: {0} (type number = {1})", (AssetType)asset.Type, asset.Type); + MainConsole.Instance.OutputFormat("Content-type: {0}", asset.Metadata.ContentType); + MainConsole.Instance.OutputFormat("Size: {0} bytes", asset.Data.Length); + MainConsole.Instance.OutputFormat("Temporary: {0}", asset.Temporary ? "yes" : "no"); + MainConsole.Instance.OutputFormat("Flags: {0}", asset.Metadata.Flags); + + for (i = 0 ; i < 5 ; i++) + { + int off = i * 16; + if (asset.Data.Length <= off) + break; + int len = 16; + if (asset.Data.Length < off + len) + len = asset.Data.Length - off; + + byte[] line = new byte[len]; + Array.Copy(asset.Data, off, line, 0, len); + + string text = BitConverter.ToString(line); + MainConsole.Instance.Output(String.Format("{0:x4}: {1}", off, text)); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs index 1ce24f1745..2369d94aa1 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Appearance/AppearanceInfoModule.cs @@ -27,6 +27,7 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Reflection; using System.Text; using log4net; @@ -114,6 +115,23 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance "Send appearance data for each avatar in the simulator to other viewers.", "Optionally, you can specify that only a particular avatar's appearance data is sent.", HandleSendAppearanceCommand); + + scene.AddCommand( + this, "appearance rebake", + "appearance rebake ", + "Send a request to the user's viewer for it to rebake and reupload its appearance textures.", + "This is currently done for all baked texture references previously received, whether the simulator can find the asset or not." + + "\nThis will only work for texture ids that the viewer has already uploaded." + + "\nIf the viewer has not yet sent the server any texture ids then nothing will happen" + + "\nsince requests can only be made for ids that the client has already sent us", + HandleRebakeAppearanceCommand); + + scene.AddCommand( + this, "appearance find", + "appearance find ", + "Find out which avatar uses the given asset as a baked texture, if any.", + "You can specify just the beginning of the uuid, e.g. 2008a8d. A longer UUID must be in dashed format.", + HandleFindAppearanceCommand); } private void HandleSendAppearanceCommand(string module, string[] cmd) @@ -210,6 +228,81 @@ namespace OpenSim.Region.OptionalModules.Avatar.Appearance } } } - } + } + + private void HandleRebakeAppearanceCommand(string module, string[] cmd) + { + if (cmd.Length != 4) + { + MainConsole.Instance.OutputFormat("Usage: appearance rebake "); + return; + } + + string firstname = cmd[2]; + string lastname = cmd[3]; + + lock (m_scenes) + { + foreach (Scene scene in m_scenes.Values) + { + ScenePresence sp = scene.GetScenePresence(firstname, lastname); + if (sp != null && !sp.IsChildAgent) + { + int rebakesRequested = scene.AvatarFactory.RequestRebake(sp, false); + + if (rebakesRequested > 0) + MainConsole.Instance.OutputFormat( + "Requesting rebake of {0} uploaded textures for {1} in {2}", + rebakesRequested, sp.Name, scene.RegionInfo.RegionName); + else + MainConsole.Instance.OutputFormat( + "No texture IDs available for rebake request for {0} in {1}", + sp.Name, scene.RegionInfo.RegionName); + } + } + } + } + + protected void HandleFindAppearanceCommand(string module, string[] cmd) + { + if (cmd.Length != 3) + { + MainConsole.Instance.OutputFormat("Usage: appearance find "); + return; + } + + string rawUuid = cmd[2]; + + HashSet matchedAvatars = new HashSet(); + + lock (m_scenes) + { + foreach (Scene scene in m_scenes.Values) + { + scene.ForEachRootScenePresence( + sp => + { + Dictionary bakedFaces = scene.AvatarFactory.GetBakedTextureFaces(sp.UUID); + foreach (Primitive.TextureEntryFace face in bakedFaces.Values) + { + if (face != null && face.TextureID.ToString().StartsWith(rawUuid)) + matchedAvatars.Add(sp); + } + }); + } + } + + if (matchedAvatars.Count == 0) + { + MainConsole.Instance.OutputFormat("{0} did not match any baked avatar textures in use", rawUuid); + } + else + { + MainConsole.Instance.OutputFormat( + "{0} matched {1}", + rawUuid, + string.Join(", ", matchedAvatars.ToList().ConvertAll(sp => sp.Name).ToArray())); + } + } } } \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 740dbdda39..b60cd4206f 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -713,7 +713,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (money != null) { // do the transaction, that is if the agent has got sufficient funds - if (!money.AmountCovered(remoteClient, money.GroupCreationCharge)) { + if (!money.AmountCovered(remoteClient.AgentId, money.GroupCreationCharge)) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got issuficient funds to create a group."); return UUID.Zero; } diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IInventoryItem.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IInventoryItem.cs index 16cd7e454e..a8e545cc06 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IInventoryItem.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/Interfaces/IInventoryItem.cs @@ -30,8 +30,7 @@ using OpenMetaverse; using OpenMetaverse.Assets; namespace OpenSim.Region.OptionalModules.Scripting.Minimodule -{ - +{ /// /// This implements the methods needed to operate on individual inventory items. /// @@ -39,6 +38,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { int Type { get; } UUID AssetID { get; } - T RetrieveAsset() where T : Asset, new(); + T RetrieveAsset() where T : OpenMetaverse.Assets.Asset, new(); } } diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index 4c4f5fb890..d2810bec71 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -44,12 +44,13 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.OptionalModules.Scripting.RegionReady { - public class RegionReadyModule : INonSharedRegionModule + public class RegionReadyModule : IRegionReadyModule, INonSharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IConfig m_config = null; + private bool m_ScriptRez; private bool m_firstEmptyCompileQueue; private bool m_oarFileLoading; private bool m_lastOarLoadedOk; @@ -93,14 +94,17 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady if (!m_enabled) return; + m_scene = scene; + + m_scene.RegisterModuleInterface(this); + + m_ScriptRez = false; m_firstEmptyCompileQueue = true; m_oarFileLoading = false; m_lastOarLoadedOk = true; - m_scene = scene; - - m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; + m_scene.EventManager.OnRezScript += OnRezScript; m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; m_log.DebugFormat("[RegionReady]: Enabled for region {0}", scene.RegionInfo.RegionName); @@ -118,6 +122,16 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } } + void OnRezScript (uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource) + { + if (!m_ScriptRez) + { + m_ScriptRez = true; + m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; + m_scene.EventManager.OnRezScript -= OnRezScript; + } + } + public void RemoveRegion(Scene scene) { if (!m_enabled) @@ -125,6 +139,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; m_scene.EventManager.OnOarFileLoaded -= OnOarFileLoaded; + m_scene.EventManager.OnLoginsEnabled -= OnLoginsEnabled; if(m_uri != string.Empty) { @@ -148,9 +163,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } #endregion - + + void OnEmptyScriptCompileQueue(int numScriptsFailed, string message) { + m_log.InfoFormat("[RegionReady]: Script compile queue empty!"); + if (m_firstEmptyCompileQueue || m_oarFileLoading) { OSChatMessage c = new OSChatMessage(); @@ -197,6 +215,10 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } } + // This will be triggerd by Scene if we have no scripts + // m_ScriptsRezzing will be false if there were none + // else it will be true and we should wait on the + // empty compile queue void OnLoginsEnabled(string regionName) { if (m_disable_logins == true) @@ -205,7 +227,12 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady { m_scene.LoginsDisabled = false; m_scene.LoginLock = false; - m_log.InfoFormat("[RegionReady]: Logins enabled for {0}", m_scene.RegionInfo.RegionName); + + m_scene.EventManager.OnEmptyScriptCompileQueue -= OnEmptyScriptCompileQueue; + + m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", + m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); + if ( m_uri != string.Empty ) { RRAlert("enabled"); @@ -214,6 +241,31 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } } + public void OarLoadingAlert(string msg) + { + // Let's bypass this for now until some better feedback can be established + // + return; + + if (msg == "load") + { + m_scene.EventManager.OnEmptyScriptCompileQueue += OnEmptyScriptCompileQueue; + m_scene.EventManager.OnOarFileLoaded += OnOarFileLoaded; + m_scene.EventManager.OnLoginsEnabled += OnLoginsEnabled; + m_scene.EventManager.OnRezScript += OnRezScript; + m_oarFileLoading = true; + m_firstEmptyCompileQueue = true; + + m_scene.LoginsDisabled = true; + m_scene.LoginLock = true; + if ( m_uri != string.Empty ) + { + RRAlert("loading oar"); + RRAlert("disabled"); + } + } + } + public void RRAlert(string status) { string request_method = "POST"; diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index 8fc50ff883..9c838d057c 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -775,11 +775,11 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule // Please do not refactor these to be just one method // Existing implementations need the distinction // - public bool UploadCovered(IClientAPI client, int amount) + public bool UploadCovered(UUID agentID, int amount) { return true; } - public bool AmountCovered(IClientAPI client, int amount) + public bool AmountCovered(UUID agentID, int amount) { return true; } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 84055cceba..6d40a92e2e 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -31,24 +31,32 @@ using System.Net; using OpenMetaverse; using OpenMetaverse.Packets; using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Estate; namespace OpenSim.Region.OptionalModules.World.NPC { - public class NPCAvatar : IClientAPI + public class NPCAvatar : IClientAPI, INPC { + public bool SenseAsAgent { get; set; } + private readonly string m_firstname; private readonly string m_lastname; private readonly Vector3 m_startPos; private readonly UUID m_uuid = UUID.Random(); private readonly Scene m_scene; + private readonly UUID m_ownerID; - public NPCAvatar(string firstname, string lastname, Vector3 position, Scene scene) + public NPCAvatar( + string firstname, string lastname, Vector3 position, UUID ownerID, bool senseAsAgent, Scene scene) { m_firstname = firstname; m_lastname = lastname; m_startPos = position; m_scene = scene; + m_ownerID = ownerID; + SenseAsAgent = senseAsAgent; } public IScene Scene @@ -56,6 +64,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC get { return m_scene; } } + public UUID OwnerID + { + get { return m_ownerID; } + } + public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } public void Say(string message) @@ -327,6 +340,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC public event EstateTeleportOneUserHomeRequest OnEstateTeleportOneUserHomeRequest; public event EstateTeleportAllUsersHomeRequest OnEstateTeleportAllUsersHomeRequest; public event EstateChangeInfo OnEstateChangeInfo; + public event EstateManageTelehub OnEstateManageTelehub; public event ScriptReset OnScriptReset; public event GetScriptRunning OnGetScriptRunning; public event SetScriptRunning OnSetScriptRunning; @@ -916,6 +930,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void SendEstateCovenantInformation(UUID covenant) { } + public void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List SpawnPoint) + { + } public void SendDetailedEstateData(UUID invoice, string estateName, uint estateID, uint parentEstate, uint estateFlags, uint sunPosition, UUID covenant, string abuseEmail, UUID estateOwner) { } diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs index 56ff3675ac..3831d7a416 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCModule.cs @@ -56,6 +56,24 @@ namespace OpenSim.Region.OptionalModules.World.NPC } } + public void PostInitialise() + { + } + + public void Close() + { + } + + public string Name + { + get { return "NPCModule"; } + } + + public bool IsSharedModule + { + get { return true; } + } + public bool IsNPC(UUID agentId, Scene scene) { // FIXME: This implementation could not just use the ScenePresence.PresenceType (and callers could inspect @@ -91,9 +109,15 @@ namespace OpenSim.Region.OptionalModules.World.NPC } public UUID CreateNPC( - string firstname, string lastname, Vector3 position, Scene scene, AvatarAppearance appearance) + string firstname, + string lastname, + Vector3 position, + UUID owner, + bool senseAsAgent, + Scene scene, + AvatarAppearance appearance) { - NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, scene); + NPCAvatar npcAvatar = new NPCAvatar(firstname, lastname, position, owner, senseAsAgent, scene); npcAvatar.CircuitCode = (uint)Util.RandomClass.Next(0, int.MaxValue); m_log.DebugFormat( @@ -234,11 +258,37 @@ namespace OpenSim.Region.OptionalModules.World.NPC return false; } - public bool DeleteNPC(UUID agentID, Scene scene) + public UUID GetOwner(UUID agentID) + { + lock (m_avatars) + { + NPCAvatar av; + if (m_avatars.TryGetValue(agentID, out av)) + { + return av.OwnerID; + } + } + + return UUID.Zero; + } + + public INPC GetNPC(UUID agentID, Scene scene) { lock (m_avatars) { if (m_avatars.ContainsKey(agentID)) + return m_avatars[agentID]; + else + return null; + } + } + + public bool DeleteNPC(UUID agentID, Scene scene) + { + lock (m_avatars) + { + NPCAvatar av; + if (m_avatars.TryGetValue(agentID, out av)) { scene.RemoveClient(agentID, false); m_avatars.Remove(agentID); @@ -250,22 +300,27 @@ namespace OpenSim.Region.OptionalModules.World.NPC return false; } - public void PostInitialise() + public bool CheckPermissions(UUID npcID, UUID callerID) { + lock (m_avatars) + { + NPCAvatar av; + if (m_avatars.TryGetValue(npcID, out av)) + return CheckPermissions(av, callerID); + else + return false; + } } - public void Close() + /// + /// Check if the caller has permission to manipulate the given NPC. + /// + /// + /// + /// true if they do, false if they don't. + private bool CheckPermissions(NPCAvatar av, UUID callerID) { - } - - public string Name - { - get { return "NPCModule"; } - } - - public bool IsSharedModule - { - get { return true; } + return callerID == UUID.Zero || av.OwnerID == UUID.Zero || av.OwnerID == callerID; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index 9c66b2567a..d5078227ef 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests afm.SetAppearance(sp, originalTe, null); INPCModule npcModule = scene.RequestModuleInterface(); - UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance); + UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, scene, sp.Appearance); ScenePresence npc = scene.GetScenePresence(npcId); @@ -118,6 +118,26 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(umm.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); } + [Test] + public void TestRemove() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); +// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); + + Vector3 startPos = new Vector3(128, 128, 30); + INPCModule npcModule = scene.RequestModuleInterface(); + UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, UUID.Zero, true, scene, sp.Appearance); + + npcModule.DeleteNPC(npcId, scene); + + ScenePresence deletedNpc = scene.GetScenePresence(npcId); + + Assert.That(deletedNpc, Is.Null); + } + [Test] public void TestAttachments() { @@ -137,7 +157,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests am.RezSingleAttachmentFromInventory(sp, attItemId, (uint)AttachmentPoint.Chest); INPCModule npcModule = scene.RequestModuleInterface(); - UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance); + UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, scene, sp.Appearance); ScenePresence npc = scene.GetScenePresence(npcId); @@ -169,7 +189,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Vector3 startPos = new Vector3(128, 128, 30); INPCModule npcModule = scene.RequestModuleInterface(); - UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, scene, sp.Appearance); + UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, UUID.Zero, true, scene, sp.Appearance); ScenePresence npc = scene.GetScenePresence(npcId); Assert.That(npc.AbsolutePosition, Is.EqualTo(startPos)); @@ -240,7 +260,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Vector3 startPos = new Vector3(128, 128, 30); INPCModule npcModule = scene.RequestModuleInterface(); - UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, scene, sp.Appearance); + UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, UUID.Zero, true, scene, sp.Appearance); ScenePresence npc = scene.GetScenePresence(npcId); SceneObjectPart part = SceneHelpers.AddSceneObject(scene); @@ -273,7 +293,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Vector3 startPos = new Vector3(1, 1, 1); INPCModule npcModule = scene.RequestModuleInterface(); - UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, scene, sp.Appearance); + UUID npcId = npcModule.CreateNPC("John", "Smith", startPos, UUID.Zero, true, scene, sp.Appearance); ScenePresence npc = scene.GetScenePresence(npcId); SceneObjectPart part = SceneHelpers.AddSceneObject(scene); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 770400265a..e9a849c839 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -72,6 +72,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters private bool m_initialized = false; + private int m_detailedStatsStep = 0; + public IMesher mesher; private float m_meshLOD; public float MeshLOD @@ -192,6 +194,8 @@ public class BSScene : PhysicsScene, IPhysicsParameters m_meshLOD = 8f; m_sculptLOD = 32f; + m_detailedStatsStep = 0; // disabled + m_maxSubSteps = 10; m_fixedTimeStep = 1f / 60f; m_maxCollisionsPerFrame = 2048; @@ -209,8 +213,9 @@ public class BSScene : PhysicsScene, IPhysicsParameters parms.deactivationTime = 0.2f; parms.linearSleepingThreshold = 0.8f; parms.angularSleepingThreshold = 1.0f; - parms.ccdMotionThreshold = 0.5f; // set to zero to disable - parms.ccdSweptSphereRadius = 0.2f; + parms.ccdMotionThreshold = 0.0f; // set to zero to disable + parms.ccdSweptSphereRadius = 0.0f; + parms.contactProcessingThreshold = 0.1f; parms.terrainFriction = 0.5f; parms.terrainHitFraction = 0.8f; @@ -231,6 +236,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters _meshSculptedPrim = pConfig.GetBoolean("MeshSculptedPrim", _meshSculptedPrim); _forceSimplePrimMeshing = pConfig.GetBoolean("ForceSimplePrimMeshing", _forceSimplePrimMeshing); + m_detailedStatsStep = pConfig.GetInt("DetailedStatsStep", m_detailedStatsStep); m_meshLOD = pConfig.GetFloat("MeshLevelOfDetail", m_meshLOD); m_sculptLOD = pConfig.GetFloat("SculptLevelOfDetail", m_sculptLOD); @@ -253,6 +259,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters parms.angularSleepingThreshold = pConfig.GetFloat("AngularSleepingThreshold", parms.angularSleepingThreshold); parms.ccdMotionThreshold = pConfig.GetFloat("CcdMotionThreshold", parms.ccdMotionThreshold); parms.ccdSweptSphereRadius = pConfig.GetFloat("CcdSweptSphereRadius", parms.ccdSweptSphereRadius); + parms.contactProcessingThreshold = pConfig.GetFloat("ContactProcessingThreshold", parms.contactProcessingThreshold); parms.terrainFriction = pConfig.GetFloat("TerrainFriction", parms.terrainFriction); parms.terrainHitFraction = pConfig.GetFloat("TerrainHitFraction", parms.terrainHitFraction); @@ -398,6 +405,14 @@ public class BSScene : PhysicsScene, IPhysicsParameters } } + if (m_detailedStatsStep > 0) + { + if ((m_simulationStep % m_detailedStatsStep) == 0) + { + BulletSimAPI.DumpBulletStatistics(); + } + } + // TODO: FIX THIS: fps calculation wrong. This calculation always returns about 1 in normal operation. return timeStep / (numSubSteps * m_fixedTimeStep) * 1000f; } @@ -671,6 +686,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters new PhysParameterEntry("MaxSubStep", "In simulation step, maximum number of substeps"), new PhysParameterEntry("FixedTimeStep", "In simulation step, seconds of one substep (1/60)"), new PhysParameterEntry("MaxObjectMass", "Maximum object mass (10000.01)"), + new PhysParameterEntry("DetailedStats", "Frames between outputting detailed phys stats. Zero is off"), new PhysParameterEntry("DefaultFriction", "Friction factor used on new objects"), new PhysParameterEntry("DefaultDensity", "Density for new objects" ), @@ -685,6 +701,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters new PhysParameterEntry("AngularSleepingThreshold", "Seconds to measure angular movement before considering static" ), // new PhysParameterEntry("CcdMotionThreshold", "" ), // new PhysParameterEntry("CcdSweptSphereRadius", "" ), + new PhysParameterEntry("ContactProcessingThreshold", "Distance between contacts before doing collision check" ), new PhysParameterEntry("TerrainFriction", "Factor to reduce movement against terrain surface" ), new PhysParameterEntry("TerrainHitFraction", "Distance to measure hit collisions" ), @@ -715,6 +732,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters string lparm = parm.ToLower(); switch (lparm) { + case "detailedstats": m_detailedStatsStep = (int)val; break; case "meshlod": m_meshLOD = (int)val; break; case "sculptlod": m_sculptLOD = (int)val; break; case "maxsubstep": m_maxSubSteps = (int)val; break; @@ -725,7 +743,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "defaultdensity": m_params[0].defaultDensity = val; break; case "defaultrestitution": m_params[0].defaultRestitution = val; break; case "collisionmargin": m_params[0].collisionMargin = val; break; - case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, PhysParameterEntry.APPLY_TO_NONE, val); break; + case "gravity": m_params[0].gravity = val; TaintedUpdateParameter(lparm, PhysParameterEntry.APPLY_TO_NONE, val); break; case "lineardamping": UpdateParameterPrims(ref m_params[0].linearDamping, lparm, localID, val); break; case "angulardamping": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; @@ -734,6 +752,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "angularsleepingthreshold": UpdateParameterPrims(ref m_params[0].angularDamping, lparm, localID, val); break; case "ccdmotionthreshold": UpdateParameterPrims(ref m_params[0].ccdMotionThreshold, lparm, localID, val); break; case "ccdsweptsphereradius": UpdateParameterPrims(ref m_params[0].ccdSweptSphereRadius, lparm, localID, val); break; + case "contactprocessingthreshold": UpdateParameterPrims(ref m_params[0].contactProcessingThreshold, lparm, localID, val); break; // set a terrain physical feature and cause terrain to be recalculated case "terrainfriction": m_params[0].terrainFriction = val; TaintedUpdateParameter("terrain", 0, val); break; @@ -741,10 +760,10 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "terrainrestitution": m_params[0].terrainRestitution = val; TaintedUpdateParameter("terrain", 0, val); break; // set an avatar physical feature and cause avatar(s) to be recalculated case "avatarfriction": UpdateParameterAvatars(ref m_params[0].avatarFriction, "avatar", localID, val); break; - case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; + case "avatardensity": UpdateParameterAvatars(ref m_params[0].avatarDensity, "avatar", localID, val); break; case "avatarrestitution": UpdateParameterAvatars(ref m_params[0].avatarRestitution, "avatar", localID, val); break; - case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; - case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; + case "avatarcapsuleradius": UpdateParameterAvatars(ref m_params[0].avatarCapsuleRadius, "avatar", localID, val); break; + case "avatarcapsuleheight": UpdateParameterAvatars(ref m_params[0].avatarCapsuleHeight, "avatar", localID, val); break; default: ret = false; break; } @@ -816,6 +835,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters bool ret = true; switch (parm.ToLower()) { + case "detailedstats": val = (int)m_detailedStatsStep; break; case "meshlod": val = (float)m_meshLOD; break; case "sculptlod": val = (float)m_sculptLOD; break; case "maxsubstep": val = (float)m_maxSubSteps; break; @@ -835,6 +855,7 @@ public class BSScene : PhysicsScene, IPhysicsParameters case "angularsleepingthreshold": val = m_params[0].angularDamping; break; case "ccdmotionthreshold": val = m_params[0].ccdMotionThreshold; break; case "ccdsweptsphereradius": val = m_params[0].ccdSweptSphereRadius; break; + case "contactprocessingthreshold": val = m_params[0].contactProcessingThreshold; break; case "terrainfriction": val = m_params[0].terrainFriction; break; case "terrainhitfraction": val = m_params[0].terrainHitFraction; break; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index a610c8d2d9..d12bd7dcca 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -122,6 +122,7 @@ public struct ConfigurationParameters public float angularSleepingThreshold; public float ccdMotionThreshold; public float ccdSweptSphereRadius; + public float contactProcessingThreshold; public float terrainFriction; public float terrainHitFraction; @@ -248,6 +249,9 @@ public static extern RaycastHit RayTest(uint worldID, uint id, Vector3 from, Vec [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 RecoverFromPenetration(uint worldID, uint id); +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void DumpBulletStatistics(); + // Log a debug message [UnmanagedFunctionPointer(CallingConvention.Cdecl)] public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index 68999fc283..7c1c046522 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -134,9 +134,18 @@ namespace OpenSim.Region.Physics.OdePlugin | CollisionCategories.Body | CollisionCategories.Character | CollisionCategories.Land); - internal IntPtr Body = IntPtr.Zero; + /// + /// Body for dynamics simulation + /// + internal IntPtr Body { get; private set; } + private OdeScene _parent_scene; - internal IntPtr Shell = IntPtr.Zero; + + /// + /// Collision geometry + /// + internal IntPtr Shell { get; private set; } + private IntPtr Amotor = IntPtr.Zero; private d.Mass ShellMass; @@ -1018,6 +1027,13 @@ namespace OpenSim.Region.Physics.OdePlugin /// private void CreateOdeStructures(float npositionX, float npositionY, float npositionZ, float tensor) { + if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) + { + m_log.ErrorFormat( + "[ODE CHARACTER]: Creating ODE structures for {0} even though some already exist. Shell = {1}, Body = {2}, Amotor = {3}", + Name, Shell, Body, Amotor); + } + int dAMotorEuler = 1; // _parent_scene.waitForSpaceUnlock(_parent_scene.space); if (CAPSULE_LENGTH <= 0) @@ -1032,6 +1048,7 @@ namespace OpenSim.Region.Physics.OdePlugin CAPSULE_RADIUS = 0.01f; } +// lock (OdeScene.UniversalColliderSyncObject) Shell = d.CreateCapsule(_parent_scene.space, CAPSULE_RADIUS, CAPSULE_LENGTH); d.GeomSetCategoryBits(Shell, (int)m_collisionCategories); @@ -1135,6 +1152,14 @@ namespace OpenSim.Region.Physics.OdePlugin /// internal void DestroyOdeStructures() { + // Create avatar capsule and related ODE data + if (Shell == IntPtr.Zero || Body == IntPtr.Zero || Amotor == IntPtr.Zero) + { + m_log.ErrorFormat( + "[ODE CHARACTER]: Destroying ODE structures for {0} even though some are already null. Shell = {1}, Body = {2}, Amotor = {3}", + Name, Shell, Body, Amotor); + } + // destroy avatar capsule and related ODE data if (Amotor != IntPtr.Zero) { @@ -1155,7 +1180,9 @@ namespace OpenSim.Region.Physics.OdePlugin if (Shell != IntPtr.Zero) { +// lock (OdeScene.UniversalColliderSyncObject) d.GeomDestroy(Shell); + _parent_scene.geom_name_map.Remove(Shell); _parent_scene.actor_name_map.Remove(Shell); @@ -1260,15 +1287,6 @@ namespace OpenSim.Region.Physics.OdePlugin { if (m_tainted_isPhysical) { - // Create avatar capsule and related ODE data - if (!(Shell == IntPtr.Zero && Body == IntPtr.Zero && Amotor == IntPtr.Zero)) - { - m_log.Warn("[ODE CHARACTER]: re-creating the following avatar ODE data for " + Name + ", even though it already exists - " - + (Shell!=IntPtr.Zero ? "Shell ":"") - + (Body!=IntPtr.Zero ? "Body ":"") - + (Amotor!=IntPtr.Zero ? "Amotor ":"")); - } - CreateOdeStructures(_position.X, _position.Y, _position.Z, m_tensor); _parent_scene.AddCharacter(this); } diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index 228eca9896..4530c09464 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -105,6 +105,32 @@ namespace OpenSim.Region.Physics.OdePlugin private readonly ILog m_log; // private Dictionary m_storedCollisions = new Dictionary(); + /// + /// Provide a sync object so that only one thread calls d.Collide() at a time across all OdeScene instances. + /// + /// + /// With ODE as of r1755 (though also tested on r1860), only one thread can call d.Collide() at a + /// time, even where physics objects are in entirely different ODE worlds. This is because generating contacts + /// uses a static cache at the ODE level. + /// + /// Without locking, simulators running multiple regions will eventually crash with a native stack trace similar + /// to + /// + /// mono() [0x489171] + /// mono() [0x4d154f] + /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f6ded592c60] + /// .../opensim/bin/libode-x86_64.so(_ZN6Opcode11OBBCollider8_CollideEPKNS_14AABBNoLeafNodeE+0xd7a) [0x7f6dd822628a] + /// + /// ODE provides an experimental option to cache in thread local storage but compiling ODE with this option + /// causes OpenSimulator to immediately crash with a native stack trace similar to + /// + /// mono() [0x489171] + /// mono() [0x4d154f] + /// /lib/x86_64-linux-gnu/libpthread.so.0(+0xfc60) [0x7f03c9849c60] + /// .../opensim/bin/libode-x86_64.so(_Z12dCollideCCTLP6dxGeomS0_iP12dContactGeomi+0x92) [0x7f03b44bcf82] + /// + internal static Object UniversalColliderSyncObject = new Object(); + private Random fluidRandomizer = new Random(Environment.TickCount); private const uint m_regionWidth = Constants.RegionSize; @@ -799,7 +825,9 @@ namespace OpenSim.Region.Physics.OdePlugin if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) return; - count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); + lock (OdeScene.UniversalColliderSyncObject) + count = d.Collide(g1, g2, contacts.Length, contacts, d.ContactGeom.SizeOf); + if (count > contacts.Length) m_log.Error("[ODE SCENE]: Got " + count + " contacts when we asked for a maximum of " + contacts.Length); } @@ -1525,7 +1553,7 @@ namespace OpenSim.Region.Physics.OdePlugin chr.CollidingGround = false; chr.CollidingObj = false; - // test the avatar's geometry for collision with the space + // Test the avatar's geometry for collision with the space // This will return near and the space that they are the closest to // And we'll run this again against the avatar and the space segment // This will return with a bunch of possible objects in the space segment diff --git a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs index 581a9a9443..17c270810f 100644 --- a/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs +++ b/OpenSim/Region/ScriptEngine/Interfaces/IScriptEngine.cs @@ -42,10 +42,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces /// An interface for a script API module to communicate with /// the engine it's running under /// - - public delegate void ScriptRemoved(UUID script); - public delegate void ObjectRemoved(UUID prim); - public interface IScriptEngine { /// @@ -57,9 +53,6 @@ namespace OpenSim.Region.ScriptEngine.Interfaces IScriptModule ScriptModule { get; } - event ScriptRemoved OnScriptRemoved; - event ObjectRemoved OnObjectRemoved; - /// /// Post an event to a single script /// diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 443e7a5701..67dee021c8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -126,11 +126,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_TransferModule = m_ScriptEngine.World.RequestModuleInterface(); m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); - if (m_UrlModule != null) - { - m_ScriptEngine.OnScriptRemoved += m_UrlModule.ScriptRemoved; - m_ScriptEngine.OnObjectRemoved += m_UrlModule.ObjectRemoved; - } AsyncCommands = new AsyncCommandManager(ScriptEngine); } @@ -468,26 +463,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke - // Old implementation of llRot2Euler. Normalization not required as Atan2 function will - // only return values >= -PI (-180 degrees) and <= PI (180 degrees). - + /// + /// Convert an LSL rotation to a Euler vector. + /// + /// + /// Using algorithm based off http://www.euclideanspace.com/maths/geometry/rotations/conversions/quaternionToEuler/quat_2_euler_paper_ver2-1.pdf + /// to avoid issues with singularity and rounding with Y rotation of +/- PI/2 + /// + /// + /// public LSL_Vector llRot2Euler(LSL_Rotation r) { m_host.AddScriptLPS(1); - //This implementation is from http://lslwiki.net/lslwiki/wakka.php?wakka=LibraryRotationFunctions. ckrinke - LSL_Rotation t = new LSL_Rotation(r.x * r.x, r.y * r.y, r.z * r.z, r.s * r.s); - double m = (t.x + t.y + t.z + t.s); - if (m == 0) return new LSL_Vector(); - double n = 2 * (r.y * r.s + r.x * r.z); - double p = m * m - n * n; - if (p > 0) - return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), - Math.Atan2(n, Math.Sqrt(p)), - Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); - else if (n > 0) - return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); - else - return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); + + LSL_Vector v = new LSL_Vector(0.0, 0.0, 1.0) * r; // Z axis unit vector unaffected by Z rotation component of r. + double m = LSL_Vector.Mag(v); // Just in case v isn't normalized, need magnitude for Asin() operation later. + if (m == 0.0) return new LSL_Vector(); + double x = Math.Atan2(-v.y, v.z); + double sin = v.x / m; + if (sin < -0.999999 || sin > 0.999999) x = 0.0; // Force X rotation to 0 at the singularities. + double y = Math.Asin(sin); + // Rotate X axis unit vector by r and unwind the X and Y rotations leaving only the Z rotation + v = new LSL_Vector(1.0, 0.0, 0.0) * ((r * new LSL_Rotation(Math.Sin(-x / 2.0), 0.0, 0.0, Math.Cos(-x / 2.0))) * new LSL_Rotation(0.0, Math.Sin(-y / 2.0), 0.0, Math.Cos(-y / 2.0))); + double z = Math.Atan2(v.y, v.x); + + return new LSL_Vector(x, y, z); } /* From wiki: @@ -2856,11 +2856,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // we need to convert from a vector describing // the angles of rotation in radians into rotation value - LSL_Types.Quaternion rot = llEuler2Rot(angle); - Quaternion rotation = new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); - m_host.startLookAt(rotation, (float)damping, (float)strength); - // Orient the object to the angle calculated - //llSetRot(rot); + LSL_Rotation rot = llEuler2Rot(angle); + + // Per discussion with Melanie, for non-physical objects llLookAt appears to simply + // set the rotation of the object, copy that behavior + if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical) + { + llSetRot(rot); + } + else + { + m_host.StartLookAt(Rot2Quaternion(rot), (float)strength, (float)damping); + } } public void llStopLookAt() @@ -3236,8 +3243,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llRotLookAt(LSL_Rotation target, double strength, double damping) { m_host.AddScriptLPS(1); - Quaternion rot = new Quaternion((float)target.x, (float)target.y, (float)target.z, (float)target.s); - m_host.RotLookAt(rot, (float)strength, (float)damping); + + // Per discussion with Melanie, for non-physical objects llLookAt appears to simply + // set the rotation of the object, copy that behavior + if (strength == 0 || m_host.PhysActor == null || !m_host.PhysActor.IsPhysical) + { + llSetLocalRot(target); + } + else + { + m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); + } } public LSL_Integer llStringLength(string str) @@ -4023,9 +4039,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api Vector3 av3 = new Vector3(Util.Clip((float)color.x, 0.0f, 1.0f), Util.Clip((float)color.y, 0.0f, 1.0f), Util.Clip((float)color.z, 0.0f, 1.0f)); - m_host.SetText(text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); - m_host.ParentGroup.HasGroupChanged = true; - m_host.ParentGroup.ScheduleGroupForFullUpdate(); + m_host.SetText(text.Length > 254 ? text.Remove(255) : text, av3, Util.Clip((float)alpha, 0.0f, 1.0f)); + //m_host.ParentGroup.HasGroupChanged = true; + //m_host.ParentGroup.ScheduleGroupForFullUpdate(); } public LSL_Float llWater(LSL_Vector offset) @@ -4693,15 +4709,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return (double)Math.Asin(val); } - // Xantor 30/apr/2008 + // jcochran 5/jan/2012 public LSL_Float llAngleBetween(LSL_Rotation a, LSL_Rotation b) { m_host.AddScriptLPS(1); - double angle = Math.Acos(a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s) * 2; - if (angle < 0) angle = -angle; - if (angle > Math.PI) return (Math.PI * 2 - angle); - return angle; + double aa = (a.x * a.x + a.y * a.y + a.z * a.z + a.s * a.s); + double bb = (b.x * b.x + b.y * b.y + b.z * b.z + b.s * b.s); + double aa_bb = aa * bb; + if (aa_bb == 0) return 0.0; + double ab = (a.x * b.x + a.y * b.y + a.z * b.z + a.s * b.s); + double quotient = (ab * ab) / aa_bb; + if (quotient >= 1.0) return 0.0; + return Math.Acos(2 * quotient - 1); } public LSL_String llGetInventoryKey(string name) @@ -5486,7 +5506,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (GridRegion sri in neighbors) { - if (sri.RegionLocX == neighborX && sri.RegionLocY == neighborY) + if (sri.RegionCoordX == neighborX && sri.RegionCoordY == neighborY) return 0; } @@ -6583,7 +6603,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } // the rest of the permission checks are done in RezScript, so check the pin there as well - World.RezScript(srcId, m_host, destId, pin, running, start_param); + World.RezScriptFromPrim(srcId, m_host, destId, pin, running, start_param); + // this will cause the delay even if the script pin or permissions were wrong - seems ok ScriptSleep(3000); } @@ -7546,6 +7567,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(2000); } + public LSL_String llGetParcelMusicURL() + { + m_host.AddScriptLPS(1); + + ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); + + if (land.LandData.OwnerID != m_host.OwnerID) + return String.Empty; + + return land.GetMusicUrl(); + } + public LSL_Vector llGetRootPosition() { m_host.AddScriptLPS(1); @@ -10613,6 +10646,75 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return list; } + public LSL_Integer llManageEstateAccess(int action, string avatar) + { + m_host.AddScriptLPS(1); + EstateSettings estate = World.RegionInfo.EstateSettings; + bool isAccount = false; + bool isGroup = false; + + if (!estate.IsEstateOwner(m_host.OwnerID) || !estate.IsEstateManager(m_host.OwnerID)) + return 0; + + UUID id = new UUID(); + if (!UUID.TryParse(avatar, out id)) + return 0; + + UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, id); + isAccount = account != null ? true : false; + if (!isAccount) + { + IGroupsModule groups = World.RequestModuleInterface(); + if (groups != null) + { + GroupRecord group = groups.GetGroupRecord(id); + isGroup = group != null ? true : false; + if (!isGroup) + return 0; + } + else + return 0; + } + + switch (action) + { + case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_ADD: + if (!isAccount) return 0; + if (estate.HasAccess(id)) return 1; + if (estate.IsBanned(id)) + estate.RemoveBan(id); + estate.AddEstateUser(id); + break; + case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_AGENT_REMOVE: + if (!isAccount || !estate.HasAccess(id)) return 0; + estate.RemoveEstateUser(id); + break; + case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_ADD: + if (!isGroup) return 0; + if (estate.GroupAccess(id)) return 1; + estate.AddEstateGroup(id); + break; + case ScriptBaseClass.ESTATE_ACCESS_ALLOWED_GROUP_REMOVE: + if (!isGroup || !estate.GroupAccess(id)) return 0; + estate.RemoveEstateGroup(id); + break; + case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_ADD: + if (!isAccount) return 0; + if (estate.IsBanned(id)) return 1; + EstateBan ban = new EstateBan(); + ban.EstateID = estate.EstateID; + ban.BannedUserID = id; + estate.AddBan(ban); + break; + case ScriptBaseClass.ESTATE_ACCESS_BANNED_AGENT_REMOVE: + if (!isAccount || !estate.IsBanned(id)) return 0; + estate.RemoveBan(id); + break; + default: return 0; + } + return 1; + } + #region Not Implemented // // Listing the unimplemented lsl functions here, please move diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 503b5d090a..b1583ebb1e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -157,6 +157,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string risk = m_ScriptEngine.Config.GetString("OSFunctionThreatLevel", "VeryLow"); switch (risk) { + case "NoAccess": + m_MaxThreatLevel = ThreatLevel.NoAccess; + break; case "None": m_MaxThreatLevel = ThreatLevel.None; break; @@ -413,6 +416,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer osSetTerrainHeight(int x, int y, double val) { CheckThreatLevel(ThreatLevel.High, "osSetTerrainHeight"); + return SetTerrainHeight(x, y, val); } @@ -420,12 +424,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osTerrainSetHeight"); OSSLDeprecated("osTerrainSetHeight", "osSetTerrainHeight"); + return SetTerrainHeight(x, y, val); } private LSL_Integer SetTerrainHeight(int x, int y, double val) { m_host.AddScriptLPS(1); + if (x > ((int)Constants.RegionSize - 1) || x < 0 || y > ((int)Constants.RegionSize - 1) || y < 0) OSSLError("osSetTerrainHeight: Coordinate out of bounds"); @@ -465,6 +471,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osTerrainFlush() { CheckThreatLevel(ThreatLevel.VeryLow, "osTerrainFlush"); + m_host.AddScriptLPS(1); ITerrainModule terrainModule = World.RequestModuleInterface(); if (terrainModule != null) terrainModule.TaintTerrain(); @@ -736,7 +743,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // High because there is no security check. High griefer potential // - CheckThreatLevel(ThreatLevel.High, "osTeleportAgent"); + CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent"); TeleportAgent(agent, regionName, position, lookat, false); } @@ -753,11 +760,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // For osTeleportAgent, agent must be over owners land to avoid abuse // For osTeleportOwner, this restriction isn't necessary - if (relaxRestrictions || - m_host.OwnerID - == World.LandChannel.GetLandObject( - presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) - { + + // commented out because its redundant and uneeded please remove eventually. + // if (relaxRestrictions || + // m_host.OwnerID + // == World.LandChannel.GetLandObject( + // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) + // { + // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. Util.FireAndForget( @@ -766,7 +776,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); ScriptSleep(5000); - } + + // } + } } } @@ -775,7 +787,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // High because there is no security check. High griefer potential // - CheckThreatLevel(ThreatLevel.High, "osTeleportAgent"); + CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent"); TeleportAgent(agent, regionX, regionY, position, lookat, false); } @@ -794,11 +806,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { // For osTeleportAgent, agent must be over owners land to avoid abuse // For osTeleportOwner, this restriction isn't necessary - if (relaxRestrictions || - m_host.OwnerID - == World.LandChannel.GetLandObject( - presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) - { + + // commented out because its redundant and uneeded please remove eventually. + // if (relaxRestrictions || + // m_host.OwnerID + // == World.LandChannel.GetLandObject( + // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) + // { + // We will launch the teleport on a new thread so that when the script threads are terminated // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. Util.FireAndForget( @@ -807,7 +822,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); ScriptSleep(5000); - } + + // } + } } } @@ -871,6 +888,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // threat level is None as we could get this information with an // in-world script as well, just not as efficient CheckThreatLevel(ThreatLevel.None, "osGetAgents"); + m_host.AddScriptLPS(1); LSL_List result = new LSL_List(); World.ForEachRootScenePresence(delegate(ScenePresence sp) @@ -885,6 +903,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarPlayAnimation"); + AvatarPlayAnimation(avatar, animation); + } + + private void AvatarPlayAnimation(string avatar, string animation) + { UUID avatarID = (UUID)avatar; m_host.AddScriptLPS(1); @@ -918,6 +941,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryHigh, "osAvatarStopAnimation"); + AvatarStopAnimation(avatar, animation); + } + + private void AvatarStopAnimation(string avatar, string animation) + { UUID avatarID = (UUID)avatar; m_host.AddScriptLPS(1); @@ -1141,6 +1169,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // should be removed // CheckThreatLevel(ThreatLevel.High, "osSetStateEvents"); + m_host.AddScriptLPS(1); m_host.SetScriptEvents(m_itemID, events); } @@ -1488,7 +1517,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y); @@ -1549,6 +1577,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.High,"osGetSimulatorVersion"); m_host.AddScriptLPS(1); + return m_ScriptEngine.World.GetSimulatorVersion(); } @@ -1886,6 +1915,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osAvatarName2Key(string firstname, string lastname) { CheckThreatLevel(ThreatLevel.Low, "osAvatarName2Key"); + m_host.AddScriptLPS(1); UserAccount account = World.UserAccountService.GetUserAccount(World.RegionInfo.ScopeID, firstname, lastname); if (null == account) @@ -1901,6 +1931,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osKey2Name(string id) { CheckThreatLevel(ThreatLevel.Low, "osKey2Name"); + m_host.AddScriptLPS(1); + UUID key = new UUID(); if (UUID.TryParse(id, out key)) @@ -1921,6 +1953,69 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + private enum InfoType + { + Nick, + Name, + Login, + Home, + Custom + }; + + private string GridUserInfo(InfoType type) + { + return GridUserInfo(type, ""); + } + + private string GridUserInfo(InfoType type, string key) + { + string retval = String.Empty; + IConfigSource config = m_ScriptEngine.ConfigSource; + string url = config.Configs["GridInfo"].GetString("GridInfoURI", String.Empty); + + if (String.IsNullOrEmpty(url)) + return "Configuration Error!"; + + string verb ="/json_grid_info"; + OSDMap json = new OSDMap(); + + OSDMap info = WebUtil.GetFromService(String.Format("{0}{1}",url,verb), 3000); + + if (info["Success"] != true) + return "Get GridInfo Failed!"; + + json = (OSDMap)OSDParser.DeserializeJson(info["_RawResult"].AsString()); + + switch (type) + { + case InfoType.Nick: + retval = json["gridnick"]; + break; + + case InfoType.Name: + retval = json["gridname"]; + break; + + case InfoType.Login: + retval = json["login"]; + break; + + case InfoType.Home: + retval = json["home"]; + break; + + case InfoType.Custom: + retval = json[key]; + break; + + default: + retval = "error"; + break; + } + + return retval; + } + /// /// Get the nickname of this grid, as set in the [GridInfo] config section. /// @@ -1934,10 +2029,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridNick"); m_host.AddScriptLPS(1); - string nick = "hippogrid"; + + string nick = String.Empty; IConfigSource config = m_ScriptEngine.ConfigSource; + if (config.Configs["GridInfo"] != null) nick = config.Configs["GridInfo"].GetString("gridnick", nick); + + if (String.IsNullOrEmpty(nick)) + nick = GridUserInfo(InfoType.Nick); + return nick; } @@ -1945,10 +2046,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridName"); m_host.AddScriptLPS(1); - string name = "the lost continent of hippo"; + + string name = String.Empty; IConfigSource config = m_ScriptEngine.ConfigSource; + if (config.Configs["GridInfo"] != null) name = config.Configs["GridInfo"].GetString("gridname", name); + + if (String.IsNullOrEmpty(name)) + name = GridUserInfo(InfoType.Name); + return name; } @@ -1956,13 +2063,53 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridLoginURI"); m_host.AddScriptLPS(1); - string loginURI = "http://127.0.0.1:9000/"; + + string loginURI = String.Empty; IConfigSource config = m_ScriptEngine.ConfigSource; + if (config.Configs["GridInfo"] != null) loginURI = config.Configs["GridInfo"].GetString("login", loginURI); + + if (String.IsNullOrEmpty(loginURI)) + loginURI = GridUserInfo(InfoType.Login); + return loginURI; } + public string osGetGridHomeURI() + { + CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI"); + m_host.AddScriptLPS(1); + + string HomeURI = String.Empty; + IConfigSource config = m_ScriptEngine.ConfigSource; + + if (config.Configs["LoginService"] != null) + HomeURI = config.Configs["LoginService"].GetString("SRV_HomeURI", HomeURI); + + if (String.IsNullOrEmpty(HomeURI)) + HomeURI = GridUserInfo(InfoType.Home); + + return HomeURI; + } + + public string osGetGridCustom(string key) + { + CheckThreatLevel(ThreatLevel.Moderate, "osGetGridCustom"); + m_host.AddScriptLPS(1); + + string retval = String.Empty; + IConfigSource config = m_ScriptEngine.ConfigSource; + + if (config.Configs["GridInfo"] != null) + retval = config.Configs["GridInfo"].GetString(key, retval); + + if (String.IsNullOrEmpty(retval)) + retval = GridUserInfo(InfoType.Custom, key); + + return retval; + } + public LSL_String osFormatString(string str, LSL_List strings) { CheckThreatLevel(ThreatLevel.Low, "osFormatString"); @@ -2064,10 +2211,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return retVal; } + public LSL_Integer osIsNpc(LSL_Key npc) + { + CheckThreatLevel(ThreatLevel.None, "osIsNpc"); + m_host.AddScriptLPS(1); + + INPCModule module = World.RequestModuleInterface(); + if (module != null) + { + UUID npcId; + if (UUID.TryParse(npc.m_string, out npcId)) + if (module.IsNPC(npcId, World)) + return ScriptBaseClass.TRUE; + } + + return ScriptBaseClass.FALSE; + } + public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard) { CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); + m_host.AddScriptLPS(1); + return NpcCreate(firstname, lastname, position, notecard, false, true); + } + + public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) + { + CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); + m_host.AddScriptLPS(1); + + return NpcCreate( + firstname, lastname, position, notecard, + (options & ScriptBaseClass.OS_NPC_NOT_OWNED) == 0, + (options & ScriptBaseClass.OS_NPC_SENSE_AS_AGENT) == 0); + } + + private LSL_Key NpcCreate( + string firstname, string lastname, LSL_Vector position, string notecard, bool owned, bool senseAsAgent) + { INPCModule module = World.RequestModuleInterface(); if (module != null) { @@ -2096,9 +2278,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (appearance == null) return new LSL_Key(UUID.Zero.ToString()); + UUID ownerID = UUID.Zero; + if (owned) + ownerID = m_host.OwnerID; UUID x = module.CreateNPC(firstname, lastname, new Vector3((float) position.x, (float) position.y, (float) position.z), + ownerID, + senseAsAgent, World, appearance); @@ -2117,6 +2304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osNpcSaveAppearance(LSL_Key npc, string notecard) { CheckThreatLevel(ThreatLevel.High, "osNpcSaveAppearance"); + m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); @@ -2126,7 +2314,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(npc.m_string, out npcId)) return new LSL_Key(UUID.Zero.ToString()); - if (!npcModule.IsNPC(npcId, m_host.ParentGroup.Scene)) + if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) return new LSL_Key(UUID.Zero.ToString()); return SaveAppearanceToNotecard(npcId, notecard); @@ -2138,6 +2326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcLoadAppearance(LSL_Key npc, string notecard) { CheckThreatLevel(ThreatLevel.High, "osNpcLoadAppearance"); + m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); @@ -2147,6 +2336,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(npc.m_string, out npcId)) return; + if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) + return; + string appearanceSerialized = LoadNotecard(notecard); OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); @@ -2159,9 +2351,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + public LSL_Key osNpcGetOwner(LSL_Key npc) + { + CheckThreatLevel(ThreatLevel.None, "osNpcGetOwner"); + m_host.AddScriptLPS(1); + + INPCModule npcModule = World.RequestModuleInterface(); + if (npcModule != null) + { + UUID npcId; + if (UUID.TryParse(npc.m_string, out npcId)) + { + UUID owner = npcModule.GetOwner(npcId); + if (owner != UUID.Zero) + return new LSL_Key(owner.ToString()); + else + return npc; + } + } + + return new LSL_Key(UUID.Zero.ToString()); + } + public LSL_Vector osNpcGetPos(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcGetPos"); + m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); if (npcModule != null) @@ -2170,7 +2385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(npc.m_string, out npcId)) return new LSL_Vector(0, 0, 0); - if (!npcModule.IsNPC(npcId, m_host.ParentGroup.Scene)) + if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) return new LSL_Vector(0, 0, 0); Vector3 pos = World.GetScenePresence(npcId).AbsolutePosition; @@ -2183,6 +2398,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); + m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -2190,6 +2406,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID npcId; if (!UUID.TryParse(npc.m_string, out npcId)) return; + + if (!module.CheckPermissions(npcId, m_host.OwnerID)) + return; Vector3 pos = new Vector3((float) position.x, (float) position.y, (float) position.z); module.MoveToTarget(npcId, World, pos, false, true); @@ -2199,6 +2418,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcMoveToTarget(LSL_Key npc, LSL_Vector target, int options) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveToTarget"); + m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -2207,6 +2427,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(npc.m_string, out npcId)) return; + if (!module.CheckPermissions(npcId, m_host.OwnerID)) + return; + Vector3 pos = new Vector3((float)target.x, (float)target.y, (float)target.z); module.MoveToTarget( new UUID(npc.m_string), @@ -2220,6 +2443,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Rotation osNpcGetRot(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcGetRot"); + m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); if (npcModule != null) @@ -2228,7 +2452,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(npc.m_string, out npcId)) return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); - if (!npcModule.IsNPC(npcId, m_host.ParentGroup.Scene)) + if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) return new LSL_Rotation(Quaternion.Identity.X, Quaternion.Identity.Y, Quaternion.Identity.Z, Quaternion.Identity.W); ScenePresence sp = World.GetScenePresence(npcId); @@ -2243,6 +2467,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation) { CheckThreatLevel(ThreatLevel.High, "osNpcSetRot"); + m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); if (npcModule != null) @@ -2251,7 +2476,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!UUID.TryParse(npc.m_string, out npcId)) return; - if (!npcModule.IsNPC(npcId, m_host.ParentGroup.Scene)) + if (!npcModule.CheckPermissions(npcId, m_host.OwnerID)) return; ScenePresence sp = World.GetScenePresence(npcId); @@ -2262,53 +2487,115 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcStopMoveToTarget(LSL_Key npc) { CheckThreatLevel(ThreatLevel.VeryLow, "osNpcStopMoveTo"); + m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) - module.StopMoveToTarget(new UUID(npc.m_string), World); + { + UUID npcId = new UUID(npc.m_string); + + if (!module.CheckPermissions(npcId, m_host.OwnerID)) + return; + + module.StopMoveToTarget(npcId, World); + } } public void osNpcSay(LSL_Key npc, string message) { CheckThreatLevel(ThreatLevel.High, "osNpcSay"); + m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) { - module.Say(new UUID(npc.m_string), World, message); + UUID npcId = new UUID(npc.m_string); + + if (!module.CheckPermissions(npcId, m_host.OwnerID)) + return; + + module.Say(npcId, World, message); } } public void osNpcSit(LSL_Key npc, LSL_Key target, int options) { CheckThreatLevel(ThreatLevel.High, "osNpcSit"); + m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) { - module.Sit(new UUID(npc.m_string), new UUID(target.m_string), World); + UUID npcId = new UUID(npc.m_string); + + if (!module.CheckPermissions(npcId, m_host.OwnerID)) + return; + + module.Sit(npcId, new UUID(target.m_string), World); } } public void osNpcStand(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcStand"); + m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) { - module.Stand(new UUID(npc.m_string), World); + UUID npcId = new UUID(npc.m_string); + + if (!module.CheckPermissions(npcId, m_host.OwnerID)) + return; + + module.Stand(npcId, World); } } public void osNpcRemove(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); + m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) { - module.DeleteNPC(new UUID(npc.m_string), World); + UUID npcId = new UUID(npc.m_string); + + if (!module.CheckPermissions(npcId, m_host.OwnerID)) + return; + + module.DeleteNPC(npcId, World); + } + } + + public void osNpcPlayAnimation(LSL_Key npc, string animation) + { + CheckThreatLevel(ThreatLevel.High, "osNpcPlayAnimation"); + m_host.AddScriptLPS(1); + + INPCModule module = World.RequestModuleInterface(); + if (module != null) + { + UUID npcID = new UUID(npc.m_string); + + if (module.CheckPermissions(npcID, m_host.OwnerID)) + AvatarPlayAnimation(npcID.ToString(), animation); + } + } + + public void osNpcStopAnimation(LSL_Key npc, string animation) + { + CheckThreatLevel(ThreatLevel.High, "osNpcStopAnimation"); + m_host.AddScriptLPS(1); + + INPCModule module = World.RequestModuleInterface(); + if (module != null) + { + UUID npcID = new UUID(npc.m_string); + + if (module.CheckPermissions(npcID, m_host.OwnerID)) + AvatarPlayAnimation(npcID.ToString(), animation); } } @@ -2320,6 +2607,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osOwnerSaveAppearance(string notecard) { CheckThreatLevel(ThreatLevel.High, "osOwnerSaveAppearance"); + m_host.AddScriptLPS(1); return SaveAppearanceToNotecard(m_host.OwnerID, notecard); } @@ -2327,6 +2615,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osAgentSaveAppearance(LSL_Key avatarId, string notecard) { CheckThreatLevel(ThreatLevel.VeryHigh, "osAgentSaveAppearance"); + m_host.AddScriptLPS(1); return SaveAppearanceToNotecard(avatarId, notecard); } @@ -2377,6 +2666,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osGetMapTexture() { CheckThreatLevel(ThreatLevel.None, "osGetMapTexture"); + m_host.AddScriptLPS(1); + return m_ScriptEngine.World.RegionInfo.RegionSettings.TerrainImageID.ToString(); } @@ -2388,6 +2679,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osGetRegionMapTexture(string regionName) { CheckThreatLevel(ThreatLevel.High, "osGetRegionMapTexture"); + m_host.AddScriptLPS(1); + Scene scene = m_ScriptEngine.World; UUID key = UUID.Zero; GridRegion region; @@ -2453,6 +2746,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osKickAvatar(string FirstName,string SurName,string alert) { CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); + m_host.AddScriptLPS(1); + if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) { World.ForEachRootScenePresence(delegate(ScenePresence sp) @@ -2587,6 +2882,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List osGetAvatarList() { CheckThreatLevel(ThreatLevel.None, "osGetAvatarList"); + m_host.AddScriptLPS(1); LSL_List result = new LSL_List(); World.ForEachRootScenePresence(delegate (ScenePresence avatar) @@ -2611,6 +2907,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osUnixTimeToTimestamp(long time) { CheckThreatLevel(ThreatLevel.VeryLow, "osUnixTimeToTimestamp"); + m_host.AddScriptLPS(1); + long baseTicks = 621355968000000000; long tickResolution = 10000000; long epochTicks = (time * tickResolution) + baseTicks; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 3eeb23d63e..3e0e452ce0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -26,10 +26,13 @@ */ using System; +using System.Reflection; using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; +using log4net; +using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; @@ -51,6 +54,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins private const int AGENT = 1; private const int AGENT_BY_USERNAME = 0x10; + private const int NPC = 0x20; private const int ACTIVE = 2; private const int PASSIVE = 4; private const int SCRIPTED = 8; @@ -203,7 +207,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins List sensedEntities = new List(); // Is the sensor type is AGENT and not SCRIPTED then include agents - if ((ts.type & (AGENT | AGENT_BY_USERNAME)) != 0 && (ts.type & SCRIPTED) == 0) + if ((ts.type & (AGENT | AGENT_BY_USERNAME | NPC)) != 0 && (ts.type & SCRIPTED) == 0) { sensedEntities.AddRange(doAgentSensor(ts)); } @@ -413,6 +417,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins private List doAgentSensor(SenseRepeatClass ts) { + INPCModule npcModule = m_CmdManager.m_ScriptEngine.World.RequestModuleInterface(); + List sensedEntities = new List(); // If nobody about quit fast @@ -441,6 +447,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins Action senseEntity = new Action(delegate(ScenePresence presence) { + if ((ts.type & NPC) == 0 + && presence.PresenceType == PresenceType.Npc + && !npcModule.GetNPC(presence.UUID, presence.Scene).SenseAsAgent) + return; + + if ((ts.type & AGENT) == 0 + && (presence.PresenceType == PresenceType.User + || npcModule.GetNPC(presence.UUID, presence.Scene).SenseAsAgent)) + return; + if (presence.IsDeleted || presence.IsChildAgent || presence.GodLevel > 0.0) return; @@ -452,6 +468,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins toRegionPos = presence.AbsolutePosition; dis = Math.Abs(Util.GetDistanceTo(toRegionPos, fromRegionPos)); + // Disabled for now since all osNpc* methods check for appropriate ownership permission. + // Perhaps could be re-enabled as an NPC setting at some point since being able to make NPCs not + // sensed might be useful. +// if (presence.PresenceType == PresenceType.Npc && npcModule != null) +// { +// UUID npcOwner = npcModule.GetOwner(presence.UUID); +// if (npcOwner != UUID.Zero && npcOwner != SensePoint.OwnerID) +// return; +// } + // are they in range if (dis <= ts.range) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 62e2854998..b66537f544 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -161,6 +161,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param); LSL_Integer llGetParcelFlags(LSL_Vector pos); LSL_Integer llGetParcelMaxPrims(LSL_Vector pos, int sim_wide); + LSL_String llGetParcelMusicURL(); LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide); LSL_List llGetParcelPrimOwners(LSL_Vector pos); LSL_Integer llGetPermissions(); @@ -241,6 +242,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void llLoopSound(string sound, double volume); void llLoopSoundMaster(string sound, double volume); void llLoopSoundSlave(string sound, double volume); + LSL_Integer llManageEstateAccess(int action, string avatar); void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset); void llMakeFire(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset); void llMakeFountain(int particles, double scale, double vel, double lifetime, double arc, int bounce, string texture, LSL_Vector offset, double bounce_offset); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 00ca0702d6..dbc1dfc804 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -42,6 +42,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { public enum ThreatLevel { + NoAccess = -1, None = 0, Nuisance = 1, VeryLow = 2, @@ -159,6 +160,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces string osGetGridNick(); string osGetGridName(); string osGetGridLoginURI(); + string osGetGridHomeURI(); + string osGetGridCustom(string key); LSL_String osFormatString(string str, LSL_List strings); LSL_List osMatchString(string src, string pattern, int start); @@ -170,22 +173,42 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_List osGetLinkPrimitiveParams(int linknumber, LSL_List rules); - key osNpcCreate(string user, string name, vector position, string notecard); - LSL_Key osNpcSaveAppearance(key npc, string notecard); - void osNpcLoadAppearance(key npc, string notecard); - vector osNpcGetPos(key npc); - void osNpcMoveTo(key npc, vector position); - void osNpcMoveToTarget(key npc, vector target, int options); - rotation osNpcGetRot(key npc); - void osNpcSetRot(LSL_Key npc, rotation rot); - void osNpcStopMoveToTarget(LSL_Key npc); - void osNpcSay(key npc, string message); - void osNpcSit(key npc, key target, int options); - void osNpcStand(LSL_Key npc); - void osNpcRemove(key npc); + /// + /// Check if the given key is an npc + /// + /// + /// TRUE if the key belongs to an npc in the scene. FALSE otherwise. + LSL_Integer osIsNpc(LSL_Key npc); - LSL_Key osOwnerSaveAppearance(string notecard); - LSL_Key osAgentSaveAppearance(key agentId, string notecard); + key osNpcCreate(string user, string name, vector position, string notecard); + key osNpcCreate(string user, string name, vector position, string notecard, int options); + LSL_Key osNpcSaveAppearance(key npc, string notecard); + void osNpcLoadAppearance(key npc, string notecard); + vector osNpcGetPos(key npc); + void osNpcMoveTo(key npc, vector position); + void osNpcMoveToTarget(key npc, vector target, int options); + + /// + /// Get the owner of the NPC + /// + /// + /// + /// The owner of the NPC for an owned NPC. The NPC's agent id for an unowned NPC. UUID.Zero if the key is not an npc. + /// + LSL_Key osNpcGetOwner(key npc); + + rotation osNpcGetRot(key npc); + void osNpcSetRot(LSL_Key npc, rotation rot); + void osNpcStopMoveToTarget(LSL_Key npc); + void osNpcSay(key npc, string message); + void osNpcSit(key npc, key target, int options); + void osNpcStand(LSL_Key npc); + void osNpcRemove(key npc); + void osNpcPlayAnimation(LSL_Key npc, string animation); + void osNpcStopAnimation(LSL_Key npc, string animation); + + LSL_Key osOwnerSaveAppearance(string notecard); + LSL_Key osAgentSaveAppearance(key agentId, string notecard); key osGetMapTexture(); key osGetRegionMapTexture(string regionName); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index fd08373574..a69b4cb487 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -52,6 +52,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int AGENT = 1; public const int AGENT_BY_LEGACY_NAME = 1; public const int AGENT_BY_USERNAME = 0x10; + public const int NPC = 0x20; public const int ACTIVE = 2; public const int PASSIVE = 4; public const int SCRIPTED = 8; @@ -431,6 +432,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int REGION_FLAG_ALLOW_DIRECT_TELEPORT = 0x100000; // region allows direct teleports public const int REGION_FLAG_RESTRICT_PUSHOBJECT = 0x400000; // region restricts llPushObject + //llManageEstateAccess + public const int ESTATE_ACCESS_ALLOWED_AGENT_ADD = 0; + public const int ESTATE_ACCESS_ALLOWED_AGENT_REMOVE = 1; + public const int ESTATE_ACCESS_ALLOWED_GROUP_ADD = 2; + public const int ESTATE_ACCESS_ALLOWED_GROUP_REMOVE = 3; + public const int ESTATE_ACCESS_BANNED_AGENT_ADD = 4; + public const int ESTATE_ACCESS_BANNED_AGENT_REMOVE = 5; + public static readonly LSLInteger PAY_HIDE = new LSLInteger(-1); public static readonly LSLInteger PAY_DEFAULT = new LSLInteger(-2); @@ -605,6 +614,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int OS_NPC_SIT_NOW = 0; + public const int OS_NPC_CREATOR_OWNED = 0x1; + public const int OS_NPC_NOT_OWNED = 0x2; + public const int OS_NPC_SENSE_AS_AGENT = 0x4; + public const string URL_REQUEST_GRANTED = "URL_REQUEST_GRANTED"; public const string URL_REQUEST_DENIED = "URL_REQUEST_DENIED"; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index 508f33b13f..840d3a4ec6 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -649,6 +649,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llGetParcelMaxPrims(pos, sim_wide); } + public LSL_String llGetParcelMusicURL() + { + return m_LSL_Functions.llGetParcelMusicURL(); + } + public LSL_Integer llGetParcelPrimCount(LSL_Vector pos, int category, int sim_wide) { return m_LSL_Functions.llGetParcelPrimCount(pos, category, sim_wide); @@ -1049,6 +1054,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_LSL_Functions.llLoopSoundSlave(sound, volume); } + public LSL_Integer llManageEstateAccess(int action, string avatar) + { + return m_LSL_Functions.llManageEstateAccess(action, avatar); + } + public void llMakeExplosion(int particles, double scale, double vel, double lifetime, double arc, string texture, LSL_Vector offset) { m_LSL_Functions.llMakeExplosion(particles, scale, vel, lifetime, arc, texture, offset); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 0d7d5ea87f..cc8d417d64 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -452,6 +452,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osGetGridLoginURI(); } + public string osGetGridHomeURI() + { + return m_OSSL_Functions.osGetGridHomeURI(); + } + + public string osGetGridCustom(string key) + { + return m_OSSL_Functions.osGetGridCustom(key); + } + public LSL_String osFormatString(string str, LSL_List strings) { return m_OSSL_Functions.osFormatString(str, strings); @@ -483,11 +493,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osGetLinkPrimitiveParams(linknumber, rules); } + public LSL_Integer osIsNpc(LSL_Key npc) + { + return m_OSSL_Functions.osIsNpc(npc); + } + public key osNpcCreate(string user, string name, vector position, key cloneFrom) { return m_OSSL_Functions.osNpcCreate(user, name, position, cloneFrom); } + public key osNpcCreate(string user, string name, vector position, key cloneFrom, int options) + { + return m_OSSL_Functions.osNpcCreate(user, name, position, cloneFrom, options); + } + public key osNpcSaveAppearance(key npc, string notecard) { return m_OSSL_Functions.osNpcSaveAppearance(npc, notecard); @@ -498,6 +518,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osNpcLoadAppearance(npc, notecard); } + public LSL_Key osNpcGetOwner(LSL_Key npc) + { + return m_OSSL_Functions.osNpcGetOwner(npc); + } + public vector osNpcGetPos(LSL_Key npc) { return m_OSSL_Functions.osNpcGetPos(npc); @@ -548,6 +573,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osNpcRemove(npc); } + public void osNpcPlayAnimation(LSL_Key npc, string animation) + { + m_OSSL_Functions.osNpcPlayAnimation(npc, animation); + } + + public void osNpcStopAnimation(LSL_Key npc, string animation) + { + m_OSSL_Functions.osNpcStopAnimation(npc, animation); + } + public LSL_Key osOwnerSaveAppearance(string notecard) { return m_OSSL_Functions.osOwnerSaveAppearance(notecard); @@ -818,4 +853,4 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osUnixTimeToTimestamp(time); } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs index f9d6eee949..9b93135fd4 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Instance/ScriptInstance.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance { public class ScriptInstance : MarshalByRefObject, IScriptInstance { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private IScriptEngine m_Engine; private IScriptWorkItem m_CurrentResult = null; @@ -109,7 +109,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance private Dictionary m_Apis = new Dictionary(); // Script state - private string m_State="default"; + private string m_State = "default"; public Object[] PluginData = new Object[0]; @@ -127,6 +127,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance m_minEventDelay = value; else m_minEventDelay = 0.0; + m_eventDelayTicks = (long)(m_minEventDelay * 10000000L); m_nextEventTimeTicks = DateTime.Now.Ticks; } @@ -296,9 +297,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance //RemotingServices.GetLifetimeService(m_Script as ScriptBaseClass); // lease.Register(this); } - catch (Exception) + catch (Exception e) { - // m_log.ErrorFormat("[Script] Error loading assembly {0}\n"+e.ToString(), assembly); + m_log.ErrorFormat( + "[SCRIPT INSTANCE]: Error loading assembly {0}. Exception {1}{2}", + assembly, e.Message, e.StackTrace); } try @@ -313,9 +316,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance part.SetScriptEvents(m_ItemID, (int)m_Script.GetStateEventFlags(State)); } - catch (Exception) + catch (Exception e) { - // m_log.Error("[Script] Error loading script instance\n"+e.ToString()); + m_log.ErrorFormat( + "[SCRIPT INSTANCE]: Error loading script instance from assembly {0}. Exception {1}{2}", + assembly, e.Message, e.StackTrace); + return; } @@ -377,12 +383,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Instance } else { - // m_log.Error("[Script] Unable to load script state: Memory limit exceeded"); + m_log.ErrorFormat( + "[SCRIPT INSTANCE]: Unable to load script state from assembly {0}: Memory limit exceeded", + assembly); } } - catch (Exception) + catch (Exception e) { - // m_log.ErrorFormat("[Script] Unable to load script state from xml: {0}\n"+e.ToString(), xml); + m_log.ErrorFormat( + "[SCRIPT INSTANCE]: Unable to load script state from assembly {0}. XML is {1}. Exception {2}{3}", + assembly, xml, e.Message, e.StackTrace); } } // else diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs index 0cbad418bd..3baa72372c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs @@ -75,32 +75,49 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests [Test] public void TestllAngleBetween() { - CheckllAngleBetween(new Vector3(1, 0, 0), 0); - CheckllAngleBetween(new Vector3(1, 0, 0), 90); - CheckllAngleBetween(new Vector3(1, 0, 0), 180); + CheckllAngleBetween(new Vector3(1, 0, 0), 0, 1, 1); + CheckllAngleBetween(new Vector3(1, 0, 0), 90, 1, 1); + CheckllAngleBetween(new Vector3(1, 0, 0), 180, 1, 1); - CheckllAngleBetween(new Vector3(0, 1, 0), 0); - CheckllAngleBetween(new Vector3(0, 1, 0), 90); - CheckllAngleBetween(new Vector3(0, 1, 0), 180); + CheckllAngleBetween(new Vector3(0, 1, 0), 0, 1, 1); + CheckllAngleBetween(new Vector3(0, 1, 0), 90, 1, 1); + CheckllAngleBetween(new Vector3(0, 1, 0), 180, 1, 1); - CheckllAngleBetween(new Vector3(0, 0, 1), 0); - CheckllAngleBetween(new Vector3(0, 0, 1), 90); - CheckllAngleBetween(new Vector3(0, 0, 1), 180); + CheckllAngleBetween(new Vector3(0, 0, 1), 0, 1, 1); + CheckllAngleBetween(new Vector3(0, 0, 1), 90, 1, 1); + CheckllAngleBetween(new Vector3(0, 0, 1), 180, 1, 1); - CheckllAngleBetween(new Vector3(1, 1, 1), 0); - CheckllAngleBetween(new Vector3(1, 1, 1), 90); - CheckllAngleBetween(new Vector3(1, 1, 1), 180); + CheckllAngleBetween(new Vector3(1, 1, 1), 0, 1, 1); + CheckllAngleBetween(new Vector3(1, 1, 1), 90, 1, 1); + CheckllAngleBetween(new Vector3(1, 1, 1), 180, 1, 1); + + CheckllAngleBetween(new Vector3(1, 0, 0), 0, 1.6f, 1.8f); + CheckllAngleBetween(new Vector3(1, 0, 0), 90, 0.3f, 3.9f); + CheckllAngleBetween(new Vector3(1, 0, 0), 180, 8.8f, 7.4f); + + CheckllAngleBetween(new Vector3(0, 1, 0), 0, 9.8f, -9.4f); + CheckllAngleBetween(new Vector3(0, 1, 0), 90, 8.4f, -8.2f); + CheckllAngleBetween(new Vector3(0, 1, 0), 180, 0.4f, -5.8f); + + CheckllAngleBetween(new Vector3(0, 0, 1), 0, -6.8f, 3.4f); + CheckllAngleBetween(new Vector3(0, 0, 1), 90, -3.6f, 5.6f); + CheckllAngleBetween(new Vector3(0, 0, 1), 180, -3.8f, 1.1f); + + CheckllAngleBetween(new Vector3(1, 1, 1), 0, -7.7f, -2.0f); + CheckllAngleBetween(new Vector3(1, 1, 1), 90, -3.0f, -9.1f); + CheckllAngleBetween(new Vector3(1, 1, 1), 180, -7.9f, -8.0f); } - private void CheckllAngleBetween(Vector3 axis,float originalAngle) + private void CheckllAngleBetween(Vector3 axis,float originalAngle, float denorm1, float denorm2) { Quaternion rotation1 = Quaternion.CreateFromAxisAngle(axis, 0); Quaternion rotation2 = Quaternion.CreateFromAxisAngle(axis, ToRadians(originalAngle)); + rotation1 *= denorm1; + rotation2 *= denorm2; double deducedAngle = FromLslFloat(m_lslApi.llAngleBetween(ToLslQuaternion(rotation2), ToLslQuaternion(rotation1))); - Assert.Greater(deducedAngle, ToRadians(originalAngle) - ANGLE_ACCURACY_IN_RADIANS); - Assert.Less(deducedAngle, ToRadians(originalAngle) + ANGLE_ACCURACY_IN_RADIANS); + Assert.That(deducedAngle, Is.EqualTo(ToRadians(originalAngle)).Within(ANGLE_ACCURACY_IN_RADIANS), "TestllAngleBetween check fail"); } #region Conversions to and from LSL_Types @@ -142,30 +159,97 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests public void TestllRot2Euler() { // 180, 90 and zero degree rotations. - CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 0.0f, 0.0f, 0.0f), new LSL_Types.Vector3(Math.PI, 0.0f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 1.0f, 0.0f, 0.0f), new LSL_Types.Vector3(Math.PI, 0.0f, Math.PI)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 1.0f, 0.0f), new LSL_Types.Vector3(0.0f, 0.0f, Math.PI)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.0f, 1.0f), new LSL_Types.Vector3(0.0f, 0.0f, 0.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, 0.5f, 0.5f), new LSL_Types.Vector3(0, -Math.PI / 2.0f, Math.PI / 2.0f)); - CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, 0.0f, 0.0f, -0.707107f), new LSL_Types.Vector3(Math.PI / 2.0f, 0.0f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.0f, 1.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.707107f, 0.707107f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 1.0f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, 0.0f, 0.707107f, -0.707107f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, 0.0f, 0.0f, 0.707107f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.5f, -0.5f, 0.5f, 0.5f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.707107f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, 0.5f, -0.5f)); + CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 0.0f, 0.0f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, -0.707107f, 0.0f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -1.0f, 0.0f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, -0.707107f, 0.0f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.707107f, 0.0f, 0.0f, -0.707107f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.5f, -0.5f, -0.5f, -0.5f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, -0.707107f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, -0.5f, 0.5f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.0f, 0.707107f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, 0.5f, 0.5f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, 0.0f, 0.707107f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, 0.5f, 0.5f, -0.5f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.0f, -0.707107f, 0.0f, -0.707107f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, -0.5f, -0.5f, -0.5f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.707107f, 0.0f, -0.707107f, 0.0f)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.5f, 0.5f, -0.5f, 0.5f)); + // A couple of messy rotations. - CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 5.651f, -3.1f, 67.023f), new LSL_Types.Vector3(0.037818f, 0.166447f, -0.095595f)); - CheckllRot2Euler(new LSL_Types.Quaternion(0.719188f, -0.408934f, -0.363998f, -0.427841f), new LSL_Types.Vector3(-1.954769f, -0.174533f, 1.151917f)); + CheckllRot2Euler(new LSL_Types.Quaternion(1.0f, 5.651f, -3.1f, 67.023f)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.719188f, -0.408934f, -0.363998f, -0.427841f)); + + // Some deliberately malicious rotations (intended on provoking singularity errors) + // The "f" suffexes are deliberately omitted. + CheckllRot2Euler(new LSL_Types.Quaternion(0.50001f, 0.50001f, 0.50001f, 0.50001f)); + // More malice. The "f" suffixes are deliberately omitted. + CheckllRot2Euler(new LSL_Types.Quaternion(-0.701055, 0.092296, 0.701055, -0.092296)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.183005, -0.683010, 0.183005, 0.683010)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.430460, -0.560982, 0.430460, 0.560982)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.701066, 0.092301, -0.701066, 0.092301)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.183013, -0.683010, 0.183013, 0.683010)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.183005, -0.683014, -0.183005, -0.683014)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.353556, 0.612375, 0.353556, -0.612375)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.353554, -0.612385, -0.353554, 0.612385)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.560989, 0.430450, 0.560989, -0.430450)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.183013, 0.683009, -0.183013, 0.683009)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.430457, -0.560985, -0.430457, 0.560985)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.353552, 0.612360, -0.353552, -0.612360)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.499991, 0.500003, 0.499991, -0.500003)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.353555, -0.612385, -0.353555, -0.612385)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.701066, -0.092301, -0.701066, 0.092301)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.499991, 0.500007, 0.499991, -0.500007)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.683002, 0.183016, -0.683002, 0.183016)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.430458, 0.560982, 0.430458, 0.560982)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.499991, -0.500003, -0.499991, 0.500003)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.183009, 0.683011, -0.183009, 0.683011)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.560975, -0.430457, 0.560975, -0.430457)); + CheckllRot2Euler(new LSL_Types.Quaternion(0.701055, 0.092300, 0.701055, 0.092300)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.560990, 0.430459, -0.560990, 0.430459)); + CheckllRot2Euler(new LSL_Types.Quaternion(-0.092302, -0.701059, -0.092302, -0.701059)); } - private void CheckllRot2Euler(LSL_Types.Quaternion rot, LSL_Types.Vector3 eulerCheck) + /// + /// Check an llRot2Euler conversion. + /// + /// + /// Testing Rot2Euler this way instead of comparing against expected angles because + /// 1. There are several ways to get to the original Quaternion. For example a rotation + /// of PI and -PI will give the same result. But PI and -PI aren't equal. + /// 2. This method checks to see if the calculated angles from a quaternion can be used + /// to create a new quaternion to produce the same rotation. + /// However, can't compare the newly calculated quaternion against the original because + /// once again, there are multiple quaternions that give the same result. For instance + /// == <-X, -Y, -Z, -S>. Additionally, the magnitude of S can be changed + /// and will still result in the same rotation if the values for X, Y, Z are also changed + /// to compensate. + /// However, if two quaternions represent the same rotation, then multiplying the first + /// quaternion by the conjugate of the second, will give a third quaternion representing + /// a zero rotation. This can be tested for by looking at the X, Y, Z values which should + /// be zero. + /// + /// + private void CheckllRot2Euler(LSL_Types.Quaternion rot) { // Call LSL function to convert quaternion rotaion to euler radians. LSL_Types.Vector3 eulerCalc = m_lslApi.llRot2Euler(rot); - // Check upper and lower bounds of x, y and z. - // This type of check is performed as opposed to comparing for equal numbers, in order to allow slight - // differences in accuracy. - Assert.Greater(eulerCalc.x, eulerCheck.x - ANGLE_ACCURACY_IN_RADIANS, "TestllRot2Euler X lower bounds check fail"); - Assert.Less(eulerCalc.x, eulerCheck.x + ANGLE_ACCURACY_IN_RADIANS, "TestllRot2Euler X upper bounds check fail"); - Assert.Greater(eulerCalc.y, eulerCheck.y - ANGLE_ACCURACY_IN_RADIANS, "TestllRot2Euler Y lower bounds check fail"); - Assert.Less(eulerCalc.y, eulerCheck.y + ANGLE_ACCURACY_IN_RADIANS, "TestllRot2Euler Y upper bounds check fail"); - Assert.Greater(eulerCalc.z, eulerCheck.z - ANGLE_ACCURACY_IN_RADIANS, "TestllRot2Euler Z lower bounds check fail"); - Assert.Less(eulerCalc.z, eulerCheck.z + ANGLE_ACCURACY_IN_RADIANS, "TestllRot2Euler Z upper bounds check fail"); + // Now use the euler radians to recalculate a new quaternion rotation + LSL_Types.Quaternion newRot = m_lslApi.llEuler2Rot(eulerCalc); + // Multiple original quaternion by conjugate of quaternion calculated with angles. + LSL_Types.Quaternion check = rot * new LSL_Types.Quaternion(-newRot.x, -newRot.y, -newRot.z, newRot.s); + + Assert.AreEqual(0.0, check.x, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler X bounds check fail"); + Assert.AreEqual(0.0, check.y, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler Y bounds check fail"); + Assert.AreEqual(0.0, check.z, VECTOR_COMPONENT_ACCURACY, "TestllRot2Euler Z bounds check fail"); } [Test] diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs new file mode 100644 index 0000000000..9d9fc514a3 --- /dev/null +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -0,0 +1,170 @@ +/* + * 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 System.Text; +using log4net; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenMetaverse.Assets; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Region.CoreModules.Avatar.AvatarFactory; +using OpenSim.Region.OptionalModules.World.NPC; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.ScriptEngine.Shared; +using OpenSim.Region.ScriptEngine.Shared.Api; +using OpenSim.Region.ScriptEngine.Shared.ScriptBase; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Region.ScriptEngine.Shared.Tests +{ + /// + /// Tests for OSSL NPC API + /// + [TestFixture] + public class OSSL_NpcApiAppearanceTest + { + protected Scene m_scene; + protected XEngine.XEngine m_engine; + + [SetUp] + public void SetUp() + { + IConfigSource initConfigSource = new IniConfigSource(); + IConfig config = initConfigSource.AddConfig("XEngine"); + config.Set("Enabled", "true"); + config.Set("AllowOSFunctions", "true"); + config.Set("OSFunctionThreatLevel", "Severe"); + config = initConfigSource.AddConfig("NPC"); + config.Set("Enabled", "true"); + + m_scene = SceneHelpers.SetupScene(); + SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); + + m_engine = new XEngine.XEngine(); + m_engine.Initialise(initConfigSource); + m_engine.AddRegion(m_scene); + } + + /// + /// Test removal of an owned NPC. + /// + [Test] + public void TestOsNpcRemoveOwned() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + UUID otherUserId = TestHelpers.ParseTail(0x2); + float newHeight = 1.9f; + + SceneHelpers.AddScenePresence(m_scene, otherUserId); + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + SceneObjectGroup otherSo = SceneHelpers.CreateSceneObject(1, otherUserId); + SceneObjectPart otherPart = otherSo.RootPart; + m_scene.AddSceneObject(otherSo); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); + + OSSL_Api otherOsslApi = new OSSL_Api(); + otherOsslApi.Initialize(m_engine, otherPart, otherPart.LocalId, otherPart.UUID); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + string npcRaw + = osslApi.osNpcCreate( + "Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName, ScriptBaseClass.OS_NPC_CREATOR_OWNED); + + otherOsslApi.osNpcRemove(npcRaw); + + // Should still be around + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + + osslApi.osNpcRemove(npcRaw); + + npc = m_scene.GetScenePresence(npcId); + + // Now the owner deleted it and it's gone + Assert.That(npc, Is.Null); + } + + /// + /// Test removal of an unowned NPC. + /// + [Test] + public void TestOsNpcRemoveUnowned() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + // Store an avatar with a different height from default in a notecard. + UUID userId = TestHelpers.ParseTail(0x1); + float newHeight = 1.9f; + + ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); + sp.Appearance.AvatarHeight = newHeight; + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, part.LocalId, part.UUID); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + string npcRaw + = osslApi.osNpcCreate( + "Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName, ScriptBaseClass.OS_NPC_NOT_OWNED); + + osslApi.osNpcRemove(npcRaw); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Null); + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 12e1a78871..f11987eede 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -26,14 +26,15 @@ */ using System; -using System.IO; -using System.Threading; using System.Collections; using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Reflection; using System.Security; using System.Security.Policy; -using System.Reflection; -using System.Globalization; +using System.Text; +using System.Threading; using System.Xml; using OpenMetaverse; using OpenMetaverse.StructuredData; @@ -273,11 +274,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine } MainConsole.Instance.Commands.AddCommand( - "scripts", false, "scripts show", "scripts show", "Show script information", - "Show information on all scripts known to the script engine", HandleShowScripts); + "scripts", false, "xengine status", "xengine status", "Show status information", + "Show status information on the script engine.", + HandleShowStatus); MainConsole.Instance.Commands.AddCommand( - "scripts", false, "show scripts", "show scripts", "Show script information", + "scripts", false, "scripts show", "scripts show []", "Show script information", + "Show information on all scripts known to the script engine." + + "If a is given then only information on that script will be shown.", + HandleShowScripts); + + MainConsole.Instance.Commands.AddCommand( + "scripts", false, "show scripts", "show scripts []", "Show script information", "Synonym for scripts show command", HandleShowScripts); MainConsole.Instance.Commands.AddCommand( @@ -308,43 +316,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine (module, cmdparams) => HandleScriptsAction(cmdparams, HandleStartScript)); } - public void HandleShowScripts(string module, string[] cmdparams) - { - lock (m_Scripts) - { - MainConsole.Instance.OutputFormat( - "Showing {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); - - foreach (IScriptInstance instance in m_Scripts.Values) - { - SceneObjectPart sop = m_Scene.GetSceneObjectPart(instance.ObjectID); - string status; - - if (instance.ShuttingDown) - { - status = "shutting down"; - } - else if (instance.Suspended) - { - status = "suspended"; - } - else if (!instance.Running) - { - status = "stopped"; - } - else - { - status = "running"; - } - - MainConsole.Instance.OutputFormat( - "{0}.{1}, item UUID {2}, prim UUID {3} @ {4} ({5})", - instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, - sop.AbsolutePosition, status); - } - } - } - /// /// Parse the raw item id into a script instance from the command params if it's present. /// @@ -353,6 +324,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine /// true if we're okay to proceed, false if not. private void HandleScriptsAction(string[] cmdparams, Action action) { + if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) + return; + lock (m_Scripts) { string rawItemId; @@ -394,6 +368,83 @@ namespace OpenSim.Region.ScriptEngine.XEngine } } + private void HandleShowStatus(string module, string[] cmdparams) + { + if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) + return; + + StringBuilder sb = new StringBuilder(); + sb.AppendFormat("Status of XEngine instance for {0}\n", m_Scene.RegionInfo.RegionName); + + lock (m_Scripts) + sb.AppendFormat("Scripts loaded : {0}\n", m_Scripts.Count); + + sb.AppendFormat("Unique scripts : {0}\n", m_uniqueScripts.Count); + sb.AppendFormat("Scripts waiting for load : {0}\n", m_CompileQueue.Count); + sb.AppendFormat("Allocated threads : {0}\n", m_ThreadPool.ActiveThreads); + sb.AppendFormat("In use threads : {0}\n", m_ThreadPool.InUseThreads); + sb.AppendFormat("Work items waiting : {0}\n", m_ThreadPool.WaitingCallbacks); +// sb.AppendFormat("Assemblies loaded : {0}\n", m_Assemblies.Count); + + MainConsole.Instance.OutputFormat(sb.ToString()); + } + + public void HandleShowScripts(string module, string[] cmdparams) + { + if (!(MainConsole.Instance.ConsoleScene == null || MainConsole.Instance.ConsoleScene == m_Scene)) + return; + + if (cmdparams.Length == 2) + { + lock (m_Scripts) + { + MainConsole.Instance.OutputFormat( + "Showing {0} scripts in {1}", m_Scripts.Count, m_Scene.RegionInfo.RegionName); + } + } + + HandleScriptsAction(cmdparams, HandleShowScript); + } + + private void HandleShowScript(IScriptInstance instance) + { + SceneObjectPart sop = m_Scene.GetSceneObjectPart(instance.ObjectID); + string status; + + if (instance.ShuttingDown) + { + status = "shutting down"; + } + else if (instance.Suspended) + { + status = "suspended"; + } + else if (!instance.Running) + { + status = "stopped"; + } + else + { + status = "running"; + } + + StringBuilder sb = new StringBuilder(); + Queue eq = instance.EventQueue; + + sb.AppendFormat("Script name : {0}\n", instance.ScriptName); + sb.AppendFormat("Status : {0}\n", status); + + lock (eq) + sb.AppendFormat("Queued events : {0}\n", eq.Count); + + sb.AppendFormat("Item UUID : {0}\n", instance.ItemID); + sb.AppendFormat("Containing part name: {0}\n", instance.PrimName); + sb.AppendFormat("Containing part UUID: {0}\n", instance.ObjectID); + sb.AppendFormat("Position : {0}\n", sop.AbsolutePosition); + + MainConsole.Instance.OutputFormat(sb.ToString()); + } + private void HandleSuspendScript(IScriptInstance instance) { if (!instance.Suspended) diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index fca9fd0884..24a94180db 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -442,7 +442,7 @@ namespace OpenSim.Region.UserStatistics public string ViewerStatsReport(string request, string path, string param, UUID agentID, Caps caps) { - //m_log.Debug(request); +// m_log.DebugFormat("[WEB STATS MODULE]: Received viewer starts report from {0}", agentID); UpdateUserStats(ParseViewerStats(request,agentID), dbConn); @@ -655,13 +655,13 @@ namespace OpenSim.Region.UserStatistics updatecmd.Parameters.Add(new SqliteParameter(":session_key", uid.session_data.session_id.ToString())); updatecmd.Parameters.Add(new SqliteParameter(":agent_key", uid.session_data.agent_id.ToString())); updatecmd.Parameters.Add(new SqliteParameter(":region_key", uid.session_data.region_id.ToString())); - m_log.Debug("UPDATE"); +// m_log.Debug("UPDATE"); int result = updatecmd.ExecuteNonQuery(); if (result == 0) { - m_log.Debug("INSERT"); +// m_log.Debug("INSERT"); updatecmd.CommandText = SQL_STATS_TABLE_INSERT; try { diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index aeba35ff1c..a6f4e4769e 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -126,11 +126,10 @@ namespace OpenSim.Server.Base m_Config = new IniConfigSource(iniFile); } } - catch (Exception) + catch (Exception e) { - System.Console.WriteLine("Error reading from config source {0}", - iniFile); - Thread.CurrentThread.Abort(); + System.Console.WriteLine("Error reading from config source. {0}", e.Message); + Environment.Exit(1); } // Merge the configuration from the command line into the diff --git a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs index df571fa925..9b80245267 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerConnector.cs @@ -26,7 +26,11 @@ */ using System; +using System.IO; using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; using OpenSim.Server.Base; using OpenSim.Services.Interfaces; using OpenSim.Framework.Servers.HttpServer; @@ -67,6 +71,129 @@ namespace OpenSim.Server.Handlers.Asset server.AddStreamHandler(new AssetServerGetHandler(m_AssetService)); server.AddStreamHandler(new AssetServerPostHandler(m_AssetService)); server.AddStreamHandler(new AssetServerDeleteHandler(m_AssetService, allowDelete)); + + MainConsole.Instance.Commands.AddCommand("kfs", false, + "show asset", + "show asset ", + "Show asset information", + HandleShowAsset); + + MainConsole.Instance.Commands.AddCommand("kfs", false, + "delete asset", + "delete asset ", + "Delete asset from database", + HandleDeleteAsset); + + MainConsole.Instance.Commands.AddCommand("kfs", false, + "dump asset", + "dump asset ", + "Dump asset to a file", + "The filename is the same as the ID given.", + HandleDumpAsset); + } + + void HandleDeleteAsset(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Syntax: delete asset "); + return; + } + + AssetBase asset = m_AssetService.Get(args[2]); + + if (asset == null || asset.Data.Length == 0) + { + MainConsole.Instance.Output("Asset not found"); + return; + } + + m_AssetService.Delete(args[2]); + + //MainConsole.Instance.Output("Asset deleted"); + // TODO: Implement this + + MainConsole.Instance.Output("Asset deletion not supported by database"); + } + + void HandleDumpAsset(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Usage is dump asset "); + return; + } + + UUID assetId; + string rawAssetId = args[2]; + + if (!UUID.TryParse(rawAssetId, out assetId)) + { + MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid ID format", rawAssetId); + return; + } + + AssetBase asset = m_AssetService.Get(assetId.ToString()); + if (asset == null) + { + MainConsole.Instance.OutputFormat("ERROR: No asset found with ID {0}", assetId); + return; + } + + string fileName = rawAssetId; + + using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) + { + using (BinaryWriter bw = new BinaryWriter(fs)) + { + bw.Write(asset.Data); + } + } + + MainConsole.Instance.OutputFormat("Asset dumped to file {0}", fileName); + } + + void HandleShowAsset(string module, string[] args) + { + if (args.Length < 3) + { + MainConsole.Instance.Output("Syntax: show asset "); + return; + } + + AssetBase asset = m_AssetService.Get(args[2]); + + if (asset == null || asset.Data.Length == 0) + { + MainConsole.Instance.Output("Asset not found"); + return; + } + + int i; + + MainConsole.Instance.OutputFormat("Name: {0}", asset.Name); + MainConsole.Instance.OutputFormat("Description: {0}", asset.Description); + MainConsole.Instance.OutputFormat("Type: {0} (type number = {1})", (AssetType)asset.Type, asset.Type); + MainConsole.Instance.OutputFormat("Content-type: {0}", asset.Metadata.ContentType); + MainConsole.Instance.OutputFormat("Size: {0} bytes", asset.Data.Length); + MainConsole.Instance.OutputFormat("Temporary: {0}", asset.Temporary ? "yes" : "no"); + MainConsole.Instance.OutputFormat("Flags: {0}", asset.Metadata.Flags); + + for (i = 0 ; i < 5 ; i++) + { + int off = i * 16; + if (asset.Data.Length <= off) + break; + int len = 16; + if (asset.Data.Length < off + len) + len = asset.Data.Length - off; + + byte[] line = new byte[len]; + Array.Copy(asset.Data, off, line, 0, len); + + string text = BitConverter.ToString(line); + MainConsole.Instance.Output(String.Format("{0:x4}: {1}", off, text)); + } } } -} +} \ No newline at end of file diff --git a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs index 645a77f086..965a54e48e 100644 --- a/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs +++ b/OpenSim/Server/Handlers/Grid/GridInfoHandlers.cs @@ -37,13 +37,14 @@ using Nini.Config; using Nwc.XmlRpc; using OpenSim.Framework; using OpenSim.Framework.Servers.HttpServer; +using OpenMetaverse.StructuredData; namespace OpenSim.Server.Handlers.Grid { public class GridInfoHandlers { private static readonly ILog _log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - + private IConfigSource m_Config; private Hashtable _info = new Hashtable(); /// @@ -59,6 +60,7 @@ namespace OpenSim.Server.Handlers.Grid /// public GridInfoHandlers(IConfigSource configSource) { + m_Config = configSource; loadGridInfo(configSource); } @@ -142,5 +144,53 @@ namespace OpenSim.Server.Handlers.Grid return sb.ToString(); } + + /// + /// Get GridInfo in json format: Used bu the OSSL osGetGrid* + /// Adding the SRV_HomeIRI to the kvp returned for use in scripts + /// + /// + /// json string + /// + /// + /// Request. + /// + /// + /// /json_grid_info + /// + /// + /// Parameter. + /// + /// + /// Http request. + /// + /// + /// Http response. + /// + public string JsonGetGridInfoMethod(string request, string path, string param, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + string HomeURI = String.Empty; + IConfig cfg = m_Config.Configs["LoginService"]; + + if (null != cfg) + { + HomeURI = cfg.GetString("SRV_HomeURI", HomeURI); + } + + OSDMap map = new OSDMap(); + + foreach (string k in _info.Keys) + { + map[k] = OSD.FromString(_info[k].ToString()); + } + + if (!String.IsNullOrEmpty(HomeURI)) + { + map["home"] = OSD.FromString(HomeURI); + } + + return OSDParser.SerializeJsonString(map).ToString(); + } } } diff --git a/OpenSim/Server/Handlers/Grid/GridInfoServerInConnector.cs b/OpenSim/Server/Handlers/Grid/GridInfoServerInConnector.cs index 8472d34f1c..f9b5915d69 100644 --- a/OpenSim/Server/Handlers/Grid/GridInfoServerInConnector.cs +++ b/OpenSim/Server/Handlers/Grid/GridInfoServerInConnector.cs @@ -48,6 +48,8 @@ namespace OpenSim.Server.Handlers.Grid server.AddStreamHandler(new RestStreamHandler("GET", "/get_grid_info", handlers.RestGetGridInfoMethod)); + server.AddStreamHandler(new RestStreamHandler("GET", "/json_grid_info", + handlers.JsonGetGridInfoMethod)); server.AddXmlRPCHandler("get_grid_info", handlers.XmlRpcGridInfoMethod); } diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs index 4c0d52e722..bf212554c7 100644 --- a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs +++ b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs @@ -88,6 +88,8 @@ namespace OpenSim.Server.Handlers.GridUser return SetPosition(request); case "getgriduserinfo": return GetGridUserInfo(request); + case "getgriduserinfos": + return GetGridUserInfos(request); } m_log.DebugFormat("[GRID USER HANDLER]: unknown method request: {0}", method); } @@ -193,6 +195,46 @@ namespace OpenSim.Server.Handlers.GridUser } + byte[] GetGridUserInfos(Dictionary request) + { + + string[] userIDs; + + if (!request.ContainsKey("AgentIDs")) + { + m_log.DebugFormat("[GRID USER HANDLER]: GetGridUserInfos called without required uuids argument"); + return FailureResult(); + } + + if (!(request["AgentIDs"] is List)) + { + m_log.DebugFormat("[GRID USER HANDLER]: GetGridUserInfos input argument was of unexpected type {0}", request["uuids"].GetType().ToString()); + return FailureResult(); + } + + userIDs = ((List)request["AgentIDs"]).ToArray(); + + GridUserInfo[] pinfos = m_GridUserService.GetGridUserInfo(userIDs); + + Dictionary result = new Dictionary(); + if ((pinfos == null) || ((pinfos != null) && (pinfos.Length == 0))) + result["result"] = "null"; + else + { + int i = 0; + foreach (GridUserInfo pinfo in pinfos) + { + Dictionary rinfoDict = pinfo.ToKeyValuePairs(); + result["griduser" + i] = rinfoDict; + i++; + } + } + + string xmlString = ServerUtils.BuildXmlResponse(result); + UTF8Encoding encoding = new UTF8Encoding(); + return encoding.GetBytes(xmlString); + } + private bool UnpackArgs(Dictionary request, out string user, out UUID region, out Vector3 position, out Vector3 lookAt) { user = string.Empty; diff --git a/OpenSim/Services/AssetService/AssetService.cs b/OpenSim/Services/AssetService/AssetService.cs index b3af8e3015..4f4cbf6077 100644 --- a/OpenSim/Services/AssetService/AssetService.cs +++ b/OpenSim/Services/AssetService/AssetService.cs @@ -32,7 +32,6 @@ using System.Reflection; using Nini.Config; using log4net; using OpenSim.Framework; -using OpenSim.Framework.Console; using OpenSim.Data; using OpenSim.Services.Interfaces; using OpenMetaverse; @@ -53,23 +52,6 @@ namespace OpenSim.Services.AssetService { m_RootInstance = this; - MainConsole.Instance.Commands.AddCommand("kfs", false, - "show digest", - "show digest ", - "Show asset digest", HandleShowDigest); - - MainConsole.Instance.Commands.AddCommand("kfs", false, - "delete asset", - "delete asset ", - "Delete asset from database", HandleDeleteAsset); - - MainConsole.Instance.Commands.AddCommand("kfs", false, - "dump asset", - "dump asset ", - "Dump asset to a file", - "The filename is the same as the ID given.", - HandleDumpAsset); - if (m_AssetLoader != null) { IConfig assetConfig = config.Configs["AssetService"]; @@ -218,111 +200,11 @@ namespace OpenSim.Services.AssetService return m_Database.Delete(id); } else + { m_log.DebugFormat("[ASSET SERVICE]: Request to delete asset {0}, but flags are not Maptile", id); + } return false; } - - void HandleDumpAsset(string module, string[] args) - { - if (args.Length < 3) - { - MainConsole.Instance.Output("Usage is dump asset "); - return; - } - - string rawAssetId = args[2]; - UUID assetId; - - if (!UUID.TryParse(rawAssetId, out assetId)) - { - MainConsole.Instance.OutputFormat("ERROR: {0} is not a valid ID format", rawAssetId); - return; - } - - AssetBase asset = m_Database.GetAsset(assetId); - if (asset == null) - { - MainConsole.Instance.OutputFormat("ERROR: No asset found with ID {0}", assetId); - return; - } - - string fileName = rawAssetId; - - using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) - { - using (BinaryWriter bw = new BinaryWriter(fs)) - { - bw.Write(asset.Data); - } - } - - MainConsole.Instance.OutputFormat("Asset dumped to file {0}", fileName); - } - - void HandleShowDigest(string module, string[] args) - { - if (args.Length < 3) - { - MainConsole.Instance.Output("Syntax: show digest "); - return; - } - - AssetBase asset = Get(args[2]); - - if (asset == null || asset.Data.Length == 0) - { - MainConsole.Instance.Output("Asset not found"); - return; - } - - int i; - - MainConsole.Instance.OutputFormat("Name: {0}", asset.Name); - MainConsole.Instance.OutputFormat("Description: {0}", asset.Description); - MainConsole.Instance.OutputFormat("Type: {0} (type number = {1})", (AssetType)asset.Type, asset.Type); - MainConsole.Instance.OutputFormat("Content-type: {0}", asset.Metadata.ContentType); - MainConsole.Instance.OutputFormat("Flags: {0}", asset.Metadata.Flags); - - for (i = 0 ; i < 5 ; i++) - { - int off = i * 16; - if (asset.Data.Length <= off) - break; - int len = 16; - if (asset.Data.Length < off + len) - len = asset.Data.Length - off; - - byte[] line = new byte[len]; - Array.Copy(asset.Data, off, line, 0, len); - - string text = BitConverter.ToString(line); - MainConsole.Instance.Output(String.Format("{0:x4}: {1}", off, text)); - } - } - - void HandleDeleteAsset(string module, string[] args) - { - if (args.Length < 3) - { - MainConsole.Instance.Output("Syntax: delete asset "); - return; - } - - AssetBase asset = Get(args[2]); - - if (asset == null || asset.Data.Length == 0) - { - MainConsole.Instance.Output("Asset not found"); - return; - } - - Delete(args[2]); - - //MainConsole.Instance.Output("Asset deleted"); - // TODO: Implement this - - MainConsole.Instance.Output("Asset deletion not supported by database"); - } } -} +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs index d7b2ff85ed..e4c3eafb77 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServiceConnector.cs @@ -86,11 +86,8 @@ namespace OpenSim.Services.Connectors m_log.Error("[ASSET CONNECTOR]: No Server URI named in section AssetService"); throw new Exception("Asset connector init error"); } - m_ServerURI = serviceURI; - MainConsole.Instance.Commands.AddCommand("asset", false, "dump asset", - "dump asset ", - "dump one cached asset", HandleDumpAsset); + m_ServerURI = serviceURI; } protected void SetCache(IImprovedAssetCache cache) @@ -328,43 +325,5 @@ namespace OpenSim.Services.Connectors } return false; } - - private void HandleDumpAsset(string module, string[] args) - { - if (args.Length != 4) - { - MainConsole.Instance.Output("Syntax: dump asset "); - return; - } - - UUID assetID; - - if (!UUID.TryParse(args[2], out assetID)) - { - MainConsole.Instance.Output("Invalid asset ID"); - return; - } - - if (m_Cache == null) - { - MainConsole.Instance.Output("Instance uses no cache"); - return; - } - - AssetBase asset = m_Cache.Get(assetID.ToString()); - - if (asset == null) - { - MainConsole.Instance.Output("Asset not found in cache"); - return; - } - - string fileName = args[3]; - - FileStream fs = File.Create(fileName); - fs.Write(asset.Data, 0, asset.Data.Length); - - fs.Close(); - } } -} +} \ No newline at end of file diff --git a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs index 738cc06949..aa98b5df49 100644 --- a/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs +++ b/OpenSim/Services/Connectors/GridUser/GridUserServiceConnector.cs @@ -223,5 +223,65 @@ namespace OpenSim.Services.Connectors } + public GridUserInfo[] GetGridUserInfo(string[] userIDs) + { + Dictionary sendData = new Dictionary(); + //sendData["SCOPEID"] = scopeID.ToString(); + sendData["VERSIONMIN"] = ProtocolVersions.ClientProtocolVersionMin.ToString(); + sendData["VERSIONMAX"] = ProtocolVersions.ClientProtocolVersionMax.ToString(); + sendData["METHOD"] = "getgriduserinfos"; + + sendData["AgentIDs"] = new List(userIDs); + + string reply = string.Empty; + string reqString = ServerUtils.BuildQueryString(sendData); + //m_log.DebugFormat("[PRESENCE CONNECTOR]: queryString = {0}", reqString); + try + { + reply = SynchronousRestFormsRequester.MakeRequest("POST", + m_ServerURI + "/griduser", + reqString); + if (reply == null || (reply != null && reply == string.Empty)) + { + m_log.DebugFormat("[GRID USER CONNECTOR]: GetGridUserInfo received null or empty reply"); + return null; + } + } + catch (Exception e) + { + m_log.DebugFormat("[GRID USER CONNECTOR]: Exception when contacting grid user server: {0}", e.Message); + } + + List rinfos = new List(); + + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData != null) + { + if (replyData.ContainsKey("result") && + (replyData["result"].ToString() == "null" || replyData["result"].ToString() == "Failure")) + { + return new GridUserInfo[0]; + } + + Dictionary.ValueCollection pinfosList = replyData.Values; + //m_log.DebugFormat("[PRESENCE CONNECTOR]: GetAgents returned {0} elements", pinfosList.Count); + foreach (object griduser in pinfosList) + { + if (griduser is Dictionary) + { + GridUserInfo pinfo = new GridUserInfo((Dictionary)griduser); + rinfos.Add(pinfo); + } + else + m_log.DebugFormat("[GRID USER CONNECTOR]: GetGridUserInfo received invalid response type {0}", + griduser.GetType()); + } + } + else + m_log.DebugFormat("[GRID USER CONNECTOR]: GetGridUserInfo received null response"); + + return rinfos.ToArray(); + } } } diff --git a/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs index c030bca077..5c509360d8 100644 --- a/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/HeloServiceConnector.cs @@ -66,7 +66,7 @@ namespace OpenSim.Services.Connectors m_ServerURI = m_ServerURI.TrimEnd('/') + "/helo/"; } } - catch (UriFormatException e) + catch (UriFormatException) { m_log.WarnFormat("[HELO SERVICE]: Malformed URL {0}", serverURI); } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs index 678f738abb..ca1b64f2b7 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianPresenceServiceConnector.cs @@ -472,6 +472,10 @@ namespace OpenSim.Services.Connectors.SimianGrid return false; } + public GridUserInfo[] GetGridUserInfo(string[] userIDs) + { + return new GridUserInfo[0]; + } #endregion Helpers } } diff --git a/OpenSim/Services/HypergridService/HGAssetService.cs b/OpenSim/Services/HypergridService/HGAssetService.cs index e518329f58..22e233a368 100644 --- a/OpenSim/Services/HypergridService/HGAssetService.cs +++ b/OpenSim/Services/HypergridService/HGAssetService.cs @@ -53,7 +53,7 @@ namespace OpenSim.Services.HypergridService LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - private string m_ProfileServiceURL; + private string m_HomeURL; private IUserAccountService m_UserAccountService; private UserAccountCache m_Cache; @@ -74,7 +74,10 @@ namespace OpenSim.Services.HypergridService if (m_UserAccountService == null) throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); - m_ProfileServiceURL = assetConfig.GetString("ProfileServerURI", string.Empty); + // legacy configuration [obsolete] + m_HomeURL = assetConfig.GetString("ProfileServerURI", string.Empty); + // Preferred + m_HomeURL = assetConfig.GetString("HomeURI", m_HomeURL); m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); } @@ -134,13 +137,13 @@ namespace OpenSim.Services.HypergridService UserAccount creator = m_Cache.GetUser(meta.CreatorID); if (creator != null) - meta.CreatorID = m_ProfileServiceURL + "/" + meta.CreatorID + ";" + creator.FirstName + " " + creator.LastName; + meta.CreatorID = meta.CreatorID + ";" + m_HomeURL + "/" + creator.FirstName + " " + creator.LastName; } protected byte[] AdjustIdentifiers(byte[] data) { string xml = Utils.BytesToString(data); - return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, m_ProfileServiceURL, m_Cache, UUID.Zero)); + return Utils.StringToBytes(ExternalRepresentationUtils.RewriteSOP(xml, m_HomeURL, m_Cache, UUID.Zero)); } } diff --git a/OpenSim/Services/HypergridService/HGInventoryService.cs b/OpenSim/Services/HypergridService/HGInventoryService.cs index 4eb61ba6b9..41d5a7aadc 100644 --- a/OpenSim/Services/HypergridService/HGInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGInventoryService.cs @@ -55,7 +55,7 @@ namespace OpenSim.Services.HypergridService protected new IXInventoryData m_Database; - private string m_ProfileServiceURL; + private string m_HomeURL; private IUserAccountService m_UserAccountService; private UserAccountCache m_Cache; @@ -100,7 +100,10 @@ namespace OpenSim.Services.HypergridService if (m_UserAccountService == null) throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); - m_ProfileServiceURL = invConfig.GetString("ProfileServerURI", string.Empty); + // legacy configuration [obsolete] + m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); + // Preferred + m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); } @@ -316,13 +319,14 @@ namespace OpenSim.Services.HypergridService public override InventoryItemBase GetItem(InventoryItemBase item) { InventoryItemBase it = base.GetItem(item); + if (it != null) + { + UserAccount user = m_Cache.GetUser(it.CreatorId); - UserAccount user = m_Cache.GetUser(it.CreatorId); - - // Adjust the creator data - if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) - it.CreatorData = m_ProfileServiceURL + "/" + it.CreatorId + ";" + user.FirstName + " " + user.LastName; - + // Adjust the creator data + if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) + it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; + } return it; } diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index 7137f9ac71..d80999649f 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -190,6 +190,7 @@ namespace OpenSim.Services.Interfaces public UUID ScopeID = UUID.Zero; public UUID TerrainImage = UUID.Zero; + public UUID ParcelImage = UUID.Zero; public byte Access; public int Maturity; public string RegionSecret = string.Empty; @@ -236,6 +237,7 @@ namespace OpenSim.Services.Interfaces RegionID = ConvertFrom.RegionID; ServerURI = ConvertFrom.ServerURI; TerrainImage = ConvertFrom.RegionSettings.TerrainImageID; + ParcelImage = ConvertFrom.RegionSettings.ParcelImageID; Access = ConvertFrom.AccessLevel; Maturity = ConvertFrom.RegionSettings.Maturity; RegionSecret = ConvertFrom.regionSecret; @@ -253,6 +255,7 @@ namespace OpenSim.Services.Interfaces RegionID = ConvertFrom.RegionID; ServerURI = ConvertFrom.ServerURI; TerrainImage = ConvertFrom.TerrainImage; + ParcelImage = ConvertFrom.ParcelImage; Access = ConvertFrom.Access; Maturity = ConvertFrom.Maturity; RegionSecret = ConvertFrom.RegionSecret; @@ -281,7 +284,7 @@ namespace OpenSim.Services.Interfaces public override int GetHashCode() { - return RegionID.GetHashCode() ^ TerrainImage.GetHashCode(); + return RegionID.GetHashCode() ^ TerrainImage.GetHashCode() ^ ParcelImage.GetHashCode(); } #endregion @@ -359,6 +362,7 @@ namespace OpenSim.Services.Interfaces kvp["serverURI"] = ServerURI; kvp["serverPort"] = InternalEndPoint.Port.ToString(); kvp["regionMapTexture"] = TerrainImage.ToString(); + kvp["parcelMapTexture"] = ParcelImage.ToString(); kvp["access"] = Access.ToString(); kvp["regionSecret"] = RegionSecret; kvp["owner_uuid"] = EstateOwner.ToString(); @@ -411,6 +415,9 @@ namespace OpenSim.Services.Interfaces if (kvp.ContainsKey("regionMapTexture")) UUID.TryParse((string)kvp["regionMapTexture"], out TerrainImage); + if (kvp.ContainsKey("parcelMapTexture")) + UUID.TryParse((string)kvp["parcelMapTexture"], out ParcelImage); + if (kvp.ContainsKey("access")) Access = Byte.Parse((string)kvp["access"]); diff --git a/OpenSim/Services/Interfaces/IGridUserService.cs b/OpenSim/Services/Interfaces/IGridUserService.cs index 6613ae769f..0a52bfaae4 100644 --- a/OpenSim/Services/Interfaces/IGridUserService.cs +++ b/OpenSim/Services/Interfaces/IGridUserService.cs @@ -131,5 +131,6 @@ namespace OpenSim.Services.Interfaces bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 lastPosition, Vector3 lastLookAt); GridUserInfo GetGridUserInfo(string userID); + GridUserInfo[] GetGridUserInfo(string[] userID); } -} \ No newline at end of file +} diff --git a/OpenSim/Services/UserAccountService/GridUserService.cs b/OpenSim/Services/UserAccountService/GridUserService.cs index 9b18915255..ac3d8fda44 100644 --- a/OpenSim/Services/UserAccountService/GridUserService.cs +++ b/OpenSim/Services/UserAccountService/GridUserService.cs @@ -73,6 +73,16 @@ namespace OpenSim.Services.UserAccountService return info; } + public GridUserInfo[] GetGridUserInfo(string[] userIDs) + { + List ret = new List(); + + foreach (string id in userIDs) + ret.Add(GetGridUserInfo(id)); + + return ret.ToArray(); + } + public GridUserInfo LoggedIn(string userID) { m_log.DebugFormat("[GRID USER SERVICE]: User {0} is online", userID); @@ -156,4 +166,4 @@ namespace OpenSim.Services.UserAccountService return m_Database.Store(d); } } -} \ No newline at end of file +} diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 37b90e17b3..ab89fe02b4 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -44,9 +44,6 @@ namespace OpenSim.Tests.Common.Mock { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - // Mock testing variables - public List sentdatapkt = new List(); - public List sentpktpkt = new List(); EventWaitHandle wh = new EventWaitHandle (false, EventResetMode.AutoReset, "Crossing"); // TODO: This is a really nasty (and temporary) means of telling the test client which scene to invoke setup @@ -61,6 +58,10 @@ namespace OpenSim.Tests.Common.Mock public List ReceivedOnlineNotifications { get; private set; } public List ReceivedFriendshipTerminations { get; private set; } + public List SentImageDataPackets { get; private set; } + public List SentImagePacketPackets { get; private set; } + public List SentImageNotInDatabasePackets { get; private set; } + // disable warning: public events, part of the public API #pragma warning disable 67 @@ -193,6 +194,7 @@ namespace OpenSim.Tests.Common.Mock public event RegionInfoRequest OnRegionInfoRequest; public event EstateCovenantRequest OnEstateCovenantRequest; public event EstateChangeInfo OnEstateChangeInfo; + public event EstateManageTelehub OnEstateManageTelehub; public event ObjectDuplicateOnRay OnObjectDuplicateOnRay; @@ -452,6 +454,10 @@ namespace OpenSim.Tests.Common.Mock ReceivedOfflineNotifications = new List(); ReceivedOnlineNotifications = new List(); ReceivedFriendshipTerminations = new List(); + + SentImageDataPackets = new List(); + SentImagePacketPackets = new List(); + SentImageNotInDatabasePackets = new List(); } /// @@ -804,7 +810,7 @@ namespace OpenSim.Tests.Common.Mock im.ImageData.Data = ImageData; im.ImageID.Codec = imageCodec; im.Header.Zerocoded = true; - sentdatapkt.Add(im); + SentImageDataPackets.Add(im); } public void SendImageNextPart(ushort partNumber, UUID imageUuid, byte[] imageData) @@ -814,11 +820,15 @@ namespace OpenSim.Tests.Common.Mock im.ImageID.Packet = partNumber; im.ImageID.ID = imageUuid; im.ImageData.Data = imageData; - sentpktpkt.Add(im); + SentImagePacketPackets.Add(im); } public void SendImageNotFound(UUID imageid) { + ImageNotInDatabasePacket p = new ImageNotInDatabasePacket(); + p.ImageID.ID = imageid; + + SentImageNotInDatabasePackets.Add(p); } public void SendShutdownConnectionNotice() @@ -942,6 +952,10 @@ namespace OpenSim.Tests.Common.Mock { } + public void SendTelehubInfo(UUID ObjectID, string ObjectName, Vector3 ObjectPos, Quaternion ObjectRot, List SpawnPoint) + { + } + public void SendEstateList(UUID invoice, int code, UUID[] Data, uint estateID) { } diff --git a/OpenSim/Tests/Torture/ObjectTortureTests.cs b/OpenSim/Tests/Torture/ObjectTortureTests.cs new file mode 100644 index 0000000000..cdbaa66c63 --- /dev/null +++ b/OpenSim/Tests/Torture/ObjectTortureTests.cs @@ -0,0 +1,126 @@ +/* + * 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.Diagnostics; +using System.Reflection; +using log4net; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using OpenSim.Tests.Common.Mock; + +namespace OpenSim.Tests.Torture +{ + /// + /// Object torture tests + /// + /// + /// Don't rely on the numbers given by these tests - they will vary a lot depending on what is already cached, + /// how much memory is free, etc. In some cases, later larger tests will apparently take less time than smaller + /// earlier tests. + /// + [TestFixture] + public class ObjectTortureTests + { +// [Test] +// public void Test0000Clean() +// { +// TestHelpers.InMethod(); +//// log4net.Config.XmlConfigurator.Configure(); +// +// TestAddObjects(200000); +// } + + [Test] + public void Test0001TenThousandObjects() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + TestAddObjects(10000); + } + + [Test] + public void Test0002OneHundredThousandObjects() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + TestAddObjects(100000); + } + + [Test] + public void Test0003TwoHundredThousandObjects() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + TestAddObjects(200000); + } + + private void TestAddObjects(int objectsToAdd) + { + UUID ownerId = new UUID("F0000000-0000-0000-0000-000000000000"); + + TestScene scene = SceneHelpers.SetupScene(); + + Process process = Process.GetCurrentProcess(); +// long startProcessMemory = process.PrivateMemorySize64; + long startGcMemory = GC.GetTotalMemory(true); + DateTime start = DateTime.Now; + + for (int i = 1; i <= objectsToAdd; i++) + { + SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, ownerId, "part_", i); + Assert.That(scene.AddNewSceneObject(so, false), Is.True, string.Format("Object {0} was not created", i)); + } + + TimeSpan elapsed = DateTime.Now - start; +// long processMemoryAlloc = process.PrivateMemorySize64 - startProcessMemory; + long processGcAlloc = GC.GetTotalMemory(false) - startGcMemory; + + for (int i = 1; i <= objectsToAdd; i++) + { + Assert.That( + scene.GetSceneObjectGroup(TestHelpers.ParseTail(i)), + Is.Not.Null, + string.Format("Object {0} could not be retrieved", i)); + } + +// Console.WriteLine( +// "Took {0}ms, {1}MB to create {2} single prim scene objects", +// elapsed.Milliseconds, processGcAlloc / 1024 / 1024, objectsToAdd); + + Console.WriteLine( + "Took {0}MB to create {1} single prim scene objects", + processGcAlloc / 1024 / 1024, objectsToAdd); + } + } +} \ No newline at end of file diff --git a/TESTING.txt b/TESTING.txt index 54fc976e95..08a0698d2f 100644 --- a/TESTING.txt +++ b/TESTING.txt @@ -69,3 +69,6 @@ Example nunit-console2 OpenSim.Framework.Tests.dll (on linux) nunit-console OpenSim.Framework.Tests.dll (on windows) + +See the file OpenSim/Data/Tests/Resources/TestDataConnections.ini +for information to setup testing for data diff --git a/bin/BulletSim-x86_64.dll b/bin/BulletSim-x86_64.dll index 6620759214..ec21dfedcf 100755 Binary files a/bin/BulletSim-x86_64.dll and b/bin/BulletSim-x86_64.dll differ diff --git a/bin/BulletSim.dll b/bin/BulletSim.dll index ffb538082c..d1571cf751 100755 Binary files a/bin/BulletSim.dll and b/bin/BulletSim.dll differ diff --git a/bin/OpenSim.Tests.Torture.dll.config b/bin/OpenSim.Tests.Torture.dll.config new file mode 100644 index 0000000000..a3f681d89e --- /dev/null +++ b/bin/OpenSim.Tests.Torture.dll.config @@ -0,0 +1,33 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index d4e61a559b..f9b405d81f 100755 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -36,6 +36,7 @@ [Startup] + ;# {ConsolePrompt} {} {ConsolePrompt} {} "Region (\R) " ;; Console prompt ;; Certain special characters can be used to customize the prompt @@ -170,9 +171,9 @@ ; physics = basicphysics ; physics = POS - ;# {permissionmodules} {} {Permission modules to use (may specify multiple modules, separated by space} {} DefaultPermissionsModule - ;; Permission modules to use, separated by space. - ; permissionmodules = "DefaultPermissionsModule" + ;# {permissionmodules} {} {Permission modules to use (may specify multiple modules, separated by comma} {} DefaultPermissionsModule + ;; Permission modules to use, separated by comma. + ; permissionmodules = DefaultPermissionsModule ;# {serverside_object_permissions} {permissionmodules:DefaultPermissionsModule} {Activate permission handling by the sim?} {true false} true ;; These are the parameters for the default permissions module diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index 3e7f8a626f..3935c92f41 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -515,16 +515,16 @@ ;DisableFacelights = "false(1815) [ClientStack.LindenCaps] - ;; Long list of capabilities taken from - ;; http://wiki.secondlife.com/wiki/Current_Sim_Capabilities - ;; Not all are supported by OpenSim. The ones supported are - ;; set to localhost. These defaults can be overwritten - ;; in OpenSim.ini - ;; - Cap_AttachmentResources = "" + ;; Long list of capabilities taken from + ;; http://wiki.secondlife.com/wiki/Current_Sim_Capabilities + ;; Not all are supported by OpenSim. The ones supported are + ;; set to localhost. These defaults can be overwritten + ;; in OpenSim.ini + ;; + Cap_AttachmentResources = "" Cap_AvatarPickerSearch = "" Cap_ChatSessionRequest = "" - Cap_CopyInventoryFromNotecard = "" + Cap_CopyInventoryFromNotecard = "localhost" Cap_DispatchRegionInfo = "" Cap_EstateChangeInfo = "" Cap_EventQueueGet = "localhost" @@ -579,12 +579,13 @@ Cap_ViewerStartAuction = "" Cap_ViewerStats = "" - ; The fetch inventory descendents caps are supported by OpenSim, but may - ; lead to poor sim performance if served by the simulators, - ; so they are disabled by default. - ; FetchInventoryDescendents2 is the one used in the latest Linden Lab viewers (from some point in the v2 series and above) + ; The various fetch inventory caps are supported by OpenSim, but may + ; lead to poor sim performance if served by the simulators, + ; so they are currently disabled by default. + ; FetchInventoryDescendents2 and FetchInventory2 are the ones used in the latest Linden Lab viewers (from some point in the v2 series and above) Cap_WebFetchInventoryDescendents = "" Cap_FetchInventoryDescendents2 = "" + Cap_FetchInventory2 = "" [Chat] @@ -841,8 +842,9 @@ DeactivationTime = 0.2 LinearSleepingThreshold = 0.8 AngularSleepingThreshold = 1.0 - CcdMotionThreshold = 0.5 - CcdSweptSphereRadius = 0.2 + CcdMotionThreshold = 0.0 + CcdSweptSphereRadius = 0.0 + ContactProcessingThreshold = 0.1 ; Whether to mesh sculpties MeshSculptedPrim = true diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 49ee41a5b6..ab5880d741 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -251,7 +251,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 SRV_HomeURI = "http://127.0.0.1:8002" SRV_InventoryServerURI = "http://127.0.0.1:8002" SRV_AssetServerURI = "http://127.0.0.1:8002" - SRV_ProfileServerURI = "http://127.0.0.1:8002/user" + SRV_ProfileServerURI = "http://127.0.0.1:8002" SRV_FriendsServerURI = "http://127.0.0.1:8002" SRV_IMServerURI = "http://127.0.0.1:8002" @@ -380,7 +380,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 ; For the InventoryServiceInConnector LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGInventoryService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" - ProfileServerURI = "http://127.0.0.1:8002/user" + HomeURI = "http://127.0.0.1:8002" ; * The interface that local users get when they are in other grids. ; * This restricts the access that the rest of the world has to @@ -389,7 +389,7 @@ ServiceConnectors = "8003/OpenSim.Server.Handlers.dll:AssetServiceConnector,8003 [HGAssetService] LocalServiceModule = "OpenSim.Services.HypergridService.dll:HGAssetService" UserAccountsService = "OpenSim.Services.UserAccountService.dll:UserAccountService" - ProfileServerURI = "http://127.0.0.1:8002/user" + HomeURI = "http://127.0.0.1:8002" [HGFriendsService] LocalServiceModule = "OpenSim.Services.FriendsService.dll:FriendsService" diff --git a/bin/config-include/GridCommon.ini.example b/bin/config-include/GridCommon.ini.example index e3682497fc..4195bcee50 100644 --- a/bin/config-include/GridCommon.ini.example +++ b/bin/config-include/GridCommon.ini.example @@ -58,6 +58,12 @@ ; InventoryServerURI = "http://mygridserver.com:8003" +[GridInfo] + ; + ; Change this to your grid info service + ; + GridInfoURI = "http://mygridserver.com:8002" + [GridService] ; ; Change this to your grid-wide grid server @@ -123,7 +129,7 @@ ; Change this to your server ; accessible from other grids ; - ProfileServerURI = "http://mygridserver.com:8002/user" + HomeURI = "http://mygridserver.com:8002" Gatekeeper = "http://mygridserver.com:8002" ;; If you want to protect your assets from being copied by foreign visitors ;; uncomment the next line. You may want to do this on sims that have licensed content. diff --git a/bin/config-include/StandaloneCommon.ini.example b/bin/config-include/StandaloneCommon.ini.example index 84611ec258..2f39218b13 100644 --- a/bin/config-include/StandaloneCommon.ini.example +++ b/bin/config-include/StandaloneCommon.ini.example @@ -48,13 +48,13 @@ AssetLoaderArgs = "assets/AssetSets.xml" [HGInventoryService] - ProfileServerURI = "http://127.0.0.1:9000/profiles" + HomeURI = "http://127.0.0.1:9000" [HGAssetService] - ProfileServerURI = "http://127.0.0.1:9000/profiles" + HomeURI = "http://127.0.0.1:9000" [HGInventoryAccessModule] - ProfileServerURI = "http://127.0.0.1:9000/profiles" + HomeURI = "http://127.0.0.1:9000" Gatekeeper = "http://127.0.0.1:9000" ;; If you want to protect your assets from being copied by foreign visitors diff --git a/bin/libBulletSim-x86_64.so b/bin/libBulletSim-x86_64.so index cd2db40090..527eda5780 100755 Binary files a/bin/libBulletSim-x86_64.so and b/bin/libBulletSim-x86_64.so differ diff --git a/bin/libBulletSim.so b/bin/libBulletSim.so index 44afb5efb1..9f91bfd411 100755 Binary files a/bin/libBulletSim.so and b/bin/libBulletSim.so differ diff --git a/prebuild.xml b/prebuild.xml index 4ea47080d7..65383ee18f 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -2822,7 +2822,6 @@ - @@ -3164,12 +3163,14 @@ + + @@ -3257,6 +3258,39 @@ + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + +