diff --git a/.gitignore b/.gitignore index fae7509131..e04c219d90 100644 --- a/.gitignore +++ b/.gitignore @@ -29,14 +29,9 @@ addon-modules/ bin/Debug/*.dll bin/*.dll.mdb bin/*.db -bin/*.db-journal bin/addin-db-* bin/*.dll bin/OpenSim.vshost.exe.config -bin/OpenSim.32BitLaunch.vshost.exe.config -bin/OpenSim.32BitLaunch.log -UpgradeLog.XML -_UpgradeReport_Files/ bin/ScriptEngines/*-*-*-*-* bin/ScriptEngines/*.dll bin/ScriptEngines/*/*.dll @@ -69,7 +64,6 @@ Examples/*.dll OpenSim.build OpenSim.sln OpenSim.suo -OpenSim.userprefs Prebuild/Prebuild.build Prebuild/Prebuild.sln TestResult.xml diff --git a/.nant/local.include b/.nant/local.include index 35f00589e8..6d3e97228f 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -135,25 +135,14 @@ - + - - + + - - - - - - - - - - - - + diff --git a/BUILDING.md b/BUILDING.txt similarity index 58% rename from BUILDING.md rename to BUILDING.txt index 5210b58f1f..12e5ea53cf 100644 --- a/BUILDING.md +++ b/BUILDING.txt @@ -1,4 +1,6 @@ -# Building on Windows +==== Building OpenSim ==== + +=== Building on Windows === Steps: * runprebuild.bat @@ -7,15 +9,16 @@ Steps: * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include * run OpenSim.exe -# Building on Linux +=== Building on Linux === Prereqs: -* Mono >= 2.4.3 -* Nant >= 0.85 -* 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 + * Mono >= 2.4.3 + * Nant >= 0.85 + * 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 @@ -24,13 +27,13 @@ From the distribution type: * copy OpenSim.ini.example to OpenSim.ini and other appropriate files in bin/config-include * run mono OpenSim.exe -# Using Monodevelop +=== Using Monodevelop === From the distribution type: * ./runprebuild.sh * type monodevelop OpenSim.sln -# References +=== References === Helpful resources: * http://opensimulator.org/wiki/Build_Instructions diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index e5a6d49413..9dd0797411 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -1,5 +1,5 @@ - <<<>>>>The following people have contributed to OpenSim (Thank you -for your effort!) +<<<>>>>The following people have contributed to OpenSim (Thank you +for your effort!) = Current OpenSim Developers (in very rough order of appearance) = These folks represent the current core team for OpenSim, and are the @@ -16,7 +16,7 @@ people that make the day to day of OpenSim happen. * BlueWall (James Hughes) * Nebadon Izumi (Michael Cerquoni, OSgrid) * Snoopy Pfeffer -* Robert Adams (Intel) +* Richard Adams (Intel) = Core Developers Following the White Rabbit = Core developers who have temporarily (we hope) gone chasing the white rabbit. @@ -92,7 +92,6 @@ what it is today. * Flyte Xevious * Garmin Kawaguichi * Gryc Ueusp -* Hiro Lecker * Imaze Rhiano * Intimidated * Jeremy Bongio (IBM) @@ -182,14 +181,12 @@ what it is today. This software uses components from the following developers: * Sleepycat Software (Berkeley DB) -* Aurora-Sim (http://aurora-sim.org) * SQLite (Public Domain) * XmlRpcCS (http://xmlrpccs.sf.net/) * MySQL, Inc. (MySQL Connector/NET) * NUnit (http://www.nunit.org) * AGEIA Inc. (PhysX) * Russel L. Smith (ODE) -* Erwin Coumans (Bullet) * Prebuild (http://sourceforge.net/projects/dnpb/) * LibOpenMetaverse (http://lib.openmetaverse.org/) * DotNetOpenMail v0.5.8b (http://dotnetopenmail.sourceforge.net) @@ -211,4 +208,3 @@ In addition, we would like to thank: * The NANT Developers * Microsoft (.NET, MSSQL-Adapters) *x - diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 9c933eee35..437d150097 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -696,7 +696,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController region.ExternalHostName = (string) requestData["external_address"]; - bool persist = Convert.ToBoolean(requestData["persist"]); + bool persist = Convert.ToBoolean((string) requestData["persist"]); if (persist) { // default place for region configuration files is in the @@ -852,6 +852,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController responseData["success"] = true; responseData["region_name"] = region.RegionName; responseData["region_id"] = region.RegionID.ToString(); + responseData["region_uuid"] = region.RegionID.ToString(); //Deprecate July 2012 m_log.Info("[RADMIN]: CreateRegion: request complete"); } @@ -1105,8 +1106,8 @@ namespace OpenSim.ApplicationPlugins.RemoteController string lastName = (string) requestData["user_lastname"]; string password = (string) requestData["user_password"]; - uint regionXLocation = Convert.ToUInt32(requestData["start_region_x"]); - uint regionYLocation = Convert.ToUInt32(requestData["start_region_y"]); + uint regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]); + uint regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]); string email = ""; // empty string for email if (requestData.Contains("user_email")) @@ -1303,9 +1304,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (requestData.ContainsKey("user_password")) password = (string) requestData["user_password"]; if (requestData.ContainsKey("start_region_x")) - regionXLocation = Convert.ToUInt32(requestData["start_region_x"]); + regionXLocation = Convert.ToUInt32((Int32) requestData["start_region_x"]); if (requestData.ContainsKey("start_region_y")) - regionYLocation = Convert.ToUInt32(requestData["start_region_y"]); + regionYLocation = Convert.ToUInt32((Int32) requestData["start_region_y"]); // if (requestData.ContainsKey("start_lookat_x")) // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]); @@ -1492,8 +1493,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// profile url /// noassets /// true if no assets should be saved - /// all - /// true to save all the regions in the simulator /// perm /// C and/or T /// @@ -1550,11 +1549,6 @@ namespace OpenSim.ApplicationPlugins.RemoteController options["checkPermissions"] = (string)requestData["perm"]; } - if ((string)requestData["all"] == "true") - { - options["all"] = (string)requestData["all"]; - } - IRegionArchiverModule archiver = scene.RequestModuleInterface(); if (archiver != null) @@ -2014,6 +2008,29 @@ namespace OpenSim.ApplicationPlugins.RemoteController { 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; @@ -2035,6 +2052,56 @@ namespace OpenSim.ApplicationPlugins.RemoteController 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"])) { diff --git a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs index 072bd6f010..cb88695600 100644 --- a/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs +++ b/OpenSim/ApplicationPlugins/Rest/Inventory/RestHandler.cs @@ -312,16 +312,14 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory // Now that everything is setup we can proceed to // add THIS agent to the HTTP server's handler list - // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will - // have to be handled through the AddHttpHandler interface. -// if (!AddAgentHandler(Rest.Name,this)) -// { -// Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId); -// foreach (IRest handler in handlers) -// { -// handler.Close(); -// } -// } + if (!AddAgentHandler(Rest.Name,this)) + { + Rest.Log.ErrorFormat("{0} Unable to activate handler interface", MsgId); + foreach (IRest handler in handlers) + { + handler.Close(); + } + } } catch (Exception e) @@ -344,13 +342,11 @@ namespace OpenSim.ApplicationPlugins.Rest.Inventory { Rest.Log.InfoFormat("{0} Plugin is terminating", MsgId); - // FIXME: If this code is ever to be re-enabled (most of it is disabled already) then this will - // have to be handled through the AddHttpHandler interface. -// try -// { -// RemoveAgentHandler(Rest.Name, this); -// } -// catch (KeyNotFoundException){} + try + { + RemoveAgentHandler(Rest.Name, this); + } + catch (KeyNotFoundException){} foreach (IRest handler in handlers) { diff --git a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs index a2425b5cf3..eb167502b0 100644 --- a/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs +++ b/OpenSim/ApplicationPlugins/Rest/RestPlugin.cs @@ -297,9 +297,7 @@ namespace OpenSim.ApplicationPlugins.Rest { if (!IsEnabled) return false; _agents.Add(agentName, handler); -// return _httpd.AddAgentHandler(agentName, handler); - - return false; + return _httpd.AddAgentHandler(agentName, handler); } /// @@ -318,7 +316,7 @@ namespace OpenSim.ApplicationPlugins.Rest if (_agents[agentName] == handler) { _agents.Remove(agentName); -// return _httpd.RemoveAgentHandler(agentName, handler); + return _httpd.RemoveAgentHandler(agentName, handler); } return false; } @@ -360,10 +358,10 @@ namespace OpenSim.ApplicationPlugins.Rest _httpd.RemoveStreamHandler(h.HttpMethod, h.Path); } _handlers = null; -// foreach (KeyValuePair h in _agents) -// { -// _httpd.RemoveAgentHandler(h.Key, h.Value); -// } + foreach (KeyValuePair h in _agents) + { + _httpd.RemoveAgentHandler(h.Key, h.Value); + } _agents = null; } diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index 6437d0b7b0..86e7aa08f3 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs @@ -200,25 +200,11 @@ namespace OpenSim.Capabilities.Handlers int start, end; if (TryParseRange(range, out start, out end)) { + // Before clamping start make sure we can satisfy it in order to avoid // sending back the last byte instead of an error status if (start >= texture.Data.Length) { -// m_log.DebugFormat( -// "[GETTEXTURE]: Client requested range for texture {0} starting at {1} but texture has end of {2}", -// texture.ID, start, texture.Data.Length); - - // Stricly speaking, as per http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html, we should be sending back - // Requested Range Not Satisfiable (416) here. However, it appears that at least recent implementations - // of the Linden Lab viewer (3.2.1 and 3.3.4 and probably earlier), a viewer that has previously - // received a very small texture may attempt to fetch bytes from the server past the - // range of data that it received originally. Whether this happens appears to depend on whether - // the viewer's estimation of how large a request it needs to make for certain discard levels - // (http://wiki.secondlife.com/wiki/Image_System#Discard_Level_and_Mip_Mapping), chiefly discard - // level 2. If this estimate is greater than the total texture size, returning a RequestedRangeNotSatisfiable - // here will cause the viewer to treat the texture as bad and never display the full resolution - // However, if we return PartialContent (or OK) instead, the viewer will display that resolution. - // response.StatusCode = (int)System.Net.HttpStatusCode.RequestedRangeNotSatisfiable; // viewers don't seem to handle RequestedRangeNotSatisfiable and keep retrying with same parameters response["int_response_code"] = (int)System.Net.HttpStatusCode.NotFound; @@ -229,7 +215,7 @@ namespace OpenSim.Capabilities.Handlers start = Utils.Clamp(start, 0, end); int len = end - start + 1; -// m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); + //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); response["content-type"] = texture.Metadata.ContentType; diff --git a/OpenSim/Data/IRegionData.cs b/OpenSim/Data/IRegionData.cs index 70e10653de..546b5e8cba 100644 --- a/OpenSim/Data/IRegionData.cs +++ b/OpenSim/Data/IRegionData.cs @@ -85,6 +85,21 @@ namespace OpenSim.Data List GetHyperlinks(UUID scopeID); } + [Flags] + public enum RegionFlags : int + { + DefaultRegion = 1, // Used for new Rez. Random if multiple defined + FallbackRegion = 2, // Regions we redirect to when the destination is down + RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false + NoDirectLogin = 8, // Region unavailable for direct logins (by name) + Persistent = 16, // Don't remove on unregister + LockedOut = 32, // Don't allow registration + NoMove = 64, // Don't allow moving this region + Reservation = 128, // This is an inactive reservation + Authenticate = 256, // Require authentication + Hyperlink = 512 // Record represents a HG link + } + public class RegionDataDistanceCompare : IComparer { private Vector2 m_origin; diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index e64a82820d..85a5c08d37 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -40,11 +40,6 @@ namespace OpenSim.Data public UUID folderID; public UUID agentID; public UUID parentFolderID; - - public XInventoryFolder Clone() - { - return (XInventoryFolder)MemberwiseClone(); - } } public class XInventoryItem @@ -69,11 +64,6 @@ namespace OpenSim.Data public UUID avatarID; public UUID parentFolderID; public int inventoryGroupPermissions; - - public XInventoryItem Clone() - { - return (XInventoryItem)MemberwiseClone(); - } } public interface IXInventoryData diff --git a/OpenSim/Data/MSSQL/MSSQLRegionData.cs b/OpenSim/Data/MSSQL/MSSQLRegionData.cs index 0d89706566..3ae87c3804 100644 --- a/OpenSim/Data/MSSQL/MSSQLRegionData.cs +++ b/OpenSim/Data/MSSQL/MSSQLRegionData.cs @@ -37,7 +37,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using RegionFlags = OpenSim.Framework.RegionFlags; namespace OpenSim.Data.MSSQL { diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs index a2d4ae4647..0614879061 100644 --- a/OpenSim/Data/MySQL/MySQLRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLRegionData.cs @@ -30,11 +30,11 @@ using System.Collections; using System.Collections.Generic; using System.Data; using System.Reflection; -using MySql.Data.MySqlClient; + using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; -using RegionFlags = OpenSim.Framework.RegionFlags; +using MySql.Data.MySqlClient; namespace OpenSim.Data.MySQL { diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 12c979aa50..4d7c0c937c 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -747,99 +747,95 @@ namespace OpenSim.Data.MySQL RegionLightShareData nWP = new RegionLightShareData(); nWP.OnSave += StoreRegionWindlightSettings; - lock (m_dbLock) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + dbcon.Open(); + + string command = "select * from `regionwindlight` where region_id = ?regionID"; + + using (MySqlCommand cmd = new MySqlCommand(command)) { - dbcon.Open(); - - string command = "select * from `regionwindlight` where region_id = ?regionID"; - - using (MySqlCommand cmd = new MySqlCommand(command)) + cmd.Connection = dbcon; + + cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); + + IDataReader result = ExecuteReader(cmd); + if (!result.Read()) { - cmd.Connection = dbcon; - - cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); - - IDataReader result = ExecuteReader(cmd); - if (!result.Read()) - { - //No result, so store our default windlight profile and return it - nWP.regionID = regionUUID; -// StoreRegionWindlightSettings(nWP); - return nWP; - } - else - { - nWP.regionID = DBGuid.FromDB(result["region_id"]); - nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); - nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); - nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); - nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); - nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); - nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); - nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); - nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); - nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); - nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); - nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); - nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); - nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); - nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); - nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); - nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); - nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); - UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); - nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); - nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); - nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); - nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); - nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); - nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); - nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); - nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); - nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); - nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); - nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); - nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); - nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); - nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); - nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); - nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); - nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); - nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); - nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); - nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); - nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); - nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); - nWP.eastAngle = Convert.ToSingle(result["east_angle"]); - nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); - nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); - nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); - nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); - nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); - nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); - nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); - nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); - nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); - nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); - nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); - nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); - nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); - nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); - nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); - nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); - nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); - nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); - nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); - nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); - nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); - nWP.valid = true; - } + //No result, so store our default windlight profile and return it + nWP.regionID = regionUUID; + // StoreRegionWindlightSettings(nWP); + return nWP; + } + else + { + nWP.regionID = DBGuid.FromDB(result["region_id"]); + nWP.waterColor.X = Convert.ToSingle(result["water_color_r"]); + nWP.waterColor.Y = Convert.ToSingle(result["water_color_g"]); + nWP.waterColor.Z = Convert.ToSingle(result["water_color_b"]); + nWP.waterFogDensityExponent = Convert.ToSingle(result["water_fog_density_exponent"]); + nWP.underwaterFogModifier = Convert.ToSingle(result["underwater_fog_modifier"]); + nWP.reflectionWaveletScale.X = Convert.ToSingle(result["reflection_wavelet_scale_1"]); + nWP.reflectionWaveletScale.Y = Convert.ToSingle(result["reflection_wavelet_scale_2"]); + nWP.reflectionWaveletScale.Z = Convert.ToSingle(result["reflection_wavelet_scale_3"]); + nWP.fresnelScale = Convert.ToSingle(result["fresnel_scale"]); + nWP.fresnelOffset = Convert.ToSingle(result["fresnel_offset"]); + nWP.refractScaleAbove = Convert.ToSingle(result["refract_scale_above"]); + nWP.refractScaleBelow = Convert.ToSingle(result["refract_scale_below"]); + nWP.blurMultiplier = Convert.ToSingle(result["blur_multiplier"]); + nWP.bigWaveDirection.X = Convert.ToSingle(result["big_wave_direction_x"]); + nWP.bigWaveDirection.Y = Convert.ToSingle(result["big_wave_direction_y"]); + nWP.littleWaveDirection.X = Convert.ToSingle(result["little_wave_direction_x"]); + nWP.littleWaveDirection.Y = Convert.ToSingle(result["little_wave_direction_y"]); + UUID.TryParse(result["normal_map_texture"].ToString(), out nWP.normalMapTexture); + nWP.horizon.X = Convert.ToSingle(result["horizon_r"]); + nWP.horizon.Y = Convert.ToSingle(result["horizon_g"]); + nWP.horizon.Z = Convert.ToSingle(result["horizon_b"]); + nWP.horizon.W = Convert.ToSingle(result["horizon_i"]); + nWP.hazeHorizon = Convert.ToSingle(result["haze_horizon"]); + nWP.blueDensity.X = Convert.ToSingle(result["blue_density_r"]); + nWP.blueDensity.Y = Convert.ToSingle(result["blue_density_g"]); + nWP.blueDensity.Z = Convert.ToSingle(result["blue_density_b"]); + nWP.blueDensity.W = Convert.ToSingle(result["blue_density_i"]); + nWP.hazeDensity = Convert.ToSingle(result["haze_density"]); + nWP.densityMultiplier = Convert.ToSingle(result["density_multiplier"]); + nWP.distanceMultiplier = Convert.ToSingle(result["distance_multiplier"]); + nWP.maxAltitude = Convert.ToUInt16(result["max_altitude"]); + nWP.sunMoonColor.X = Convert.ToSingle(result["sun_moon_color_r"]); + nWP.sunMoonColor.Y = Convert.ToSingle(result["sun_moon_color_g"]); + nWP.sunMoonColor.Z = Convert.ToSingle(result["sun_moon_color_b"]); + nWP.sunMoonColor.W = Convert.ToSingle(result["sun_moon_color_i"]); + nWP.sunMoonPosition = Convert.ToSingle(result["sun_moon_position"]); + nWP.ambient.X = Convert.ToSingle(result["ambient_r"]); + nWP.ambient.Y = Convert.ToSingle(result["ambient_g"]); + nWP.ambient.Z = Convert.ToSingle(result["ambient_b"]); + nWP.ambient.W = Convert.ToSingle(result["ambient_i"]); + nWP.eastAngle = Convert.ToSingle(result["east_angle"]); + nWP.sunGlowFocus = Convert.ToSingle(result["sun_glow_focus"]); + nWP.sunGlowSize = Convert.ToSingle(result["sun_glow_size"]); + nWP.sceneGamma = Convert.ToSingle(result["scene_gamma"]); + nWP.starBrightness = Convert.ToSingle(result["star_brightness"]); + nWP.cloudColor.X = Convert.ToSingle(result["cloud_color_r"]); + nWP.cloudColor.Y = Convert.ToSingle(result["cloud_color_g"]); + nWP.cloudColor.Z = Convert.ToSingle(result["cloud_color_b"]); + nWP.cloudColor.W = Convert.ToSingle(result["cloud_color_i"]); + nWP.cloudXYDensity.X = Convert.ToSingle(result["cloud_x"]); + nWP.cloudXYDensity.Y = Convert.ToSingle(result["cloud_y"]); + nWP.cloudXYDensity.Z = Convert.ToSingle(result["cloud_density"]); + nWP.cloudCoverage = Convert.ToSingle(result["cloud_coverage"]); + nWP.cloudScale = Convert.ToSingle(result["cloud_scale"]); + nWP.cloudDetailXYDensity.X = Convert.ToSingle(result["cloud_detail_x"]); + nWP.cloudDetailXYDensity.Y = Convert.ToSingle(result["cloud_detail_y"]); + nWP.cloudDetailXYDensity.Z = Convert.ToSingle(result["cloud_detail_density"]); + nWP.cloudScrollX = Convert.ToSingle(result["cloud_scroll_x"]); + nWP.cloudScrollXLock = Convert.ToBoolean(result["cloud_scroll_x_lock"]); + nWP.cloudScrollY = Convert.ToSingle(result["cloud_scroll_y"]); + nWP.cloudScrollYLock = Convert.ToBoolean(result["cloud_scroll_y_lock"]); + nWP.drawClassicClouds = Convert.ToBoolean(result["draw_classic_clouds"]); + nWP.valid = true; } } } - return nWP; } @@ -885,124 +881,118 @@ namespace OpenSim.Data.MySQL public virtual void StoreRegionWindlightSettings(RegionLightShareData wl) { - lock (m_dbLock) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; - cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; - cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; - cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; - cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; - cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; - cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; - cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; - cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; - cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; - cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; - cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; - cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; - cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; - cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; - cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; - cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; - cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; - cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; - cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; - cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; - cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; - cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; - cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; - cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; - - cmd.Parameters.AddWithValue("region_id", wl.regionID); - cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); - cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); - cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); - cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); - cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); - cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); - cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); - cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); - cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); - cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); - cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); - cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); - cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); - cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); - cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); - cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); - cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); - cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); - cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); - cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); - cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); - cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); - cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); - cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); - cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); - cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); - cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); - cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); - cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); - cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); - cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); - cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); - cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); - cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); - cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); - cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); - cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); - cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); - cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); - cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); - cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); - cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); - cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); - cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); - cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); - cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); - cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); - cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); - cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); - cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); - cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); - cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); - cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); - cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); - cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); - cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); - cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); - cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); - cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); - cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); - cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); - cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); - - ExecuteNonQuery(cmd); - } + cmd.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, "; + cmd.CommandText += "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, "; + cmd.CommandText += "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, "; + cmd.CommandText += "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, "; + cmd.CommandText += "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, "; + cmd.CommandText += "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, "; + cmd.CommandText += "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, "; + cmd.CommandText += "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, "; + cmd.CommandText += "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, "; + cmd.CommandText += "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, "; + cmd.CommandText += "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, "; + cmd.CommandText += "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, "; + cmd.CommandText += "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, "; + cmd.CommandText += "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, "; + cmd.CommandText += "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, "; + cmd.CommandText += "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, "; + cmd.CommandText += "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, "; + cmd.CommandText += "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, "; + cmd.CommandText += "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, "; + cmd.CommandText += "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, "; + cmd.CommandText += "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, "; + cmd.CommandText += "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, "; + cmd.CommandText += "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, "; + cmd.CommandText += "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, "; + cmd.CommandText += "?cloud_scroll_y, ?cloud_scroll_y_lock, ?draw_classic_clouds)"; + + cmd.Parameters.AddWithValue("region_id", wl.regionID); + cmd.Parameters.AddWithValue("water_color_r", wl.waterColor.X); + cmd.Parameters.AddWithValue("water_color_g", wl.waterColor.Y); + cmd.Parameters.AddWithValue("water_color_b", wl.waterColor.Z); + cmd.Parameters.AddWithValue("water_fog_density_exponent", wl.waterFogDensityExponent); + cmd.Parameters.AddWithValue("underwater_fog_modifier", wl.underwaterFogModifier); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_1", wl.reflectionWaveletScale.X); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_2", wl.reflectionWaveletScale.Y); + cmd.Parameters.AddWithValue("reflection_wavelet_scale_3", wl.reflectionWaveletScale.Z); + cmd.Parameters.AddWithValue("fresnel_scale", wl.fresnelScale); + cmd.Parameters.AddWithValue("fresnel_offset", wl.fresnelOffset); + cmd.Parameters.AddWithValue("refract_scale_above", wl.refractScaleAbove); + cmd.Parameters.AddWithValue("refract_scale_below", wl.refractScaleBelow); + cmd.Parameters.AddWithValue("blur_multiplier", wl.blurMultiplier); + cmd.Parameters.AddWithValue("big_wave_direction_x", wl.bigWaveDirection.X); + cmd.Parameters.AddWithValue("big_wave_direction_y", wl.bigWaveDirection.Y); + cmd.Parameters.AddWithValue("little_wave_direction_x", wl.littleWaveDirection.X); + cmd.Parameters.AddWithValue("little_wave_direction_y", wl.littleWaveDirection.Y); + cmd.Parameters.AddWithValue("normal_map_texture", wl.normalMapTexture); + cmd.Parameters.AddWithValue("horizon_r", wl.horizon.X); + cmd.Parameters.AddWithValue("horizon_g", wl.horizon.Y); + cmd.Parameters.AddWithValue("horizon_b", wl.horizon.Z); + cmd.Parameters.AddWithValue("horizon_i", wl.horizon.W); + cmd.Parameters.AddWithValue("haze_horizon", wl.hazeHorizon); + cmd.Parameters.AddWithValue("blue_density_r", wl.blueDensity.X); + cmd.Parameters.AddWithValue("blue_density_g", wl.blueDensity.Y); + cmd.Parameters.AddWithValue("blue_density_b", wl.blueDensity.Z); + cmd.Parameters.AddWithValue("blue_density_i", wl.blueDensity.W); + cmd.Parameters.AddWithValue("haze_density", wl.hazeDensity); + cmd.Parameters.AddWithValue("density_multiplier", wl.densityMultiplier); + cmd.Parameters.AddWithValue("distance_multiplier", wl.distanceMultiplier); + cmd.Parameters.AddWithValue("max_altitude", wl.maxAltitude); + cmd.Parameters.AddWithValue("sun_moon_color_r", wl.sunMoonColor.X); + cmd.Parameters.AddWithValue("sun_moon_color_g", wl.sunMoonColor.Y); + cmd.Parameters.AddWithValue("sun_moon_color_b", wl.sunMoonColor.Z); + cmd.Parameters.AddWithValue("sun_moon_color_i", wl.sunMoonColor.W); + cmd.Parameters.AddWithValue("sun_moon_position", wl.sunMoonPosition); + cmd.Parameters.AddWithValue("ambient_r", wl.ambient.X); + cmd.Parameters.AddWithValue("ambient_g", wl.ambient.Y); + cmd.Parameters.AddWithValue("ambient_b", wl.ambient.Z); + cmd.Parameters.AddWithValue("ambient_i", wl.ambient.W); + cmd.Parameters.AddWithValue("east_angle", wl.eastAngle); + cmd.Parameters.AddWithValue("sun_glow_focus", wl.sunGlowFocus); + cmd.Parameters.AddWithValue("sun_glow_size", wl.sunGlowSize); + cmd.Parameters.AddWithValue("scene_gamma", wl.sceneGamma); + cmd.Parameters.AddWithValue("star_brightness", wl.starBrightness); + cmd.Parameters.AddWithValue("cloud_color_r", wl.cloudColor.X); + cmd.Parameters.AddWithValue("cloud_color_g", wl.cloudColor.Y); + cmd.Parameters.AddWithValue("cloud_color_b", wl.cloudColor.Z); + cmd.Parameters.AddWithValue("cloud_color_i", wl.cloudColor.W); + cmd.Parameters.AddWithValue("cloud_x", wl.cloudXYDensity.X); + cmd.Parameters.AddWithValue("cloud_y", wl.cloudXYDensity.Y); + cmd.Parameters.AddWithValue("cloud_density", wl.cloudXYDensity.Z); + cmd.Parameters.AddWithValue("cloud_coverage", wl.cloudCoverage); + cmd.Parameters.AddWithValue("cloud_scale", wl.cloudScale); + cmd.Parameters.AddWithValue("cloud_detail_x", wl.cloudDetailXYDensity.X); + cmd.Parameters.AddWithValue("cloud_detail_y", wl.cloudDetailXYDensity.Y); + cmd.Parameters.AddWithValue("cloud_detail_density", wl.cloudDetailXYDensity.Z); + cmd.Parameters.AddWithValue("cloud_scroll_x", wl.cloudScrollX); + cmd.Parameters.AddWithValue("cloud_scroll_x_lock", wl.cloudScrollXLock); + cmd.Parameters.AddWithValue("cloud_scroll_y", wl.cloudScrollY); + cmd.Parameters.AddWithValue("cloud_scroll_y_lock", wl.cloudScrollYLock); + cmd.Parameters.AddWithValue("draw_classic_clouds", wl.drawClassicClouds); + + ExecuteNonQuery(cmd); } } } public virtual void RemoveRegionWindlightSettings(UUID regionID) { - lock (m_dbLock) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID"; - cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); - ExecuteNonQuery(cmd); - } + cmd.CommandText = "delete from `regionwindlight` where `region_id`=?regionID"; + cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); + ExecuteNonQuery(cmd); } } } @@ -1010,29 +1000,26 @@ namespace OpenSim.Data.MySQL #region RegionEnvironmentSettings public string LoadRegionEnvironmentSettings(UUID regionUUID) { - lock (m_dbLock) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + dbcon.Open(); + + string command = "select * from `regionenvironment` where region_id = ?region_id"; + + using (MySqlCommand cmd = new MySqlCommand(command)) { - dbcon.Open(); - - string command = "select * from `regionenvironment` where region_id = ?region_id"; - - using (MySqlCommand cmd = new MySqlCommand(command)) + cmd.Connection = dbcon; + + cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); + + IDataReader result = ExecuteReader(cmd); + if (!result.Read()) { - cmd.Connection = dbcon; - - cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); - - IDataReader result = ExecuteReader(cmd); - if (!result.Read()) - { - return String.Empty; - } - else - { - return Convert.ToString(result["llsd_settings"]); - } + return String.Empty; + } + else + { + return Convert.ToString(result["llsd_settings"]); } } } @@ -1040,39 +1027,33 @@ namespace OpenSim.Data.MySQL public void StoreRegionEnvironmentSettings(UUID regionUUID, string settings) { - lock (m_dbLock) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)"; - - cmd.Parameters.AddWithValue("region_id", regionUUID); - cmd.Parameters.AddWithValue("llsd_settings", settings); - - ExecuteNonQuery(cmd); - } + cmd.CommandText = "REPLACE INTO `regionenvironment` (`region_id`, `llsd_settings`) VALUES (?region_id, ?llsd_settings)"; + + cmd.Parameters.AddWithValue("region_id", regionUUID); + cmd.Parameters.AddWithValue("llsd_settings", settings); + + ExecuteNonQuery(cmd); } } } public void RemoveRegionEnvironmentSettings(UUID regionUUID) { - lock (m_dbLock) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + dbcon.Open(); + + using (MySqlCommand cmd = dbcon.CreateCommand()) { - dbcon.Open(); - - using (MySqlCommand cmd = dbcon.CreateCommand()) - { - cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id"; - cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); - ExecuteNonQuery(cmd); - } + cmd.CommandText = "delete from `regionenvironment` where region_id = ?region_id"; + cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); + ExecuteNonQuery(cmd); } } } diff --git a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations index d08e096364..32b85ee8c1 100644 --- a/OpenSim/Data/MySQL/Resources/GridUserStore.migrations +++ b/OpenSim/Data/MySQL/Resources/GridUserStore.migrations @@ -17,8 +17,3 @@ CREATE TABLE `GridUser` ( ) ENGINE=InnoDB; COMMIT; - -:VERSION 2 # -------------------------- -BEGIN; - -COMMIT; diff --git a/OpenSim/Data/Null/NullRegionData.cs b/OpenSim/Data/Null/NullRegionData.cs index b4d701af50..deb50cb4df 100644 --- a/OpenSim/Data/Null/NullRegionData.cs +++ b/OpenSim/Data/Null/NullRegionData.cs @@ -33,7 +33,6 @@ using OpenSim.Framework; using OpenSim.Data; using System.Reflection; using log4net; -using RegionFlags = OpenSim.Framework.RegionFlags; namespace OpenSim.Data.Null { diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs index 42cd59de31..431709f8d5 100644 --- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -1366,13 +1366,6 @@ namespace OpenSim.Data.SQLite createCol(land, "UserLookAtZ", typeof(Double)); createCol(land, "AuthbuyerID", typeof(String)); createCol(land, "OtherCleanTime", typeof(Int32)); - createCol(land, "Dwell", typeof(Int32)); - createCol(land, "MediaType", typeof(String)); - createCol(land, "MediaDescription", typeof(String)); - createCol(land, "MediaSize", typeof(String)); - createCol(land, "MediaLoop", typeof(Boolean)); - createCol(land, "ObscureMedia", typeof(Boolean)); - createCol(land, "ObscureMusic", typeof(Boolean)); land.PrimaryKey = new DataColumn[] { land.Columns["UUID"] }; @@ -1788,16 +1781,9 @@ namespace OpenSim.Data.SQLite newData.PassHours = Convert.ToSingle(row["PassHours"]); newData.PassPrice = Convert.ToInt32(row["PassPrice"]); newData.SnapshotID = (UUID)(String)row["SnapshotUUID"]; - newData.Dwell = Convert.ToInt32(row["Dwell"]); - newData.MediaType = (String)row["MediaType"]; - newData.MediaDescription = (String)row["MediaDescription"]; - newData.MediaWidth = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[0]); - newData.MediaHeight = Convert.ToInt32((((string)row["MediaSize"]).Split(','))[1]); - newData.MediaLoop = Convert.ToBoolean(row["MediaLoop"]); - newData.ObscureMedia = Convert.ToBoolean(row["ObscureMedia"]); - newData.ObscureMusic = Convert.ToBoolean(row["ObscureMusic"]); try { + newData.UserLocation = new Vector3(Convert.ToSingle(row["UserLocationX"]), Convert.ToSingle(row["UserLocationY"]), Convert.ToSingle(row["UserLocationZ"])); @@ -2209,13 +2195,12 @@ namespace OpenSim.Data.SQLite row["UserLookAtZ"] = land.UserLookAt.Z; row["AuthbuyerID"] = land.AuthBuyerID.ToString(); row["OtherCleanTime"] = land.OtherCleanTime; - row["Dwell"] = land.Dwell; row["MediaType"] = land.MediaType; row["MediaDescription"] = land.MediaDescription; - row["MediaSize"] = String.Format("{0},{1}", land.MediaWidth, land.MediaHeight); - row["MediaLoop"] = land.MediaLoop; - row["ObscureMusic"] = land.ObscureMusic; - row["ObscureMedia"] = land.ObscureMedia; + row["MediaSize"] = land.MediaWidth.ToString() + "," + land.MediaHeight.ToString(); + row["MediaLoop"] = land.MediaLoop.ToString(); + row["ObscureMusic"] = land.ObscureMusic.ToString(); + row["ObscureMedia"] = land.ObscureMedia.ToString(); } /// diff --git a/OpenSim/Framework/AssetPermissions.cs b/OpenSim/Framework/AssetPermissions.cs deleted file mode 100644 index 4a905c2f5d..0000000000 --- a/OpenSim/Framework/AssetPermissions.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Framework -{ - public class AssetPermissions - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private bool[] m_DisallowExport, m_DisallowImport; - private string[] m_AssetTypeNames; - - public AssetPermissions(IConfig config) - { - Type enumType = typeof(AssetType); - m_AssetTypeNames = Enum.GetNames(enumType); - for (int i = 0; i < m_AssetTypeNames.Length; i++) - m_AssetTypeNames[i] = m_AssetTypeNames[i].ToLower(); - int n = Enum.GetValues(enumType).Length; - m_DisallowExport = new bool[n]; - m_DisallowImport = new bool[n]; - - LoadPermsFromConfig(config, "DisallowExport", m_DisallowExport); - LoadPermsFromConfig(config, "DisallowImport", m_DisallowImport); - - } - - private void LoadPermsFromConfig(IConfig assetConfig, string variable, bool[] bitArray) - { - if (assetConfig == null) - return; - - string perms = assetConfig.GetString(variable, String.Empty); - string[] parts = perms.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - foreach (string s in parts) - { - int index = Array.IndexOf(m_AssetTypeNames, s.Trim().ToLower()); - if (index >= 0) - bitArray[index] = true; - else - m_log.WarnFormat("[Asset Permissions]: Invalid AssetType {0}", s); - } - - } - - public bool AllowedExport(sbyte type) - { - string assetTypeName = ((AssetType)type).ToString(); - - int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower()); - if (index >= 0 && m_DisallowExport[index]) - { - m_log.DebugFormat("[Asset Permissions]: Export denied: configuration does not allow export of AssetType {0}", assetTypeName); - return false; - } - - return true; - } - - public bool AllowedImport(sbyte type) - { - string assetTypeName = ((AssetType)type).ToString(); - - int index = Array.IndexOf(m_AssetTypeNames, assetTypeName.ToLower()); - if (index >= 0 && m_DisallowImport[index]) - { - m_log.DebugFormat("[Asset Permissions]: Import denied: configuration does not allow import of AssetType {0}", assetTypeName); - return false; - } - - return true; - } - - - } -} diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 16385417e6..c5d9641da7 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -358,9 +358,6 @@ namespace OpenSim.Framework SetVisualParams(visualParams); } - /// - /// Set avatar height by a calculation based on their visual parameters. - /// public virtual void SetHeight() { // Start with shortest possible female avatar height diff --git a/OpenSim/Framework/Cache.cs b/OpenSim/Framework/Cache.cs index 31cab4a021..79e20fc88e 100644 --- a/OpenSim/Framework/Cache.cs +++ b/OpenSim/Framework/Cache.cs @@ -199,14 +199,7 @@ namespace OpenSim.Framework // public class Cache { - /// - /// Must only be accessed under lock. - /// private List m_Index = new List(); - - /// - /// Must only be accessed under m_Index lock. - /// private Dictionary m_Lookup = new Dictionary(); @@ -327,19 +320,19 @@ namespace OpenSim.Framework { if (m_Lookup.ContainsKey(index)) item = m_Lookup[index]; - - if (item == null) - { - Expire(true); - return null; - } - - item.hits++; - item.lastUsed = DateTime.Now; - - Expire(true); } + if (item == null) + { + Expire(true); + return null; + } + + item.hits++; + item.lastUsed = DateTime.Now; + + Expire(true); + return item; } @@ -392,10 +385,7 @@ namespace OpenSim.Framework // public Object Find(Predicate d) { - CacheItemBase item; - - lock (m_Index) - item = m_Index.Find(d); + CacheItemBase item = m_Index.Find(d); if (item == null) return null; @@ -429,12 +419,12 @@ namespace OpenSim.Framework public virtual void Store(string index, Object data, Type container, Object[] parameters) { + Expire(false); + CacheItemBase item; lock (m_Index) { - Expire(false); - if (m_Index.Contains(new CacheItemBase(index))) { if ((m_Flags & CacheFlags.AllowUpdate) != 0) @@ -460,17 +450,9 @@ namespace OpenSim.Framework m_Index.Add(item); m_Lookup[index] = item; } - item.Store(data); } - /// - /// Expire items as appropriate. - /// - /// - /// Callers must lock m_Index. - /// - /// protected virtual void Expire(bool getting) { if (getting && (m_Strategy == CacheStrategy.Aggressive)) @@ -493,10 +475,12 @@ namespace OpenSim.Framework switch (m_Strategy) { - case CacheStrategy.Aggressive: - if (Count < Size) - return; + case CacheStrategy.Aggressive: + if (Count < Size) + return; + lock (m_Index) + { m_Index.Sort(new SortLRU()); m_Index.Reverse(); @@ -506,7 +490,7 @@ namespace OpenSim.Framework ExpireDelegate doExpire = OnExpire; - if (doExpire != null) + if (doExpire != null) { List candidates = m_Index.GetRange(target, Count - target); @@ -529,34 +513,27 @@ namespace OpenSim.Framework foreach (CacheItemBase item in m_Index) m_Lookup[item.uuid] = item; } - - break; - - default: - break; + } + break; + default: + break; } } public void Invalidate(string uuid) { - lock (m_Index) - { - if (!m_Lookup.ContainsKey(uuid)) - return; + if (!m_Lookup.ContainsKey(uuid)) + return; - CacheItemBase item = m_Lookup[uuid]; - m_Lookup.Remove(uuid); - m_Index.Remove(item); - } + CacheItemBase item = m_Lookup[uuid]; + m_Lookup.Remove(uuid); + m_Index.Remove(item); } public void Clear() { - lock (m_Index) - { - m_Index.Clear(); - m_Lookup.Clear(); - } + m_Index.Clear(); + m_Lookup.Clear(); } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Client/IClientChat.cs b/OpenSim/Framework/Client/IClientChat.cs index 86b1faa8f6..078ea9b668 100644 --- a/OpenSim/Framework/Client/IClientChat.cs +++ b/OpenSim/Framework/Client/IClientChat.cs @@ -33,8 +33,7 @@ namespace OpenSim.Framework.Client { event ChatMessage OnChatFromClient; - void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, - byte audible); + void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, + byte audible); } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Console/ConsoleUtil.cs b/OpenSim/Framework/Console/ConsoleUtil.cs deleted file mode 100644 index 16a63e0ca5..0000000000 --- a/OpenSim/Framework/Console/ConsoleUtil.cs +++ /dev/null @@ -1,228 +0,0 @@ -/* - * 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.Linq; -using System.Reflection; -using log4net; -using OpenMetaverse; - -namespace OpenSim.Framework.Console -{ - public class ConsoleUtil - { - // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - public const int LocalIdNotFound = 0; - - /// - /// Used by modules to display stock co-ordinate help, though possibly this should be under some general section - /// rather than in each help summary. - /// - public const string CoordHelp - = @"Each component of the coord is comma separated. There must be no spaces between the commas. - If you don't care about the z component you can simply omit it. - If you don't care about the x or y components then you can leave them blank (though a comma is still required) - If you want to specify the maxmimum value of a component then you can use ~ instead of a number - If you want to specify the minimum value of a component then you can use -~ instead of a number - e.g. - delete object pos 20,20,20 to 40,40,40 - delete object pos 20,20 to 40,40 - delete object pos ,20,20 to ,40,40 - delete object pos ,,30 to ,,~ - delete object pos ,,-~ to ,,30"; - - public const string MinRawConsoleVectorValue = "-~"; - public const string MaxRawConsoleVectorValue = "~"; - - public const string VectorSeparator = ","; - public static char[] VectorSeparatorChars = VectorSeparator.ToCharArray(); - - /// - /// Check if the given file path exists. - /// - /// If not, warning is printed to the given console. - /// true if the file does not exist, false otherwise. - /// - /// - public static bool CheckFileDoesNotExist(ICommandConsole console, string path) - { - if (File.Exists(path)) - { - console.OutputFormat("File {0} already exists. Please move or remove it.", path); - return false; - } - - return true; - } - - /// - /// Try to parse a console UUID from the console. - /// - /// - /// Will complain to the console if parsing fails. - /// - /// - /// If null then no complaint is printed. - /// - /// - public static bool TryParseConsoleUuid(ICommandConsole console, string rawUuid, out UUID uuid) - { - if (!UUID.TryParse(rawUuid, out uuid)) - { - if (console != null) - console.OutputFormat("{0} is not a valid uuid", rawUuid); - - return false; - } - - return true; - } - - public static bool TryParseConsoleLocalId(ICommandConsole console, string rawLocalId, out uint localId) - { - if (!uint.TryParse(rawLocalId, out localId)) - { - if (console != null) - console.OutputFormat("{0} is not a valid local id", localId); - - return false; - } - - if (localId == 0) - { - if (console != null) - console.OutputFormat("{0} is not a valid local id - it must be greater than 0", localId); - - return false; - } - - return true; - } - - /// - /// Tries to parse the input as either a UUID or a local ID. - /// - /// true if parsing succeeded, false otherwise. - /// - /// - /// - /// - /// Will be set to ConsoleUtil.LocalIdNotFound if parsing result was a UUID or no parse succeeded. - /// - public static bool TryParseConsoleId(ICommandConsole console, string rawId, out UUID uuid, out uint localId) - { - if (TryParseConsoleUuid(null, rawId, out uuid)) - { - localId = LocalIdNotFound; - return true; - } - - if (TryParseConsoleLocalId(null, rawId, out localId)) - { - return true; - } - - if (console != null) - console.OutputFormat("{0} is not a valid UUID or local id", rawId); - - return false; - } - - /// - /// Convert a minimum vector input from the console to an OpenMetaverse.Vector3 - /// - /// /param> - /// - /// - public static bool TryParseConsoleMinVector(string rawConsoleVector, out Vector3 vector) - { - return TryParseConsoleVector(rawConsoleVector, c => float.MinValue.ToString(), out vector); - } - - /// - /// Convert a maximum vector input from the console to an OpenMetaverse.Vector3 - /// - /// /param> - /// - /// - public static bool TryParseConsoleMaxVector(string rawConsoleVector, out Vector3 vector) - { - return TryParseConsoleVector(rawConsoleVector, c => float.MaxValue.ToString(), out vector); - } - - /// - /// Convert a vector input from the console to an OpenMetaverse.Vector3 - /// - /// - /// A string in the form ,, where there is no space between values. - /// Any component can be missing (e.g. ,,40). blankComponentFunc is invoked to replace the blank with a suitable value - /// Also, if the blank component is at the end, then the comma can be missed off entirely (e.g. 40,30 or 40) - /// The strings "~" and "-~" are valid in components. The first substitutes float.MaxValue whilst the second is float.MinValue - /// Other than that, component values must be numeric. - /// - /// - /// - /// - public static bool TryParseConsoleVector( - string rawConsoleVector, Func blankComponentFunc, out Vector3 vector) - { - List components = rawConsoleVector.Split(VectorSeparatorChars).ToList(); - - if (components.Count < 1 || components.Count > 3) - { - vector = Vector3.Zero; - return false; - } - - for (int i = components.Count; i < 3; i++) - components.Add(""); - - List semiDigestedComponents - = components.ConvertAll( - c => - { - if (c == "") - return blankComponentFunc.Invoke(c); - else if (c == MaxRawConsoleVectorValue) - return float.MaxValue.ToString(); - else if (c == MinRawConsoleVectorValue) - return float.MinValue.ToString(); - else - return c; - }); - - string semiDigestedConsoleVector = string.Join(VectorSeparator, semiDigestedComponents.ToArray()); - - // m_log.DebugFormat("[CONSOLE UTIL]: Parsing {0} into OpenMetaverse.Vector3", semiDigestedConsoleVector); - - return Vector3.TryParse(semiDigestedConsoleVector, out vector); - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/Constants.cs b/OpenSim/Framework/Constants.cs index a2eb5ee18e..1b1aaf2bc4 100644 --- a/OpenSim/Framework/Constants.cs +++ b/OpenSim/Framework/Constants.cs @@ -31,7 +31,6 @@ namespace OpenSim.Framework public class Constants { public const uint RegionSize = 256; - public const uint RegionHeight = 4096; public const byte TerrainPatchSize = 16; public const string DefaultTexture = "89556747-24cb-43ed-920b-47caed15465f"; diff --git a/OpenSim/Framework/EstateSettings.cs b/OpenSim/Framework/EstateSettings.cs index e03750bcc5..9020761cad 100644 --- a/OpenSim/Framework/EstateSettings.cs +++ b/OpenSim/Framework/EstateSettings.cs @@ -419,11 +419,11 @@ namespace OpenSim.Framework public void SetFromFlags(ulong regionFlags) { - ResetHomeOnTeleport = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport) == (ulong)OpenMetaverse.RegionFlags.ResetHomeOnTeleport); - BlockDwell = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.BlockDwell) == (ulong)OpenMetaverse.RegionFlags.BlockDwell); - AllowLandmark = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowLandmark) == (ulong)OpenMetaverse.RegionFlags.AllowLandmark); - AllowParcelChanges = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges) == (ulong)OpenMetaverse.RegionFlags.AllowParcelChanges); - AllowSetHome = ((regionFlags & (ulong)OpenMetaverse.RegionFlags.AllowSetHome) == (ulong)OpenMetaverse.RegionFlags.AllowSetHome); + ResetHomeOnTeleport = ((regionFlags & (ulong)RegionFlags.ResetHomeOnTeleport) == (ulong)RegionFlags.ResetHomeOnTeleport); + BlockDwell = ((regionFlags & (ulong)RegionFlags.BlockDwell) == (ulong)RegionFlags.BlockDwell); + AllowLandmark = ((regionFlags & (ulong)RegionFlags.AllowLandmark) == (ulong)RegionFlags.AllowLandmark); + AllowParcelChanges = ((regionFlags & (ulong)RegionFlags.AllowParcelChanges) == (ulong)RegionFlags.AllowParcelChanges); + AllowSetHome = ((regionFlags & (ulong)RegionFlags.AllowSetHome) == (ulong)RegionFlags.AllowSetHome); } public bool GroupAccess(UUID groupID) diff --git a/OpenSim/Framework/GridInstantMessage.cs b/OpenSim/Framework/GridInstantMessage.cs index 6ae0488fc2..a6bf6e3c32 100644 --- a/OpenSim/Framework/GridInstantMessage.cs +++ b/OpenSim/Framework/GridInstantMessage.cs @@ -44,6 +44,7 @@ namespace OpenSim.Framework public Vector3 Position; public byte[] binaryBucket; + public uint ParentEstateID; public Guid RegionID; public uint timestamp; @@ -57,7 +58,7 @@ namespace OpenSim.Framework string _fromAgentName, UUID _toAgentID, byte _dialog, bool _fromGroup, string _message, UUID _imSessionID, bool _offline, Vector3 _position, - byte[] _binaryBucket, bool addTimestamp) + byte[] _binaryBucket) { fromAgentID = _fromAgentID.Guid; fromAgentName = _fromAgentName; @@ -78,9 +79,7 @@ namespace OpenSim.Framework ParentEstateID = scene.RegionInfo.EstateSettings.ParentEstateID; RegionID = scene.RegionInfo.RegionSettings.RegionUUID.Guid; } - - if (addTimestamp) - timestamp = (uint)Util.UnixTimeSinceEpoch(); + timestamp = (uint)Util.UnixTimeSinceEpoch(); } public GridInstantMessage(IScene scene, UUID _fromAgentID, @@ -88,7 +87,7 @@ namespace OpenSim.Framework string _message, bool _offline, Vector3 _position) : this(scene, _fromAgentID, _fromAgentName, _toAgentID, _dialog, false, _message, - _fromAgentID ^ _toAgentID, _offline, _position, new byte[0], true) + _fromAgentID ^ _toAgentID, _offline, _position, new byte[0]) { } } diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1c6685aec6..e31c7f6d23 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -815,23 +815,8 @@ namespace OpenSim.Framework event Action OnRegionHandShakeReply; event GenericCall1 OnRequestWearables; event Action OnCompleteMovementToRegion; - - /// - /// Called when an AgentUpdate message is received and before OnAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates. - /// event UpdateAgent OnPreAgentUpdate; - - /// - /// Called when an AgentUpdate message is received and after OnPreAgentUpdate. - /// - /// - /// Listeners must not retain a reference to AgentUpdateArgs since this object may be reused for subsequent AgentUpdates. - /// event UpdateAgent OnAgentUpdate; - event AgentRequestSit OnAgentRequestSit; event AgentSit OnAgentSit; event AvatarPickerRequest OnAvatarPickerRequest; @@ -1061,21 +1046,8 @@ namespace OpenSim.Framework void InPacket(object NewPack); void ProcessInPacket(Packet NewPack); - - /// - /// Close this client - /// void Close(); - - /// - /// Close this client - /// - /// - /// If true, attempts the close without checking active status. You do not want to try this except as a last - /// ditch attempt where Active == false but the ScenePresence still exists. - /// - void Close(bool sendStop, bool force); - + void Close(bool sendStop); void Kick(string message); /// @@ -1112,20 +1084,8 @@ namespace OpenSim.Framework void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); - /// - /// Send chat to the viewer. - /// - /// - /// - /// - /// - /// - /// - /// - /// - void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, - byte audible); + void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, + byte audible); void SendInstantMessage(GridInstantMessage im); diff --git a/OpenSim/Framework/InventoryFolderBase.cs b/OpenSim/Framework/InventoryFolderBase.cs index b3457a65b9..a12183c535 100644 --- a/OpenSim/Framework/InventoryFolderBase.cs +++ b/OpenSim/Framework/InventoryFolderBase.cs @@ -73,27 +73,33 @@ namespace OpenSim.Framework { } - public InventoryFolderBase(UUID id) : this() + public InventoryFolderBase(UUID id) { ID = id; } - public InventoryFolderBase(UUID id, UUID owner) : this(id) + public InventoryFolderBase(UUID id, UUID owner) { + ID = id; Owner = owner; } - public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) : this(id, owner) + public InventoryFolderBase(UUID id, string name, UUID owner, UUID parent) { + ID = id; Name = name; + Owner = owner; ParentID = parent; } - public InventoryFolderBase( - UUID id, string name, UUID owner, short type, UUID parent, ushort version) : this(id, name, owner, parent) + public InventoryFolderBase(UUID id, string name, UUID owner, short type, UUID parent, ushort version) { + ID = id; + Name = name; + Owner = owner; Type = type; + ParentID = parent; Version = version; } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs index 4dffd3f22d..dcaa46d960 100644 --- a/OpenSim/Framework/LandData.cs +++ b/OpenSim/Framework/LandData.cs @@ -49,8 +49,8 @@ namespace OpenSim.Framework // use only one serializer to give the runtime a chance to // optimize it (it won't do that if you use a new instance // every time) - private static XmlSerializer serializer = new XmlSerializer(typeof(LandData)); - + private static XmlSerializer serializer = new XmlSerializer(typeof (LandData)); + private Vector3 _AABBMax = new Vector3(); private Vector3 _AABBMin = new Vector3(); private int _area = 0; @@ -65,11 +65,11 @@ namespace OpenSim.Framework private byte[] _bitmap = new byte[512]; private string _description = String.Empty; - private uint _flags = (uint)ParcelFlags.AllowFly | (uint)ParcelFlags.AllowLandmark | - (uint)ParcelFlags.AllowAPrimitiveEntry | - (uint)ParcelFlags.AllowDeedToGroup | - (uint)ParcelFlags.CreateObjects | (uint)ParcelFlags.AllowOtherScripts | - (uint)ParcelFlags.AllowVoiceChat; + private uint _flags = (uint) ParcelFlags.AllowFly | (uint) ParcelFlags.AllowLandmark | + (uint) ParcelFlags.AllowAPrimitiveEntry | + (uint) ParcelFlags.AllowDeedToGroup | + (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts | + (uint) ParcelFlags.SoundLocal | (uint) ParcelFlags.AllowVoiceChat; private byte _landingType = 0; private string _name = "Your Parcel"; @@ -97,36 +97,16 @@ namespace OpenSim.Framework private bool _mediaLoop = false; private bool _obscureMusic = false; private bool _obscureMedia = false; - private float _dwell = 0; - - /// - /// Traffic count of parcel - /// - [XmlIgnore] - public float Dwell - { - get - { - return _dwell; - } - set - { - _dwell = value; - } - } /// /// Whether to obscure parcel media URL /// [XmlIgnore] - public bool ObscureMedia - { - get - { + public bool ObscureMedia { + get { return _obscureMedia; } - set - { + set { _obscureMedia = value; } } @@ -135,14 +115,11 @@ namespace OpenSim.Framework /// Whether to obscure parcel music URL /// [XmlIgnore] - public bool ObscureMusic - { - get - { + public bool ObscureMusic { + get { return _obscureMusic; } - set - { + set { _obscureMusic = value; } } @@ -151,14 +128,11 @@ namespace OpenSim.Framework /// Whether to loop parcel media /// [XmlIgnore] - public bool MediaLoop - { - get - { + public bool MediaLoop { + get { return _mediaLoop; } - set - { + set { _mediaLoop = value; } } @@ -167,14 +141,11 @@ namespace OpenSim.Framework /// Height of parcel media render /// [XmlIgnore] - public int MediaHeight - { - get - { + public int MediaHeight { + get { return _mediaHeight; } - set - { + set { _mediaHeight = value; } } @@ -183,14 +154,11 @@ namespace OpenSim.Framework /// Width of parcel media render /// [XmlIgnore] - public int MediaWidth - { - get - { + public int MediaWidth { + get { return _mediaWidth; } - set - { + set { _mediaWidth = value; } } @@ -199,14 +167,11 @@ namespace OpenSim.Framework /// Upper corner of the AABB for the parcel /// [XmlIgnore] - public Vector3 AABBMax - { - get - { + public Vector3 AABBMax { + get { return _AABBMax; } - set - { + set { _AABBMax = value; } } @@ -214,14 +179,11 @@ namespace OpenSim.Framework /// Lower corner of the AABB for the parcel /// [XmlIgnore] - public Vector3 AABBMin - { - get - { + public Vector3 AABBMin { + get { return _AABBMin; } - set - { + set { _AABBMin = value; } } @@ -229,14 +191,11 @@ namespace OpenSim.Framework /// /// Area in meters^2 the parcel contains /// - public int Area - { - get - { + public int Area { + get { return _area; } - set - { + set { _area = value; } } @@ -244,14 +203,11 @@ namespace OpenSim.Framework /// /// ID of auction (3rd Party Integration) when parcel is being auctioned /// - public uint AuctionID - { - get - { + public uint AuctionID { + get { return _auctionID; } - set - { + set { _auctionID = value; } } @@ -259,14 +215,11 @@ namespace OpenSim.Framework /// /// UUID of authorized buyer of parcel. This is UUID.Zero if anyone can buy it. /// - public UUID AuthBuyerID - { - get - { + public UUID AuthBuyerID { + get { return _authBuyerID; } - set - { + set { _authBuyerID = value; } } @@ -274,14 +227,11 @@ namespace OpenSim.Framework /// /// Category of parcel. Used for classifying the parcel in classified listings /// - public ParcelCategory Category - { - get - { + public ParcelCategory Category { + get { return _category; } - set - { + set { _category = value; } } @@ -289,14 +239,11 @@ namespace OpenSim.Framework /// /// Date that the current owner purchased or claimed the parcel /// - public int ClaimDate - { - get - { + public int ClaimDate { + get { return _claimDate; } - set - { + set { _claimDate = value; } } @@ -304,14 +251,11 @@ namespace OpenSim.Framework /// /// The last price that the parcel was sold at /// - public int ClaimPrice - { - get - { + public int ClaimPrice { + get { return _claimPrice; } - set - { + set { _claimPrice = value; } } @@ -319,14 +263,11 @@ namespace OpenSim.Framework /// /// Global ID for the parcel. (3rd Party Integration) /// - public UUID GlobalID - { - get - { + public UUID GlobalID { + get { return _globalID; } - set - { + set { _globalID = value; } } @@ -334,14 +275,11 @@ namespace OpenSim.Framework /// /// Unique ID of the Group that owns /// - public UUID GroupID - { - get - { + public UUID GroupID { + get { return _groupID; } - set - { + set { _groupID = value; } } @@ -349,14 +287,11 @@ namespace OpenSim.Framework /// /// Returns true if the Land Parcel is owned by a group /// - public bool IsGroupOwned - { - get - { + public bool IsGroupOwned { + get { return _isGroupOwned; } - set - { + set { _isGroupOwned = value; } } @@ -364,14 +299,11 @@ namespace OpenSim.Framework /// /// jp2 data for the image representative of the parcel in the parcel dialog /// - public byte[] Bitmap - { - get - { + public byte[] Bitmap { + get { return _bitmap; } - set - { + set { _bitmap = value; } } @@ -379,14 +311,11 @@ namespace OpenSim.Framework /// /// Parcel Description /// - public string Description - { - get - { + public string Description { + get { return _description; } - set - { + set { _description = value; } } @@ -394,14 +323,11 @@ namespace OpenSim.Framework /// /// Parcel settings. Access flags, Fly, NoPush, Voice, Scripts allowed, etc. ParcelFlags /// - public uint Flags - { - get - { + public uint Flags { + get { return _flags; } - set - { + set { _flags = value; } } @@ -410,14 +336,11 @@ namespace OpenSim.Framework /// Determines if people are able to teleport where they please on the parcel or if they /// get constrainted to a specific point on teleport within the parcel /// - public byte LandingType - { - get - { + public byte LandingType { + get { return _landingType; } - set - { + set { _landingType = value; } } @@ -425,14 +348,11 @@ namespace OpenSim.Framework /// /// Parcel Name /// - public string Name - { - get - { + public string Name { + get { return _name; } - set - { + set { _name = value; } } @@ -440,14 +360,11 @@ namespace OpenSim.Framework /// /// Status of Parcel, Leased, Abandoned, For Sale /// - public ParcelStatus Status - { - get - { + public ParcelStatus Status { + get { return _status; } - set - { + set { _status = value; } } @@ -455,14 +372,11 @@ namespace OpenSim.Framework /// /// Internal ID of the parcel. Sometimes the client will try to use this value /// - public int LocalID - { - get - { + public int LocalID { + get { return _localID; } - set - { + set { _localID = value; } } @@ -470,14 +384,11 @@ namespace OpenSim.Framework /// /// Determines if we scale the media based on the surface it's on /// - public byte MediaAutoScale - { - get - { + public byte MediaAutoScale { + get { return _mediaAutoScale; } - set - { + set { _mediaAutoScale = value; } } @@ -485,14 +396,11 @@ namespace OpenSim.Framework /// /// Texture Guid to replace with the output of the media stream /// - public UUID MediaID - { - get - { + public UUID MediaID { + get { return _mediaID; } - set - { + set { _mediaID = value; } } @@ -500,14 +408,11 @@ namespace OpenSim.Framework /// /// URL to the media file to display /// - public string MediaURL - { - get - { + public string MediaURL { + get { return _mediaURL; } - set - { + set { _mediaURL = value; } } @@ -527,14 +432,11 @@ namespace OpenSim.Framework /// /// URL to the shoutcast music stream to play on the parcel /// - public string MusicURL - { - get - { + public string MusicURL { + get { return _musicURL; } - set - { + set { _musicURL = value; } } @@ -543,14 +445,11 @@ namespace OpenSim.Framework /// Owner Avatar or Group of the parcel. Naturally, all land masses must be /// owned by someone /// - public UUID OwnerID - { - get - { + public UUID OwnerID { + get { return _ownerID; } - set - { + set { _ownerID = value; } } @@ -558,14 +457,11 @@ namespace OpenSim.Framework /// /// List of access data for the parcel. User data, some bitflags, and a time /// - public List ParcelAccessList - { - get - { + public List ParcelAccessList { + get { return _parcelAccessList; } - set - { + set { _parcelAccessList = value; } } @@ -573,14 +469,11 @@ namespace OpenSim.Framework /// /// How long in hours a Pass to the parcel is given /// - public float PassHours - { - get - { + public float PassHours { + get { return _passHours; } - set - { + set { _passHours = value; } } @@ -588,14 +481,11 @@ namespace OpenSim.Framework /// /// Price to purchase a Pass to a restricted parcel /// - public int PassPrice - { - get - { + public int PassPrice { + get { return _passPrice; } - set - { + set { _passPrice = value; } } @@ -603,14 +493,11 @@ namespace OpenSim.Framework /// /// When the parcel is being sold, this is the price to purchase the parcel /// - public int SalePrice - { - get - { + public int SalePrice { + get { return _salePrice; } - set - { + set { _salePrice = value; } } @@ -619,14 +506,11 @@ namespace OpenSim.Framework /// Number of meters^2 in the Simulator /// [XmlIgnore] - public int SimwideArea - { - get - { + public int SimwideArea { + get { return _simwideArea; } - set - { + set { _simwideArea = value; } } @@ -635,14 +519,11 @@ namespace OpenSim.Framework /// Number of SceneObjectPart in the Simulator /// [XmlIgnore] - public int SimwidePrims - { - get - { + public int SimwidePrims { + get { return _simwidePrims; } - set - { + set { _simwidePrims = value; } } @@ -650,14 +531,11 @@ namespace OpenSim.Framework /// /// ID of the snapshot used in the client parcel dialog of the parcel /// - public UUID SnapshotID - { - get - { + public UUID SnapshotID { + get { return _snapshotID; } - set - { + set { _snapshotID = value; } } @@ -666,14 +544,11 @@ namespace OpenSim.Framework /// When teleporting is restricted to a certain point, this is the location /// that the user will be redirected to /// - public Vector3 UserLocation - { - get - { + public Vector3 UserLocation { + get { return _userLocation; } - set - { + set { _userLocation = value; } } @@ -682,14 +557,11 @@ namespace OpenSim.Framework /// When teleporting is restricted to a certain point, this is the rotation /// that the user will be positioned /// - public Vector3 UserLookAt - { - get - { + public Vector3 UserLookAt { + get { return _userLookAt; } - set - { + set { _userLookAt = value; } } @@ -698,14 +570,11 @@ namespace OpenSim.Framework /// Autoreturn number of minutes to return SceneObjectGroup that are owned by someone who doesn't own /// the parcel and isn't set to the same 'group' as the parcel. /// - public int OtherCleanTime - { - get - { + public int OtherCleanTime { + get { return _otherCleanTime; } - set - { + set { _otherCleanTime = value; } } @@ -713,14 +582,11 @@ namespace OpenSim.Framework /// /// parcel media description /// - public string MediaDescription - { - get - { + public string MediaDescription { + get { return _mediaDescription; } - set - { + set { _mediaDescription = value; } } @@ -756,7 +622,7 @@ namespace OpenSim.Framework landData._mediaURL = _mediaURL; landData._musicURL = _musicURL; landData._ownerID = _ownerID; - landData._bitmap = (byte[])_bitmap.Clone(); + landData._bitmap = (byte[]) _bitmap.Clone(); landData._description = _description; landData._flags = _flags; landData._name = _name; @@ -777,7 +643,6 @@ namespace OpenSim.Framework landData._obscureMedia = _obscureMedia; landData._simwideArea = _simwideArea; landData._simwidePrims = _simwidePrims; - landData._dwell = _dwell; landData._parcelAccessList.Clear(); foreach (LandAccessEntry entry in _parcelAccessList) diff --git a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs index 446e3c0697..9ee087694b 100644 --- a/OpenSim/Framework/Monitoring/BaseStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/BaseStatsCollector.cs @@ -43,32 +43,27 @@ namespace OpenSim.Framework.Monitoring StringBuilder sb = new StringBuilder(Environment.NewLine); sb.Append("MEMORY STATISTICS"); sb.Append(Environment.NewLine); - sb.AppendFormat( + sb.Append( + string.Format( "Allocated to OpenSim objects: {0} MB\n", - Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0)); - - sb.AppendFormat( - "OpenSim last object memory churn : {0} MB/s\n", - Math.Round((MemoryWatchdog.LastMemoryChurn * 1000) / 1024.0 / 1024, 3)); - - sb.AppendFormat( - "OpenSim average object memory churn : {0} MB/s\n", - Math.Round((MemoryWatchdog.AverageMemoryChurn * 1000) / 1024.0 / 1024, 3)); + Math.Round(GC.GetTotalMemory(false) / 1024.0 / 1024.0))); Process myprocess = Process.GetCurrentProcess(); if (!myprocess.HasExited) { myprocess.Refresh(); - sb.AppendFormat( + sb.Append( + string.Format( "Process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", Math.Round(Process.GetCurrentProcess().WorkingSet64 / 1024.0 / 1024.0), Math.Round(Process.GetCurrentProcess().PagedMemorySize64 / 1024.0 / 1024.0), - Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0)); - sb.AppendFormat( + Math.Round(Process.GetCurrentProcess().VirtualMemorySize64 / 1024.0 / 1024.0))); + sb.Append( + string.Format( "Peak process memory: Physical {0} MB \t Paged {1} MB \t Virtual {2} MB\n", Math.Round(Process.GetCurrentProcess().PeakWorkingSet64 / 1024.0 / 1024.0), Math.Round(Process.GetCurrentProcess().PeakPagedMemorySize64 / 1024.0 / 1024.0), - Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0)); + Math.Round(Process.GetCurrentProcess().PeakVirtualMemorySize64 / 1024.0 / 1024.0))); } else sb.Append("Process reported as Exited \n"); diff --git a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs index c6010cd092..a23cf1fea8 100644 --- a/OpenSim/Framework/Monitoring/MemoryWatchdog.cs +++ b/OpenSim/Framework/Monitoring/MemoryWatchdog.cs @@ -60,21 +60,13 @@ namespace OpenSim.Framework.Monitoring private static bool m_enabled; /// - /// Last memory churn in bytes per millisecond. + /// Average memory churn in bytes per millisecond. /// public static double AverageMemoryChurn { get { if (m_samples.Count > 0) return m_samples.Average(); else return 0; } } - /// - /// Average memory churn in bytes per millisecond. - /// - public static double LastMemoryChurn - { - get { if (m_samples.Count > 0) return m_samples.Last(); else return 0; } - } - /// /// Maximum number of statistical samples. /// diff --git a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs index aa862027b8..cdd7cc711e 100644 --- a/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/SimExtraStatsCollector.cs @@ -355,25 +355,10 @@ Asset service request failures: {3}" + Environment.NewLine, sb.Append(Environment.NewLine); sb.Append( string.Format( - "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}\n\n", + "{0,6:0} {1,6:0} {2,6:0} {3,6:0} {4,6:0} {5,6:0.0} {6,6:0.0} {7,6:0.0} {8,6:0.0} {9,6:0.0} {10,6:0.0}", inPacketsPerSecond, outPacketsPerSecond, pendingDownloads, pendingUploads, unackedBytes, totalFrameTime, netFrameTime, physicsFrameTime, otherFrameTime, agentFrameTime, imageFrameTime)); - - Dictionary> sceneStats; - - if (StatsManager.TryGetStats("scene", out sceneStats)) - { - foreach (KeyValuePair> kvp in sceneStats) - { - foreach (Stat stat in kvp.Value.Values) - { - if (stat.Verbosity == StatVerbosity.Info) - { - sb.AppendFormat("{0} ({1}): {2}{3}\n", stat.Name, stat.Container, stat.Value, stat.UnitName); - } - } - } - } + sb.Append(Environment.NewLine); /* sb.Append(Environment.NewLine); diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index 4844336e31..d78fa6a1f0 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -25,9 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; -using System.Collections.Generic; - namespace OpenSim.Framework.Monitoring { /// @@ -35,24 +32,6 @@ namespace OpenSim.Framework.Monitoring /// public class StatsManager { - // Subcommand used to list other stats. - public const string AllSubCommand = "all"; - - // Subcommand used to list other stats. - public const string ListSubCommand = "list"; - - // All subcommands - public static HashSet SubCommands = new HashSet { AllSubCommand, ListSubCommand }; - - /// - /// Registered stats categorized by category/container/shortname - /// - /// - /// Do not add or remove directly from this dictionary. - /// - public static Dictionary>> RegisteredStats - = new Dictionary>>(); - private static AssetStatsCollector assetStats; private static UserStatsCollector userStats; private static SimExtraStatsCollector simExtraStats = new SimExtraStatsCollector(); @@ -61,75 +40,6 @@ namespace OpenSim.Framework.Monitoring public static UserStatsCollector UserStats { get { return userStats; } } public static SimExtraStatsCollector SimExtraStats { get { return simExtraStats; } } - public static void RegisterConsoleCommands(ICommandConsole console) - { - console.Commands.AddCommand( - "General", - false, - "show stats", - "show stats [list|all|]", - "Show statistical information for this server", - "If no final argument is specified then legacy statistics information is currently shown.\n" - + "If list is specified then statistic categories are shown.\n" - + "If all is specified then all registered statistics are shown.\n" - + "If a category name is specified then only statistics from that category are shown.\n" - + "THIS STATS FACILITY IS EXPERIMENTAL AND DOES NOT YET CONTAIN ALL STATS", - HandleShowStatsCommand); - } - - public static void HandleShowStatsCommand(string module, string[] cmd) - { - ICommandConsole con = MainConsole.Instance; - - if (cmd.Length > 2) - { - var categoryName = cmd[2]; - - if (categoryName == AllSubCommand) - { - foreach (var category in RegisteredStats.Values) - { - OutputCategoryStatsToConsole(con, category); - } - } - else if (categoryName == ListSubCommand) - { - con.Output("Statistic categories available are:"); - foreach (string category in RegisteredStats.Keys) - con.OutputFormat(" {0}", category); - } - else - { - Dictionary> category; - if (!RegisteredStats.TryGetValue(categoryName, out category)) - { - con.OutputFormat("No such category as {0}", categoryName); - } - else - { - OutputCategoryStatsToConsole(con, category); - } - } - } - else - { - // Legacy - con.Output(SimExtraStats.Report()); - } - } - - private static void OutputCategoryStatsToConsole( - ICommandConsole con, Dictionary> category) - { - foreach (var container in category.Values) - { - foreach (Stat stat in container.Values) - { - con.Output(stat.ToConsoleString()); - } - } - } - /// /// Start collecting statistics related to assets. /// Should only be called once. @@ -151,275 +61,5 @@ namespace OpenSim.Framework.Monitoring return userStats; } - - /// - /// Registers a statistic. - /// - /// - /// - public static bool RegisterStat(Stat stat) - { - Dictionary> category = null, newCategory; - Dictionary container = null, newContainer; - - lock (RegisteredStats) - { - // Stat name is not unique across category/container/shortname key. - // XXX: For now just return false. This is to avoid problems in regression tests where all tests - // in a class are run in the same instance of the VM. - if (TryGetStat(stat, out category, out container)) - return false; - - // We take a copy-on-write approach here of replacing dictionaries when keys are added or removed. - // This means that we don't need to lock or copy them on iteration, which will be a much more - // common operation after startup. - if (container != null) - newContainer = new Dictionary(container); - else - newContainer = new Dictionary(); - - if (category != null) - newCategory = new Dictionary>(category); - else - newCategory = new Dictionary>(); - - newContainer[stat.ShortName] = stat; - newCategory[stat.Container] = newContainer; - RegisteredStats[stat.Category] = newCategory; - } - - return true; - } - - /// - /// Deregister a statistic - /// > - /// - /// > category = null, newCategory; - Dictionary container = null, newContainer; - - lock (RegisteredStats) - { - if (!TryGetStat(stat, out category, out container)) - return false; - - newContainer = new Dictionary(container); - newContainer.Remove(stat.ShortName); - - newCategory = new Dictionary>(category); - newCategory.Remove(stat.Container); - - newCategory[stat.Container] = newContainer; - RegisteredStats[stat.Category] = newCategory; - - return true; - } - } - - public static bool TryGetStats(string category, out Dictionary> stats) - { - return RegisteredStats.TryGetValue(category, out stats); - } - - public static bool TryGetStat( - Stat stat, - out Dictionary> category, - out Dictionary container) - { - category = null; - container = null; - - lock (RegisteredStats) - { - if (RegisteredStats.TryGetValue(stat.Category, out category)) - { - if (category.TryGetValue(stat.Container, out container)) - { - if (container.ContainsKey(stat.ShortName)) - return true; - } - } - } - - return false; - } - } - - /// - /// Stat type. - /// - /// - /// A push stat is one which is continually updated and so it's value can simply by read. - /// A pull stat is one where reading the value triggers a collection method - the stat is not continually updated. - /// - public enum StatType - { - Push, - Pull - } - - /// - /// Verbosity of stat. - /// - /// - /// Info will always be displayed. - /// - public enum StatVerbosity - { - Debug, - Info - } - - /// - /// Holds individual static details - /// - public class Stat - { - /// - /// Category of this stat (e.g. cache, scene, etc). - /// - public string Category { get; private set; } - - /// - /// Containing name for this stat. - /// FIXME: In the case of a scene, this is currently the scene name (though this leaves - /// us with a to-be-resolved problem of non-unique region names). - /// - /// - /// The container. - /// - public string Container { get; private set; } - - public StatType StatType { get; private set; } - - /// - /// Action used to update this stat when the value is requested if it's a pull type. - /// - public Action PullAction { get; private set; } - - public StatVerbosity Verbosity { get; private set; } - public string ShortName { get; private set; } - public string Name { get; private set; } - public string Description { get; private set; } - public virtual string UnitName { get; private set; } - - public virtual double Value - { - get - { - // Asking for an update here means that the updater cannot access this value without infinite recursion. - // XXX: A slightly messy but simple solution may be to flick a flag so we can tell if this is being - // called by the pull action and just return the value. - if (StatType == StatType.Pull) - PullAction(this); - - return m_value; - } - - set - { - m_value = value; - } - } - - private double m_value; - - /// - /// Constructor - /// - /// Short name for the stat. Must not contain spaces. e.g. "LongFrames" - /// Human readable name for the stat. e.g. "Long frames" - /// Description of stat - /// - /// Unit name for the stat. Should be preceeded by a space if the unit name isn't normally appeneded immediately to the value. - /// e.g. " frames" - /// - /// Category under which this stat should appear, e.g. "scene". Do not capitalize. - /// Entity to which this stat relates. e.g. scene name if this is a per scene stat. - /// Push or pull - /// Pull stats need an action to update the stat on request. Push stats should set null here. - /// Verbosity of stat. Controls whether it will appear in short stat display or only full display. - public Stat( - string shortName, - string name, - string description, - string unitName, - string category, - string container, - StatType type, - Action pullAction, - StatVerbosity verbosity) - { - if (StatsManager.SubCommands.Contains(category)) - throw new Exception( - string.Format("Stat cannot be in category '{0}' since this is reserved for a subcommand", category)); - - ShortName = shortName; - Name = name; - Description = description; - UnitName = unitName; - Category = category; - Container = container; - StatType = type; - - if (StatType == StatType.Push && pullAction != null) - throw new Exception("A push stat cannot have a pull action"); - else - PullAction = pullAction; - - Verbosity = verbosity; - } - - public virtual string ToConsoleString() - { - return string.Format( - "{0}.{1}.{2} : {3}{4}", Category, Container, ShortName, Value, UnitName); - } - } - - public class PercentageStat : Stat - { - public int Antecedent { get; set; } - public int Consequent { get; set; } - - public override double Value - { - get - { - int c = Consequent; - - // Avoid any chance of a multi-threaded divide-by-zero - if (c == 0) - return 0; - - return (double)Antecedent / c * 100; - } - - set - { - throw new Exception("Cannot set value on a PercentageStat"); - } - } - - public PercentageStat( - string shortName, - string name, - string description, - string category, - string container, - StatType type, - Action pullAction, - StatVerbosity verbosity) - : base(shortName, name, description, "%", category, container, type, pullAction, verbosity) {} - - public override string ToConsoleString() - { - return string.Format( - "{0}.{1}.{2} : {3:0.##}{4} ({5}/{6})", - Category, Container, ShortName, Value, UnitName, Antecedent, Consequent); - } } } \ No newline at end of file diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index 28d6d5cce5..b709baa3c7 100644 --- a/OpenSim/Framework/Monitoring/Watchdog.cs +++ b/OpenSim/Framework/Monitoring/Watchdog.cs @@ -89,17 +89,6 @@ namespace OpenSim.Framework.Monitoring FirstTick = Environment.TickCount & Int32.MaxValue; LastTick = FirstTick; } - - public ThreadWatchdogInfo(ThreadWatchdogInfo previousTwi) - { - Thread = previousTwi.Thread; - FirstTick = previousTwi.FirstTick; - LastTick = previousTwi.LastTick; - Timeout = previousTwi.Timeout; - IsTimedOut = previousTwi.IsTimedOut; - AlarmIfTimeout = previousTwi.AlarmIfTimeout; - AlarmMethod = previousTwi.AlarmMethod; - } } /// @@ -231,25 +220,7 @@ namespace OpenSim.Framework.Monitoring private static bool RemoveThread(int threadID) { lock (m_threads) - { - ThreadWatchdogInfo twi; - if (m_threads.TryGetValue(threadID, out twi)) - { - m_log.DebugFormat( - "[WATCHDOG]: Removing thread {0}, ID {1}", twi.Thread.Name, twi.Thread.ManagedThreadId); - - m_threads.Remove(threadID); - - return true; - } - else - { - m_log.WarnFormat( - "[WATCHDOG]: Requested to remove thread with ID {0} but this is not being monitored", threadID); - - return false; - } - } + return m_threads.Remove(threadID); } public static bool AbortThread(int threadID) @@ -364,9 +335,7 @@ namespace OpenSim.Framework.Monitoring if (callbackInfos == null) callbackInfos = new List(); - // Send a copy of the watchdog info to prevent race conditions where the watchdog - // thread updates the monitoring info after an alarm has been sent out. - callbackInfos.Add(new ThreadWatchdogInfo(threadInfo)); + callbackInfos.Add(threadInfo); } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs b/OpenSim/Framework/PacketPool.cs similarity index 71% rename from OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs rename to OpenSim/Framework/PacketPool.cs index 9f22fb48ec..41d17c54f2 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/PacketPool.cs +++ b/OpenSim/Framework/PacketPool.cs @@ -31,10 +31,10 @@ using System.Reflection; using OpenMetaverse; using OpenMetaverse.Packets; using log4net; -using OpenSim.Framework.Monitoring; -namespace OpenSim.Region.ClientStack.LindenUDP +namespace OpenSim.Framework { + public sealed class PacketPool { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -44,32 +44,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool packetPoolEnabled = true; private bool dataBlockPoolEnabled = true; - private PercentageStat m_packetsReusedStat = new PercentageStat( - "PacketsReused", - "Packets reused", - "Number of packets reused out of all requests to the packet pool", - "clientstack", - "packetpool", - StatType.Push, - null, - StatVerbosity.Debug); - - private PercentageStat m_blocksReusedStat = new PercentageStat( - "PacketDataBlocksReused", - "Packet data blocks reused", - "Number of data blocks reused out of all requests to the packet pool", - "clientstack", - "packetpool", - StatType.Push, - null, - StatVerbosity.Debug); - - /// - /// Pool of packets available for reuse. - /// private readonly Dictionary> pool = new Dictionary>(); - private static Dictionary> DataBlocks = new Dictionary>(); + private static Dictionary> DataBlocks = + new Dictionary>(); + + static PacketPool() + { + } public static PacketPool Instance { @@ -88,45 +70,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP get { return dataBlockPoolEnabled; } } - private PacketPool() - { - StatsManager.RegisterStat(m_packetsReusedStat); - StatsManager.RegisterStat(m_blocksReusedStat); - - StatsManager.RegisterStat( - new Stat( - "PacketsPoolCount", - "Objects within the packet pool", - "The number of objects currently stored within the packet pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => { lock (pool) { stat.Value = pool.Count; } }, - StatVerbosity.Debug)); - - StatsManager.RegisterStat( - new Stat( - "PacketDataBlocksPoolCount", - "Objects within the packet data block pool", - "The number of objects currently stored within the packet data block pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => { lock (DataBlocks) { stat.Value = DataBlocks.Count; } }, - StatVerbosity.Debug)); - } - - /// - /// Gets a packet of the given type. - /// - /// - /// Guaranteed to always return a packet, whether from the pool or newly constructed. public Packet GetPacket(PacketType type) { - m_packetsReusedStat.Consequent++; - Packet packet; if (!packetPoolEnabled) @@ -136,19 +81,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (!pool.ContainsKey(type) || pool[type] == null || (pool[type]).Count == 0) { -// m_log.DebugFormat("[PACKETPOOL]: Building {0} packet", type); - // Creating a new packet if we cannot reuse an old package packet = Packet.BuildPacket(type); } else { -// m_log.DebugFormat("[PACKETPOOL]: Pulling {0} packet", type); - // Recycle old packages - m_packetsReusedStat.Antecedent++; - - packet = pool[type].Pop(); + packet = (pool[type]).Pop(); } } @@ -197,7 +136,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketType type = GetType(bytes); -// Array.Clear(zeroBuffer, 0, zeroBuffer.Length); + Array.Clear(zeroBuffer, 0, zeroBuffer.Length); int i = 0; Packet packet = GetPacket(type); @@ -244,7 +183,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP switch (packet.Type) { // List pooling packets here - case PacketType.AgentUpdate: case PacketType.PacketAck: case PacketType.ObjectUpdate: case PacketType.ImprovedTerseObjectUpdate: @@ -259,9 +197,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if ((pool[type]).Count < 50) { -// m_log.DebugFormat("[PACKETPOOL]: Pushing {0} packet", type); - - pool[type].Push(packet); + (pool[type]).Push(packet); } } break; @@ -273,21 +209,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public T GetDataBlock() where T: new() + public static T GetDataBlock() where T: new() { lock (DataBlocks) { - m_blocksReusedStat.Consequent++; - Stack s; if (DataBlocks.TryGetValue(typeof(T), out s)) { if (s.Count > 0) - { - m_blocksReusedStat.Antecedent++; return (T)s.Pop(); - } } else { @@ -298,7 +229,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } - public void ReturnDataBlock(T block) where T: new() + public static void ReturnDataBlock(T block) where T: new() { if (block == null) return; @@ -313,4 +244,4 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Pool.cs b/OpenSim/Framework/Pool.cs deleted file mode 100644 index 5484f5c2d5..0000000000 --- a/OpenSim/Framework/Pool.cs +++ /dev/null @@ -1,91 +0,0 @@ -/* - * 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; - -namespace OpenSim.Framework -{ - /// - /// Naive pool implementation. - /// - /// - /// Currently assumes that objects are in a useable state when returned. - /// - public class Pool - { - /// - /// Number of objects in the pool. - /// - public int Count - { - get - { - lock (m_pool) - return m_pool.Count; - } - } - - private Stack m_pool; - - /// - /// Maximum pool size. Beyond this, any returned objects are not pooled. - /// - private int m_maxPoolSize; - - private Func m_createFunction; - - public Pool(Func createFunction, int maxSize) - { - m_maxPoolSize = maxSize; - m_createFunction = createFunction; - m_pool = new Stack(m_maxPoolSize); - } - - public T GetObject() - { - lock (m_pool) - { - if (m_pool.Count > 0) - return m_pool.Pop(); - else - return m_createFunction(); - } - } - - public void ReturnObject(T obj) - { - lock (m_pool) - { - if (m_pool.Count >= m_maxPoolSize) - return; - else - m_pool.Push(obj); - } - } - } -} \ No newline at end of file diff --git a/OpenSim/Framework/RegionFlags.cs b/OpenSim/Framework/RegionFlags.cs deleted file mode 100644 index a3089b077d..0000000000 --- a/OpenSim/Framework/RegionFlags.cs +++ /dev/null @@ -1,53 +0,0 @@ -/* - * 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.Framework -{ - /// - /// Region flags used internally by OpenSimulator to store installation specific information about regions. - /// - /// - /// Don't confuse with OpenMetaverse.RegionFlags which are client facing flags (i.e. they go over the wire). - /// Returned by IGridService.GetRegionFlags() - /// - [Flags] - public enum RegionFlags : int - { - DefaultRegion = 1, // Used for new Rez. Random if multiple defined - FallbackRegion = 2, // Regions we redirect to when the destination is down - RegionOnline = 4, // Set when a region comes online, unset when it unregisters and DeleteOnUnregister is false - NoDirectLogin = 8, // Region unavailable for direct logins (by name) - Persistent = 16, // Don't remove on unregister - LockedOut = 32, // Don't allow registration - NoMove = 64, // Don't allow moving this region - Reservation = 128, // This is an inactive reservation - Authenticate = 256, // Require authentication - Hyperlink = 512 // Record represents a HG link - } -} \ No newline at end of file diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index e7bed6aeb0..4bde7be2e1 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -122,13 +122,10 @@ namespace OpenSim.Framework public UUID lastMapUUID = UUID.Zero; public string lastMapRefresh = "0"; - private float m_nonphysPrimMin = 0; private int m_nonphysPrimMax = 0; - private float m_physPrimMin = 0; private int m_physPrimMax = 0; private bool m_clampPrimSize = false; private int m_objectCapacity = 0; - private int m_linksetCapacity = 0; private int m_agentCapacity = 0; private string m_regionType = String.Empty; private RegionLightShareData m_windlight = new RegionLightShareData(); @@ -290,21 +287,11 @@ namespace OpenSim.Framework set { m_windlight = value; } } - public float NonphysPrimMin - { - get { return m_nonphysPrimMin; } - } - public int NonphysPrimMax { get { return m_nonphysPrimMax; } } - public float PhysPrimMin - { - get { return m_physPrimMin; } - } - public int PhysPrimMax { get { return m_physPrimMax; } @@ -320,11 +307,6 @@ namespace OpenSim.Framework get { return m_objectCapacity; } } - public int LinksetCapacity - { - get { return m_linksetCapacity; } - } - public int AgentCapacity { get { return m_agentCapacity; } @@ -643,31 +625,16 @@ namespace OpenSim.Framework m_regionType = config.GetString("RegionType", String.Empty); allKeys.Remove("RegionType"); - #region Prim stuff - - m_nonphysPrimMin = config.GetFloat("NonPhysicalPrimMin", 0); - allKeys.Remove("NonPhysicalPrimMin"); - - m_nonphysPrimMax = config.GetInt("NonPhysicalPrimMax", 0); - allKeys.Remove("NonPhysicalPrimMax"); - - m_physPrimMin = config.GetFloat("PhysicalPrimMin", 0); - allKeys.Remove("PhysicalPrimMin"); - + // Prim stuff + // + m_nonphysPrimMax = config.GetInt("NonphysicalPrimMax", 0); + allKeys.Remove("NonphysicalPrimMax"); m_physPrimMax = config.GetInt("PhysicalPrimMax", 0); allKeys.Remove("PhysicalPrimMax"); - m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); allKeys.Remove("ClampPrimSize"); - m_objectCapacity = config.GetInt("MaxPrims", 15000); allKeys.Remove("MaxPrims"); - - m_linksetCapacity = config.GetInt("LinksetPrims", 0); - allKeys.Remove("LinksetPrims"); - - #endregion - m_agentCapacity = config.GetInt("MaxAgents", 100); allKeys.Remove("MaxAgents"); @@ -706,27 +673,16 @@ namespace OpenSim.Framework config.Set("ExternalHostName", m_externalHostName); - if (m_nonphysPrimMin > 0) - config.Set("NonphysicalPrimMax", m_nonphysPrimMin); - - if (m_nonphysPrimMax > 0) + if (m_nonphysPrimMax != 0) config.Set("NonphysicalPrimMax", m_nonphysPrimMax); - - if (m_physPrimMin > 0) - config.Set("PhysicalPrimMax", m_physPrimMin); - - if (m_physPrimMax > 0) + if (m_physPrimMax != 0) config.Set("PhysicalPrimMax", m_physPrimMax); - config.Set("ClampPrimSize", m_clampPrimSize.ToString()); - if (m_objectCapacity > 0) + if (m_objectCapacity != 0) config.Set("MaxPrims", m_objectCapacity); - if (m_linksetCapacity > 0) - config.Set("LinksetPrims", m_linksetCapacity); - - if (m_agentCapacity > 0) + if (m_agentCapacity != 0) config.Set("MaxAgents", m_agentCapacity); if (ScopeID != UUID.Zero) @@ -803,15 +759,9 @@ namespace OpenSim.Framework configMember.addConfigurationOption("lastmap_refresh", ConfigurationOption.ConfigurationTypes.TYPE_STRING_NOT_EMPTY, "Last Map Refresh", Util.UnixTimeSinceEpoch().ToString(), true); - configMember.addConfigurationOption("nonphysical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, - "Minimum size for nonphysical prims", m_nonphysPrimMin.ToString(), true); - configMember.addConfigurationOption("nonphysical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Maximum size for nonphysical prims", m_nonphysPrimMax.ToString(), true); - configMember.addConfigurationOption("physical_prim_min", ConfigurationOption.ConfigurationTypes.TYPE_FLOAT, - "Minimum size for nonphysical prims", m_physPrimMin.ToString(), true); - configMember.addConfigurationOption("physical_prim_max", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Maximum size for physical prims", m_physPrimMax.ToString(), true); @@ -821,9 +771,6 @@ namespace OpenSim.Framework configMember.addConfigurationOption("object_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Max objects this sim will hold", m_objectCapacity.ToString(), true); - configMember.addConfigurationOption("linkset_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, - "Max prims an object will hold", m_linksetCapacity.ToString(), true); - configMember.addConfigurationOption("agent_capacity", ConfigurationOption.ConfigurationTypes.TYPE_INT32, "Max avatars this sim will hold", m_agentCapacity.ToString(), true); @@ -945,9 +892,6 @@ namespace OpenSim.Framework case "object_capacity": m_objectCapacity = (int)configuration_result; break; - case "linkset_capacity": - m_linksetCapacity = (int)configuration_result; - break; case "agent_capacity": m_agentCapacity = (int)configuration_result; break; diff --git a/OpenSim/Framework/Serialization/ArchiveConstants.cs b/OpenSim/Framework/Serialization/ArchiveConstants.cs index 48f1c4f94f..2c5e0018ec 100644 --- a/OpenSim/Framework/Serialization/ArchiveConstants.cs +++ b/OpenSim/Framework/Serialization/ArchiveConstants.cs @@ -52,11 +52,6 @@ namespace OpenSim.Framework.Serialization /// public const string INVENTORY_PATH = "inventory/"; - /// - /// Path for regions in a multi-region archive - /// - public const string REGIONS_PATH = "regions/"; - /// /// Path for the prims file /// diff --git a/OpenSim/Framework/Serialization/External/OspResolver.cs b/OpenSim/Framework/Serialization/External/OspResolver.cs index fa7160f874..d31d27c4a6 100644 --- a/OpenSim/Framework/Serialization/External/OspResolver.cs +++ b/OpenSim/Framework/Serialization/External/OspResolver.cs @@ -65,14 +65,9 @@ namespace OpenSim.Framework.Serialization UserAccount account = userService.GetUserAccount(UUID.Zero, userId); if (account != null) - { return MakeOspa(account.FirstName, account.LastName); - } // else -// { // m_log.WarnFormat("[OSP RESOLVER]: No user account for {0}", userId); -// System.Console.WriteLine("[OSP RESOLVER]: No user account for {0}", userId); -// } return null; } @@ -84,13 +79,10 @@ namespace OpenSim.Framework.Serialization /// public static string MakeOspa(string firstName, string lastName) { - string ospa - = OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName; - -// m_log.DebugFormat("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName); -// System.Console.WriteLine("[OSP RESOLVER]: Made OSPA {0} for {1} {2}", ospa, firstName, lastName); +// m_log.DebugFormat("[OSP RESOLVER]: Making OSPA for {0} {1}", firstName, lastName); - return ospa; + return + OSPA_PREFIX + OSPA_NAME_KEY + OSPA_PAIR_SEPARATOR + firstName + OSPA_NAME_VALUE_SEPARATOR + lastName; } /// diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 605909dcc6..cf19002baf 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -96,6 +96,11 @@ namespace OpenSim.Framework.Servers get { return m_httpServer; } } + /// + /// Holds the non-viewer statistics collection object for this service/server + /// + protected IStatsCollector m_stats; + public BaseOpenSimServer() { m_startuptime = DateTime.Now; @@ -172,6 +177,10 @@ namespace OpenSim.Framework.Servers "show info", "Show general information about the server", HandleShow); + m_console.Commands.AddCommand("General", false, "show stats", + "show stats", + "Show statistics", HandleShow); + m_console.Commands.AddCommand("General", false, "show threads", "show threads", "Show thread status", HandleShow); @@ -192,19 +201,8 @@ namespace OpenSim.Framework.Servers "threads show", "Show thread status. Synonym for \"show threads\"", (string module, string[] args) => Notice(GetThreadsReport())); - - m_console.Commands.AddCommand("General", false, "force gc", - "force gc", - "Manually invoke runtime garbage collection. For debugging purposes", - HandleForceGc); } } - - private void HandleForceGc(string module, string[] args) - { - MainConsole.Instance.Output("Manually invoking runtime garbage collection"); - GC.Collect(); - } /// /// Should be overriden and referenced by descendents if they need to perform extra shutdown processing @@ -228,7 +226,12 @@ namespace OpenSim.Framework.Servers { StringBuilder sb = new StringBuilder("DIAGNOSTICS\n\n"); sb.Append(GetUptimeReport()); - sb.Append(StatsManager.SimExtraStats.Report()); + + if (m_stats != null) + { + sb.Append(m_stats.Report()); + } + sb.Append(Environment.NewLine); sb.Append(GetThreadsReport()); @@ -379,6 +382,10 @@ namespace OpenSim.Framework.Servers { Notice("set log level [level] - change the console logging level only. For example, off or debug."); Notice("show info - show server information (e.g. startup path)."); + + if (m_stats != null) + Notice("show stats - show statistical information for this server"); + Notice("show threads - list tracked threads"); Notice("show uptime - show server startup time and uptime."); Notice("show version - show server version."); @@ -402,6 +409,11 @@ namespace OpenSim.Framework.Servers ShowInfo(); break; + case "stats": + if (m_stats != null) + Notice(m_stats.Report()); + break; + case "threads": Notice(GetThreadsReport()); break; @@ -592,7 +604,8 @@ namespace OpenSim.Framework.Servers public string osSecret { // Secret uuid for the simulator - get { return m_osSecret; } + get { return m_osSecret; } + } public string StatReport(IOSHttpRequest httpRequest) @@ -600,11 +613,11 @@ namespace OpenSim.Framework.Servers // If we catch a request for "callback", wrap the response in the value for jsonp if (httpRequest.Query.ContainsKey("callback")) { - return httpRequest.Query["callback"].ToString() + "(" + StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; + return httpRequest.Query["callback"].ToString() + "(" + m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version) + ");"; } else { - return StatsManager.SimExtraStats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); + return m_stats.XReport((DateTime.Now - m_startuptime).ToString() , m_version); } } diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index 3198891a30..788a0b95ee 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -54,23 +54,8 @@ namespace OpenSim.Framework.Servers.HttpServer private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private HttpServerLogWriter httpserverlog = new HttpServerLogWriter(); - /// - /// Gets or sets the debug level. - /// - /// - /// See MainServer.DebugLevel. - /// public int DebugLevel { get; set; } - /// - /// Request number for diagnostic purposes. - /// - /// - /// This is an internal number. In some debug situations an external number may also be supplied in the - /// opensim-request-id header but we are not currently logging this. - /// - public int RequestNumber { get; private set; } - private volatile int NotSocketErrors = 0; public volatile bool HTTPDRunning = false; @@ -82,7 +67,7 @@ namespace OpenSim.Framework.Servers.HttpServer protected Dictionary m_llsdHandlers = new Dictionary(); protected Dictionary m_streamHandlers = new Dictionary(); protected Dictionary m_HTTPHandlers = new Dictionary(); -// protected Dictionary m_agentHandlers = new Dictionary(); + protected Dictionary m_agentHandlers = new Dictionary(); protected Dictionary m_pollHandlers = new Dictionary(); @@ -260,29 +245,29 @@ namespace OpenSim.Framework.Servers.HttpServer return new List(m_pollHandlers.Keys); } -// // Note that the agent string is provided simply to differentiate -// // the handlers - it is NOT required to be an actual agent header -// // value. -// public bool AddAgentHandler(string agent, IHttpAgentHandler handler) -// { -// lock (m_agentHandlers) -// { -// if (!m_agentHandlers.ContainsKey(agent)) -// { -// m_agentHandlers.Add(agent, handler); -// return true; -// } -// } -// -// //must already have a handler for that path so return false -// return false; -// } -// -// public List GetAgentHandlerKeys() -// { -// lock (m_agentHandlers) -// return new List(m_agentHandlers.Keys); -// } + // Note that the agent string is provided simply to differentiate + // the handlers - it is NOT required to be an actual agent header + // value. + public bool AddAgentHandler(string agent, IHttpAgentHandler handler) + { + lock (m_agentHandlers) + { + if (!m_agentHandlers.ContainsKey(agent)) + { + m_agentHandlers.Add(agent, handler); + return true; + } + } + + //must already have a handler for that path so return false + return false; + } + + public List GetAgentHandlerKeys() + { + lock (m_agentHandlers) + return new List(m_agentHandlers.Keys); + } public bool AddLLSDHandler(string path, LLSDMethod handler) { @@ -311,8 +296,6 @@ namespace OpenSim.Framework.Servers.HttpServer private void OnRequest(object source, RequestEventArgs args) { - RequestNumber++; - try { IHttpClientContext context = (IHttpClientContext)source; @@ -423,6 +406,7 @@ namespace OpenSim.Framework.Servers.HttpServer string requestMethod = request.HttpMethod; string uriString = request.RawUrl; +// string reqnum = "unknown"; int requestStartTick = Environment.TickCount; // Will be adjusted later on. @@ -439,22 +423,22 @@ namespace OpenSim.Framework.Servers.HttpServer Thread.CurrentThread.CurrentCulture = new CultureInfo("en-US", true); -// // This is the REST agent interface. We require an agent to properly identify -// // itself. If the REST handler recognizes the prefix it will attempt to -// // satisfy the request. If it is not recognizable, and no damage has occurred -// // the request can be passed through to the other handlers. This is a low -// // probability event; if a request is matched it is normally expected to be -// // handled -// IHttpAgentHandler agentHandler; -// -// if (TryGetAgentHandler(request, response, out agentHandler)) -// { -// if (HandleAgentRequest(agentHandler, request, response)) -// { -// requestEndTick = Environment.TickCount; -// return; -// } -// } + // This is the REST agent interface. We require an agent to properly identify + // itself. If the REST handler recognizes the prefix it will attempt to + // satisfy the request. If it is not recognizable, and no damage has occurred + // the request can be passed through to the other handlers. This is a low + // probability event; if a request is matched it is normally expected to be + // handled + IHttpAgentHandler agentHandler; + + if (TryGetAgentHandler(request, response, out agentHandler)) + { + if (HandleAgentRequest(agentHandler, request, response)) + { + requestEndTick = Environment.TickCount; + return; + } + } //response.KeepAlive = true; response.SendChunked = false; @@ -466,7 +450,9 @@ namespace OpenSim.Framework.Servers.HttpServer if (TryGetStreamHandler(handlerKey, out requestHandler)) { if (DebugLevel >= 3) - LogIncomingToStreamHandler(request, requestHandler); + m_log.DebugFormat( + "[BASE HTTP SERVER]: Found stream handler for {0} {1} {2} {3}", + request.HttpMethod, request.Url.PathAndQuery, requestHandler.Name, requestHandler.Description); response.ContentType = requestHandler.ContentType; // Lets do this defaulting before in case handler has varying content type. @@ -543,8 +529,11 @@ namespace OpenSim.Framework.Servers.HttpServer { case null: case "text/html": + if (DebugLevel >= 3) - LogIncomingToContentTypeHandler(request); + m_log.DebugFormat( + "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", + request.ContentType, request.HttpMethod, request.Url.PathAndQuery); buffer = HandleHTTPRequest(request, response); break; @@ -552,8 +541,11 @@ namespace OpenSim.Framework.Servers.HttpServer case "application/llsd+xml": case "application/xml+llsd": case "application/llsd+json": + if (DebugLevel >= 3) - LogIncomingToContentTypeHandler(request); + m_log.DebugFormat( + "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", + request.ContentType, request.HttpMethod, request.Url.PathAndQuery); buffer = HandleLLSDRequests(request, response); break; @@ -572,7 +564,9 @@ namespace OpenSim.Framework.Servers.HttpServer if (DoWeHaveALLSDHandler(request.RawUrl)) { if (DebugLevel >= 3) - LogIncomingToContentTypeHandler(request); + m_log.DebugFormat( + "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", + request.ContentType, request.HttpMethod, request.Url.PathAndQuery); buffer = HandleLLSDRequests(request, response); } @@ -580,14 +574,18 @@ namespace OpenSim.Framework.Servers.HttpServer else if (DoWeHaveAHTTPHandler(request.RawUrl)) { if (DebugLevel >= 3) - LogIncomingToContentTypeHandler(request); + m_log.DebugFormat( + "[BASE HTTP SERVER]: Found a {0} content type handler for {1} {2}", + request.ContentType, request.HttpMethod, request.Url.PathAndQuery); buffer = HandleHTTPRequest(request, response); } else { if (DebugLevel >= 3) - LogIncomingToXmlRpcHandler(request); + m_log.DebugFormat( + "[BASE HTTP SERVER]: Assuming a generic XMLRPC request for {0} {1}", + request.HttpMethod, request.Url.PathAndQuery); // generic login request. buffer = HandleXmlRpcRequests(request, response); @@ -631,11 +629,11 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (IOException e) { - m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); + m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); } catch (Exception e) { - m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.StackTrace), e); + m_log.Error(String.Format("[BASE HTTP SERVER]: HandleRequest() threw {0} ", e.Message), e); SendHTML500(response); } finally @@ -646,90 +644,14 @@ namespace OpenSim.Framework.Servers.HttpServer if (tickdiff > 3000 && (requestHandler == null || requestHandler.Name == null || requestHandler.Name != "GetTexture")) { m_log.InfoFormat( - "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} {4} from {5} took {6}ms", - RequestNumber, + "[BASE HTTP SERVER]: Slow handling of {0} {1} {2} {3} from {4} took {5}ms", requestMethod, uriString, requestHandler != null ? requestHandler.Name : "", requestHandler != null ? requestHandler.Description : "", - request.RemoteIPEndPoint, + request.RemoteIPEndPoint.ToString(), tickdiff); } - else if (DebugLevel >= 4) - { - m_log.DebugFormat( - "[BASE HTTP SERVER]: HTTP IN {0} :{1} took {2}ms", - RequestNumber, - Port, - tickdiff); - } - } - } - - private void LogIncomingToStreamHandler(OSHttpRequest request, IRequestHandler requestHandler) - { - m_log.DebugFormat( - "[BASE HTTP SERVER]: HTTP IN {0} :{1} stream handler {2} {3} {4} {5} from {6}", - RequestNumber, - Port, - request.HttpMethod, - request.Url.PathAndQuery, - requestHandler.Name, - requestHandler.Description, - request.RemoteIPEndPoint); - - if (DebugLevel >= 5) - LogIncomingInDetail(request); - } - - private void LogIncomingToContentTypeHandler(OSHttpRequest request) - { - m_log.DebugFormat( - "[BASE HTTP SERVER]: HTTP IN {0} :{1} {2} content type handler {3} {4} from {5}", - RequestNumber, - Port, - (request.ContentType == null || request.ContentType == "") ? "not set" : request.ContentType, - request.HttpMethod, - request.Url.PathAndQuery, - request.RemoteIPEndPoint); - - if (DebugLevel >= 5) - LogIncomingInDetail(request); - } - - private void LogIncomingToXmlRpcHandler(OSHttpRequest request) - { - m_log.DebugFormat( - "[BASE HTTP SERVER]: HTTP IN {0} :{1} assumed generic XMLRPC request {2} {3} from {4}", - RequestNumber, - Port, - request.HttpMethod, - request.Url.PathAndQuery, - request.RemoteIPEndPoint); - - if (DebugLevel >= 5) - LogIncomingInDetail(request); - } - - private void LogIncomingInDetail(OSHttpRequest request) - { - using (StreamReader reader = new StreamReader(Util.Copy(request.InputStream), Encoding.UTF8)) - { - string output; - - if (DebugLevel == 5) - { - const int sampleLength = 80; - char[] sampleChars = new char[sampleLength]; - reader.Read(sampleChars, 0, sampleLength); - output = new string(sampleChars); - } - else - { - output = reader.ReadToEnd(); - } - - m_log.DebugFormat("[BASE HTTP SERVER]: {0}...", output.Replace("\n", @"\n")); } } @@ -825,24 +747,24 @@ namespace OpenSim.Framework.Servers.HttpServer } } -// private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) -// { -// agentHandler = null; -// -// lock (m_agentHandlers) -// { -// foreach (IHttpAgentHandler handler in m_agentHandlers.Values) -// { -// if (handler.Match(request, response)) -// { -// agentHandler = handler; -// return true; -// } -// } -// } -// -// return false; -// } + private bool TryGetAgentHandler(OSHttpRequest request, OSHttpResponse response, out IHttpAgentHandler agentHandler) + { + agentHandler = null; + + lock (m_agentHandlers) + { + foreach (IHttpAgentHandler handler in m_agentHandlers.Values) + { + if (handler.Match(request, response)) + { + agentHandler = handler; + return true; + } + } + } + + return false; + } /// /// Try all the registered xmlrpc handlers when an xmlrpc request is received. @@ -1815,21 +1737,21 @@ namespace OpenSim.Framework.Servers.HttpServer m_pollHandlers.Remove(path); } -// public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) -// { -// lock (m_agentHandlers) -// { -// IHttpAgentHandler foundHandler; -// -// if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) -// { -// m_agentHandlers.Remove(agent); -// return true; -// } -// } -// -// return false; -// } + public bool RemoveAgentHandler(string agent, IHttpAgentHandler handler) + { + lock (m_agentHandlers) + { + IHttpAgentHandler foundHandler; + + if (m_agentHandlers.TryGetValue(agent, out foundHandler) && foundHandler == handler) + { + m_agentHandlers.Remove(agent); + return true; + } + } + + return false; + } public void RemoveXmlRPCHandler(string method) { diff --git a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs index 0bd3aae7d5..db58f6f468 100644 --- a/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/Interfaces/IHttpServer.cs @@ -41,10 +41,10 @@ namespace OpenSim.Framework.Servers.HttpServer uint Port { get; } bool UseSSL { get; } -// // Note that the agent string is provided simply to differentiate -// // the handlers - it is NOT required to be an actual agent header -// // value. -// bool AddAgentHandler(string agent, IHttpAgentHandler handler); + // Note that the agent string is provided simply to differentiate + // the handlers - it is NOT required to be an actual agent header + // value. + bool AddAgentHandler(string agent, IHttpAgentHandler handler); /// /// Add a handler for an HTTP request. @@ -106,13 +106,13 @@ namespace OpenSim.Framework.Servers.HttpServer bool SetDefaultLLSDHandler(DefaultLLSDMethod handler); -// /// -// /// Remove the agent if it is registered. -// /// -// /// -// /// -// /// -// bool RemoveAgentHandler(string agent, IHttpAgentHandler handler); + /// + /// Remove the agent if it is registered. + /// + /// + /// + /// + bool RemoveAgentHandler(string agent, IHttpAgentHandler handler); /// /// Remove an HTTP handler diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs index ae7d515e13..8dc0e3a71d 100644 --- a/OpenSim/Framework/Servers/MainServer.cs +++ b/OpenSim/Framework/Servers/MainServer.cs @@ -29,7 +29,6 @@ using System; using System.Collections.Generic; using System.Reflection; using System.Net; -using System.Text; using log4net; using OpenSim.Framework; using OpenSim.Framework.Console; @@ -48,12 +47,9 @@ namespace OpenSim.Framework.Servers /// Control the printing of certain debug messages. /// /// - /// If DebugLevel >= 1 then short warnings are logged when receiving bad input data. - /// If DebugLevel >= 2 then long warnings are logged when receiving bad input data. - /// If DebugLevel >= 3 then short notices about all incoming non-poll HTTP requests are logged. - /// If DebugLevel >= 4 then the time taken to fulfill the request is logged. - /// If DebugLevel >= 5 then the start of the body of incoming non-poll HTTP requests will be logged. - /// If DebugLevel >= 6 then the entire body of incoming non-poll HTTP requests will be logged. + /// If DebugLevel >= 1, then short warnings are logged when receiving bad input data. + /// If DebugLevel >= 2, then long warnings are logged when receiving bad input data. + /// If DebugLevel >= 3, then short notices about all incoming non-poll HTTP requests are logged. /// public static int DebugLevel { @@ -105,28 +101,17 @@ namespace OpenSim.Framework.Servers get { return new Dictionary(m_Servers); } } + public static void RegisterHttpConsoleCommands(ICommandConsole console) { console.Commands.AddCommand( - "Comms", false, "show http-handlers", - "show http-handlers", - "Show all registered http handlers", HandleShowHttpHandlersCommand); - - console.Commands.AddCommand( - "Debug", false, "debug http", "debug http []", - "Turn on http request logging.", - "If in or all and\n" - + " level <= 0 then no extra logging is done.\n" - + " level >= 1 then short warnings are logged when receiving bad input data.\n" - + " level >= 2 then long warnings are logged when receiving bad input data.\n" - + " level >= 3 then short notices about all incoming non-poll HTTP requests are logged.\n" - + " level >= 4 then the time taken to fulfill the request is logged.\n" - + " level >= 5 then a sample from the beginning of the incoming data is logged.\n" - + " level >= 6 then the entire incoming data is logged.\n" - + " no level is specified then the current level is returned.\n\n" - + "If out or all and\n" - + " level >= 3 then short notices about all outgoing requests going through WebUtil are logged.\n" - + " level >= 4 then the time taken to fulfill the request is logged.\n", + "Debug", false, "debug http", "debug http []", + "Turn on inbound non-poll http request debugging.", + "If level <= 0, then no extra logging is done.\n" + + "If level >= 1, then short warnings are logged when receiving bad input data.\n" + + "If level >= 2, then long warnings are logged when receiving bad input data.\n" + + "If level >= 3, then short notices about all incoming non-poll HTTP requests are logged.\n" + + "If no level is specified then the current level is returned.", HandleDebugHttpCommand); } @@ -134,122 +119,27 @@ namespace OpenSim.Framework.Servers /// Turn on some debugging values for OpenSim. /// /// - private static void HandleDebugHttpCommand(string module, string[] cmdparams) + private static void HandleDebugHttpCommand(string module, string[] args) { - if (cmdparams.Length < 3) + if (args.Length == 3) { - MainConsole.Instance.Output("Usage: debug http 0..6"); - return; - } - - bool inReqs = false; - bool outReqs = false; - bool allReqs = false; - - string subCommand = cmdparams[2]; - - if (subCommand.ToLower() == "in") - { - inReqs = true; - } - else if (subCommand.ToLower() == "out") - { - outReqs = true; - } - else if (subCommand.ToLower() == "all") - { - allReqs = true; - } - else - { - MainConsole.Instance.Output("You must specify in, out or all"); - return; - } - - if (cmdparams.Length >= 4) - { - string rawNewDebug = cmdparams[3]; int newDebug; - - if (!int.TryParse(rawNewDebug, out newDebug)) - { - MainConsole.Instance.OutputFormat("{0} is not a valid debug level", rawNewDebug); - return; - } - - if (newDebug < 0 || newDebug > 6) - { - MainConsole.Instance.OutputFormat("{0} is outside the valid debug level range of 0..6", newDebug); - return; - } - - if (allReqs || inReqs) + if (int.TryParse(args[2], out newDebug)) { MainServer.DebugLevel = newDebug; - MainConsole.Instance.OutputFormat("IN debug level set to {0}", newDebug); - } - - if (allReqs || outReqs) - { - WebUtil.DebugLevel = newDebug; - MainConsole.Instance.OutputFormat("OUT debug level set to {0}", newDebug); + MainConsole.Instance.OutputFormat("Debug http level set to {0}", newDebug); } } + else if (args.Length == 2) + { + MainConsole.Instance.OutputFormat("Current debug http level is {0}", MainServer.DebugLevel); + } else { - if (allReqs || inReqs) - MainConsole.Instance.OutputFormat("Current IN debug level is {0}", MainServer.DebugLevel); - - if (allReqs || outReqs) - MainConsole.Instance.OutputFormat("Current OUT debug level is {0}", WebUtil.DebugLevel); + MainConsole.Instance.Output("Usage: debug http 0..3"); } } - private static void HandleShowHttpHandlersCommand(string module, string[] args) - { - if (args.Length != 2) - { - MainConsole.Instance.Output("Usage: show http-handlers"); - return; - } - - StringBuilder handlers = new StringBuilder(); - - lock (m_Servers) - { - foreach (BaseHttpServer httpServer in m_Servers.Values) - { - handlers.AppendFormat( - "Registered HTTP Handlers for server at {0}:{1}\n", httpServer.ListenIPAddress, httpServer.Port); - - handlers.AppendFormat("* XMLRPC:\n"); - foreach (String s in httpServer.GetXmlRpcHandlerKeys()) - handlers.AppendFormat("\t{0}\n", s); - - handlers.AppendFormat("* HTTP:\n"); - List poll = httpServer.GetPollServiceHandlerKeys(); - foreach (String s in httpServer.GetHTTPHandlerKeys()) - handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty)); - -// handlers.AppendFormat("* Agent:\n"); -// foreach (String s in httpServer.GetAgentHandlerKeys()) -// handlers.AppendFormat("\t{0}\n", s); - - handlers.AppendFormat("* LLSD:\n"); - foreach (String s in httpServer.GetLLSDHandlerKeys()) - handlers.AppendFormat("\t{0}\n", s); - - handlers.AppendFormat("* StreamHandlers ({0}):\n", httpServer.GetStreamHandlerKeys().Count); - foreach (String s in httpServer.GetStreamHandlerKeys()) - handlers.AppendFormat("\t{0}\n", s); - - handlers.Append("\n"); - } - } - - MainConsole.Instance.Output(handlers.ToString()); - } - /// /// Register an already started HTTP server to the collection of known servers. /// diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index bb094ed6f5..016a1744ef 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.7.5CM"; + private const string VERSION_NUMBER = "0.7.4CM"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour diff --git a/OpenSim/Framework/TaskInventoryDictionary.cs b/OpenSim/Framework/TaskInventoryDictionary.cs index 62ecbd1018..4d07746d2a 100644 --- a/OpenSim/Framework/TaskInventoryDictionary.cs +++ b/OpenSim/Framework/TaskInventoryDictionary.cs @@ -39,12 +39,10 @@ using OpenMetaverse; namespace OpenSim.Framework { /// - /// A dictionary containing task inventory items. Indexed by item UUID. + /// A dictionary for task inventory. /// - /// /// This class is not thread safe. Callers must synchronize on Dictionary methods or Clone() this object before /// iterating over it. - /// public class TaskInventoryDictionary : Dictionary, ICloneable, IXmlSerializable { diff --git a/OpenSim/Framework/TaskInventoryItem.cs b/OpenSim/Framework/TaskInventoryItem.cs index 574ee567f4..fb818ee74b 100644 --- a/OpenSim/Framework/TaskInventoryItem.cs +++ b/OpenSim/Framework/TaskInventoryItem.cs @@ -73,6 +73,9 @@ namespace OpenSim.Framework private bool _ownerChanged = false; + // This used ONLY during copy. It can't be relied on at other times! + private bool _scriptRunning = true; + public UUID AssetID { get { return _assetID; @@ -350,13 +353,14 @@ namespace OpenSim.Framework } } - /// - /// This used ONLY during copy. It can't be relied on at other times! - /// - /// - /// For true script running status, use IEntityInventory.TryGetScriptInstanceRunning() for now. - /// - public bool ScriptRunning { get; set; } + public bool ScriptRunning { + get { + return _scriptRunning; + } + set { + _scriptRunning = value; + } + } // See ICloneable @@ -384,7 +388,6 @@ namespace OpenSim.Framework public TaskInventoryItem() { - ScriptRunning = true; CreationDate = (uint)(DateTime.UtcNow - new DateTime(1970, 1, 1)).TotalSeconds; } } diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index e76a37b9a1..384f7160f3 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -545,19 +545,6 @@ namespace OpenSim.Framework return (x + y - (min >> 1) - (min >> 2) + (min >> 4)); } - /// - /// Determines whether a point is inside a bounding box. - /// - /// - /// - /// - /// - public static bool IsInsideBox(Vector3 v, Vector3 min, Vector3 max) - { - return v.X >= min.X & v.Y >= min.Y && v.Z >= min.Z - && v.X <= max.X && v.Y <= max.Y && v.Z <= max.Z; - } - /// /// Are the co-ordinates of the new region visible from the old region? /// @@ -875,12 +862,6 @@ namespace OpenSim.Framework return Math.Min(Math.Max(x, min), max); } - public static Vector3 Clip(Vector3 vec, float min, float max) - { - return new Vector3(Clip(vec.X, min, max), Clip(vec.Y, min, max), - Clip(vec.Z, min, max)); - } - /// /// Convert an UUID to a raw uuid string. Right now this is a string without hyphens. /// @@ -1032,38 +1013,6 @@ namespace OpenSim.Framework } } - /// - /// Copy data from one stream to another, leaving the read position of both streams at the beginning. - /// - /// - /// Input stream. Must be seekable. - /// - /// - /// Thrown if the input stream is not seekable. - /// - public static Stream Copy(Stream inputStream) - { - if (!inputStream.CanSeek) - throw new ArgumentException("Util.Copy(Stream inputStream) must receive an inputStream that can seek"); - - const int readSize = 256; - byte[] buffer = new byte[readSize]; - MemoryStream ms = new MemoryStream(); - - int count = inputStream.Read(buffer, 0, readSize); - - while (count > 0) - { - ms.Write(buffer, 0, count); - count = inputStream.Read(buffer, 0, readSize); - } - - ms.Position = 0; - inputStream.Position = 0; - - return ms; - } - public static XmlRpcResponse XmlRpcCommand(string url, string methodName, params object[] args) { return SendXmlRpcCommand(url, methodName, args); diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index b85d93d53a..30a8c28072 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -53,18 +53,10 @@ namespace OpenSim.Framework LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Control the printing of certain debug messages. - /// - /// - /// If DebugLevel >= 3 then short notices about outgoing HTTP requests are logged. - /// - public static int DebugLevel { get; set; } - /// /// Request number for diagnostic purposes. /// - public static int RequestNumber { get; internal set; } + public static int RequestNumber = 0; /// /// this is the header field used to communicate the local request id @@ -154,11 +146,7 @@ namespace OpenSim.Framework private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed) { int reqnum = RequestNumber++; - - if (DebugLevel >= 3) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} ServiceOSD {1} {2} (timeout {3}, compressed {4})", - reqnum, method, url, timeout, compressed); + // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); string errorMessage = "unknown error"; int tickstart = Util.EnvironmentTickCount(); @@ -242,7 +230,7 @@ namespace OpenSim.Framework int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); if (tickdiff > LongCallTime) m_log.InfoFormat( - "[WEB UTIL]: Slow ServiceOSD request {0} {1} {2} took {3}ms, {4}ms writing, {5}", + "[OSD REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", reqnum, method, url, @@ -251,14 +239,10 @@ namespace OpenSim.Framework strBuffer != null ? (strBuffer.Length > MaxRequestDiagLength ? strBuffer.Remove(MaxRequestDiagLength) : strBuffer) : ""); - else if (DebugLevel >= 4) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", - reqnum, tickdiff, tickdata); } m_log.DebugFormat( - "[WEB UTIL]: ServiceOSD request {0} {1} {2} FAILED: {3}", reqnum, url, method, errorMessage); + "[WEB UTIL]: <{0}> osd request for {1}, method {2} FAILED: {3}", reqnum, url, method, errorMessage); return ErrorResponseMap(errorMessage); } @@ -334,11 +318,7 @@ namespace OpenSim.Framework { int reqnum = RequestNumber++; string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; - - if (DebugLevel >= 3) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} ServiceForm {1} {2} (timeout {3})", - reqnum, method, url, timeout); + // m_log.DebugFormat("[WEB UTIL]: <{0}> start form request for {1}, method {2}",reqnum,url,method); string errorMessage = "unknown error"; int tickstart = Util.EnvironmentTickCount(); @@ -401,7 +381,7 @@ namespace OpenSim.Framework int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); if (tickdiff > LongCallTime) m_log.InfoFormat( - "[WEB UTIL]: Slow ServiceForm request {0} {1} {2} took {3}ms, {4}ms writing, {5}", + "[SERVICE FORM]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", reqnum, method, url, @@ -410,13 +390,9 @@ namespace OpenSim.Framework queryString != null ? (queryString.Length > MaxRequestDiagLength) ? queryString.Remove(MaxRequestDiagLength) : queryString : ""); - else if (DebugLevel >= 4) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", - reqnum, tickdiff, tickdata); } - m_log.WarnFormat("[WEB UTIL]: ServiceForm request {0} {1} {2} failed: {2}", reqnum, method, url, errorMessage); + m_log.WarnFormat("[SERVICE FORM]: <{0}> form request to {1} failed: {2}", reqnum, url, errorMessage); return ErrorResponseMap(errorMessage); } @@ -668,6 +644,7 @@ namespace OpenSim.Framework /// public static string[] GetPreferredImageTypes(string accept) { + if (accept == null || accept == string.Empty) return new string[0]; @@ -726,16 +703,14 @@ namespace OpenSim.Framework int maxConnections) { int reqnum = WebUtil.RequestNumber++; - - if (WebUtil.DebugLevel >= 3) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} AsynchronousRequestObject {1} {2}", - reqnum, verb, requestUrl); + // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); int tickstart = Util.EnvironmentTickCount(); // int tickdata = 0; int tickdiff = 0; +// m_log.DebugFormat("[ASYNC REQUEST]: Starting {0} {1}", verb, requestUrl); + Type type = typeof(TRequest); WebRequest request = WebRequest.Create(requestUrl); @@ -893,7 +868,7 @@ namespace OpenSim.Framework } m_log.InfoFormat( - "[ASYNC REQUEST]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", + "[ASYNC REQUEST]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", reqnum, verb, requestUrl, @@ -908,12 +883,6 @@ namespace OpenSim.Framework requestUrl, tickdiff); } - else if (WebUtil.DebugLevel >= 4) - { - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} took {1}ms", - reqnum, tickdiff); - } } } @@ -934,11 +903,7 @@ namespace OpenSim.Framework public static string MakeRequest(string verb, string requestUrl, string obj) { int reqnum = WebUtil.RequestNumber++; - - if (WebUtil.DebugLevel >= 3) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} SynchronousRestForms {1} {2}", - reqnum, verb, requestUrl); + // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); int tickstart = Util.EnvironmentTickCount(); int tickdata = 0; @@ -1025,7 +990,7 @@ namespace OpenSim.Framework int tickdiff = Util.EnvironmentTickCountSubtract(tickstart); if (tickdiff > WebUtil.LongCallTime) m_log.InfoFormat( - "[FORMS]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", + "[FORMS]: Slow request to <{0}> {1} {2} took {3}ms {4}ms writing {5}", reqnum, verb, requestUrl, @@ -1033,10 +998,6 @@ namespace OpenSim.Framework tickset, tickdata, obj.Length > WebUtil.MaxRequestDiagLength ? obj.Remove(WebUtil.MaxRequestDiagLength) : obj); - else if (WebUtil.DebugLevel >= 4) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", - reqnum, tickdiff, tickdata); return respstring; } @@ -1071,11 +1032,7 @@ namespace OpenSim.Framework public static TResponse MakeRequest(string verb, string requestUrl, TRequest obj, int pTimeout, int maxConnections) { int reqnum = WebUtil.RequestNumber++; - - if (WebUtil.DebugLevel >= 3) - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} SynchronousRestObject {1} {2}", - reqnum, verb, requestUrl); + // m_log.DebugFormat("[WEB UTIL]: <{0}> start osd request for {1}, method {2}",reqnum,url,method); int tickstart = Util.EnvironmentTickCount(); int tickdata = 0; @@ -1194,7 +1151,7 @@ namespace OpenSim.Framework } m_log.InfoFormat( - "[SynchronousRestObjectRequester]: Slow request {0} {1} {2} took {3}ms, {4}ms writing, {5}", + "[SynchronousRestObjectRequester]: Slow request to <{0}> {1} {2} took {3}ms, {4}ms writing, {5}", reqnum, verb, requestUrl, @@ -1202,12 +1159,6 @@ namespace OpenSim.Framework tickdata, originalRequest); } - else if (WebUtil.DebugLevel >= 4) - { - m_log.DebugFormat( - "[WEB UTIL]: HTTP OUT {0} took {1}ms, {2}ms writing", - reqnum, tickdiff, tickdata); - } return deserial; } diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 5f072722a2..6255515c32 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -35,7 +35,6 @@ using System.Text; using System.Text.RegularExpressions; using System.Timers; using log4net; -using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -254,14 +253,8 @@ namespace OpenSim m_console.Commands.AddCommand("Debug", false, "debug teleport", "debug teleport", "Toggle teleport route debugging", Debug); m_console.Commands.AddCommand("Debug", false, "debug scene", - "debug scene active|collisions|physics|scripting|teleport true|false", - "Turn on scene debugging.", - "If active is false then main scene update and maintenance loops are suspended.\n" - + "If collisions is false then collisions with other objects are turned off.\n" - + "If physics is false then all physics objects are non-physical.\n" - + "If scripting is false then no scripting operations happen.\n" - + "If teleport is true then some extra teleport debug information is logged.", - Debug); + "debug scene ", + "Turn on scene debugging", Debug); m_console.Commands.AddCommand("General", false, "change region", "change region ", @@ -298,7 +291,7 @@ namespace OpenSim m_console.Commands.AddCommand("Archiving", false, "save oar", //"save oar [-v|--version=] [-p|--profile=] []", - "save oar [-h|--home=] [--noassets] [--publish] [--perm=] [--all] []", + "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 "-h|--home= adds the url of the profile service to the saved user information.\n" @@ -308,7 +301,6 @@ namespace OpenSim + " this is useful if you're making oars generally available that might be reloaded to the same grid from which you published\n" + "--perm= stops objects with insufficient permissions from being saved to the OAR.\n" + " can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer\n" - + "--all saves all the regions in the simulator, instead of just the current region.\n" + "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.", SaveOar); @@ -318,11 +310,8 @@ namespace OpenSim "Change the scale of a named prim", HandleEditScale); m_console.Commands.AddCommand("Users", false, "kick user", - "kick user [--force] [message]", - "Kick a user off the simulator", - "The --force option will kick the user without any checks to see whether it's already in the process of closing\n" - + "Only use this option if you are sure the avatar is inactive and a normal kick user operation does not removed them", - KickUserCommand); + "kick user [message]", + "Kick a user off the simulator", KickUserCommand); m_console.Commands.AddCommand("Users", false, "show users", "show users [full]", @@ -339,6 +328,10 @@ namespace OpenSim "show circuits", "Show agent circuit data", HandleShow); + m_console.Commands.AddCommand("Comms", false, "show http-handlers", + "show http-handlers", + "Show all registered http handlers", HandleShow); + m_console.Commands.AddCommand("Comms", false, "show pending-objects", "show pending-objects", "Show # of objects on the pending queues of all scene viewers", HandleShow); @@ -423,7 +416,6 @@ namespace OpenSim { RunCommandScript(m_shutdownCommandsFile); } - base.ShutdownSpecific(); } @@ -461,17 +453,11 @@ namespace OpenSim /// name of avatar to kick private void KickUserCommand(string module, string[] cmdparams) { - bool force = false; - - OptionSet options = new OptionSet().Add("f|force", delegate (string v) { force = v != null; }); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 4) + if (cmdparams.Length < 4) return; string alert = null; - if (mainParams.Count > 4) + if (cmdparams.Length > 4) alert = String.Format("\n{0}\n", String.Join(" ", cmdparams, 4, cmdparams.Length - 4)); IList agents = SceneManager.GetCurrentSceneAvatars(); @@ -480,8 +466,8 @@ namespace OpenSim { RegionInfo regionInfo = presence.Scene.RegionInfo; - if (presence.Firstname.ToLower().Contains(mainParams[2].ToLower()) && - presence.Lastname.ToLower().Contains(mainParams[3].ToLower())) + if (presence.Firstname.ToLower().Contains(cmdparams[2].ToLower()) && + presence.Lastname.ToLower().Contains(cmdparams[3].ToLower())) { MainConsole.Instance.Output( String.Format( @@ -494,7 +480,7 @@ namespace OpenSim else presence.ControllingClient.Kick("\nYou have been logged out by an administrator.\n"); - presence.Scene.IncomingCloseAgent(presence.UUID, force); + presence.Scene.IncomingCloseAgent(presence.UUID); } } @@ -936,8 +922,7 @@ namespace OpenSim } else { - MainConsole.Instance.Output( - "Usage: debug scene active|scripting|collisions|physics|teleport true|false"); + MainConsole.Instance.Output("Usage: debug scene scripting|collisions|physics|teleport true|false"); } break; @@ -1017,6 +1002,33 @@ namespace OpenSim HandleShowCircuits(); break; + case "http-handlers": + System.Text.StringBuilder handlers = new System.Text.StringBuilder("Registered HTTP Handlers:\n"); + + handlers.AppendFormat("* XMLRPC:\n"); + foreach (String s in HttpServer.GetXmlRpcHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + handlers.AppendFormat("* HTTP:\n"); + List poll = HttpServer.GetPollServiceHandlerKeys(); + foreach (String s in HttpServer.GetHTTPHandlerKeys()) + handlers.AppendFormat("\t{0} {1}\n", s, (poll.Contains(s) ? "(poll service)" : string.Empty)); + + handlers.AppendFormat("* Agent:\n"); + foreach (String s in HttpServer.GetAgentHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + handlers.AppendFormat("* LLSD:\n"); + foreach (String s in HttpServer.GetLLSDHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + handlers.AppendFormat("* StreamHandlers ({0}):\n", HttpServer.GetStreamHandlerKeys().Count); + foreach (String s in HttpServer.GetStreamHandlerKeys()) + handlers.AppendFormat("\t{0}\n", s); + + MainConsole.Instance.Output(handlers.ToString()); + break; + case "modules": MainConsole.Instance.Output("The currently loaded shared modules are:"); foreach (IRegionModule module in m_moduleLoader.GetLoadedSharedModules) @@ -1111,7 +1123,7 @@ namespace OpenSim aCircuit.Name, aCircuit.child ? "child" : "root", aCircuit.circuitcode.ToString(), - aCircuit.IPAddress != null ? aCircuit.IPAddress.ToString() : "not set", + aCircuit.IPAddress.ToString(), aCircuit.Viewer); }); diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 7232383a77..d107b7a461 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -232,6 +232,8 @@ namespace OpenSim base.StartupSpecific(); + m_stats = StatsManager.SimExtraStats; + // Create a ModuleLoader instance m_moduleLoader = new ModuleLoader(m_config.Source); @@ -247,51 +249,51 @@ namespace OpenSim plugin.PostInitialise(); } - if (m_console != null) - { - StatsManager.RegisterConsoleCommands(m_console); - AddPluginCommands(m_console); - } + AddPluginCommands(); } - protected virtual void AddPluginCommands(CommandConsole console) + protected virtual void AddPluginCommands() { - List topics = GetHelpTopics(); - - foreach (string topic in topics) + // If console exists add plugin commands. + if (m_console != null) { - string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); + List topics = GetHelpTopics(); - // This is a hack to allow the user to enter the help command in upper or lowercase. This will go - // away at some point. - console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); - console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, - "help " + capitalizedTopic, - "Get help on plugin command '" + topic + "'", - HandleCommanderHelp); - - ICommander commander = null; - - Scene s = SceneManager.CurrentOrFirstScene; - - if (s != null && s.GetCommanders() != null) + foreach (string topic in topics) { - if (s.GetCommanders().ContainsKey(topic)) - commander = s.GetCommanders()[topic]; - } + string capitalizedTopic = char.ToUpper(topic[0]) + topic.Substring(1); - if (commander == null) - continue; + // This is a hack to allow the user to enter the help command in upper or lowercase. This will go + // away at some point. + m_console.Commands.AddCommand(capitalizedTopic, false, "help " + topic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); + m_console.Commands.AddCommand(capitalizedTopic, false, "help " + capitalizedTopic, + "help " + capitalizedTopic, + "Get help on plugin command '" + topic + "'", + HandleCommanderHelp); - foreach (string command in commander.Commands.Keys) - { - console.Commands.AddCommand(capitalizedTopic, false, - topic + " " + command, - topic + " " + commander.Commands[command].ShortHelp(), - String.Empty, HandleCommanderCommand); + ICommander commander = null; + + Scene s = SceneManager.CurrentOrFirstScene; + + if (s != null && s.GetCommanders() != null) + { + if (s.GetCommanders().ContainsKey(topic)) + commander = s.GetCommanders()[topic]; + } + + if (commander == null) + continue; + + foreach (string command in commander.Commands.Keys) + { + m_console.Commands.AddCommand(capitalizedTopic, false, + topic + " " + command, + topic + " " + commander.Commands[command].ShortHelp(), + String.Empty, HandleCommanderCommand); + } } } } @@ -621,7 +623,7 @@ namespace OpenSim if (account == null) { m_log.ErrorFormat( - "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first at the grid level."); + "[OPENSIM]: Unable to store account. If this simulator is connected to a grid, you must create the estate owner account first."); } else { diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index f6146a9171..650cd508f5 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -241,8 +241,8 @@ namespace OpenSim.Region.ClientStack.Linden m_HostCapsObj.RegisterHandler( "SEED", new RestStreamHandler("POST", capsBase + m_requestPath, SeedCapRequest, "SEED", null)); -// m_log.DebugFormat( -// "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); + m_log.DebugFormat( + "[CAPS]: Registered seed capability {0} for {1}", capsBase + m_requestPath, m_HostCapsObj.AgentID); //m_capsHandlers["MapLayer"] = // new LLSDStreamhandler("POST", @@ -337,12 +337,11 @@ namespace OpenSim.Region.ClientStack.Linden public string SeedCapRequest(string request, string path, string param, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - m_log.DebugFormat( - "[CAPS]: Received SEED caps request in {0} for agent {1}", m_regionName, m_HostCapsObj.AgentID); +// m_log.Debug("[CAPS]: Seed Caps Request in region: " + m_regionName); if (!m_Scene.CheckClient(m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint)) { - m_log.WarnFormat( + m_log.DebugFormat( "[CAPS]: Unauthorized CAPS client {0} from {1}", m_HostCapsObj.AgentID, httpRequest.RemoteIPEndPoint); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 5bbdce8345..e113c60fd1 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden //scene.CommsManager.HttpServer.AddLLSDHandler("/CAPS/EQG/", EventQueueFallBack); -// scene.EventManager.OnNewClient += OnNewClient; + scene.EventManager.OnNewClient += OnNewClient; // TODO: Leaving these open, or closing them when we // become a child is incorrect. It messes up TP in a big @@ -102,7 +102,6 @@ namespace OpenSim.Region.ClientStack.Linden // circuit is there. scene.EventManager.OnClientClosed += ClientClosed; - scene.EventManager.OnMakeChildAgent += MakeChildAgent; scene.EventManager.OnRegisterCaps += OnRegisterCaps; @@ -111,10 +110,10 @@ namespace OpenSim.Region.ClientStack.Linden false, "debug eq", "debug eq [0|1|2]", - "Turn on event queue debugging\n" - + " <= 0 - turns off all event queue logging\n" - + " >= 1 - turns on outgoing event logging\n" - + " >= 2 - turns on poll notification", + "Turn on event queue debugging" + + "<= 0 - turns off all event queue logging" + + ">= 1 - turns on outgoing event logging" + + ">= 2 - turns on poll notification", HandleDebugEq); } else @@ -227,6 +226,16 @@ namespace OpenSim.Region.ClientStack.Linden #endregion + private void OnNewClient(IClientAPI client) + { + //client.OnLogout += ClientClosed; + } + +// private void ClientClosed(IClientAPI client) +// { +// ClientClosed(client.AgentId); +// } + private void ClientClosed(UUID agentID, Scene scene) { // m_log.DebugFormat("[EVENTQUEUE]: Closed client {0} in region {1}", agentID, m_scene.RegionInfo.RegionName); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs index d604cf6f51..cd70410680 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/Tests/EventQueueTests.cs @@ -94,7 +94,7 @@ namespace OpenSim.Region.ClientStack.Linden.Tests UUID spId = TestHelpers.ParseTail(0x1); SceneHelpers.AddScenePresence(m_scene, spId); - m_scene.IncomingCloseAgent(spId, false); + m_scene.IncomingCloseAgent(spId); // TODO: Add more assertions for the other aspects of event queues Assert.That(MainServer.Instance.GetPollServiceHandlerKeys().Count, Is.EqualTo(0)); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs index fcac182f45..0a5ad0f02a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs @@ -109,7 +109,7 @@ namespace OpenSim.Region.ClientStack.Linden UUID capID = UUID.Random(); -// m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); + m_log.DebugFormat("[REGION CONSOLE]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); caps.RegisterHandler( "SimConsoleAsync", new ConsoleHandler("/CAPS/" + capID + "/", "SimConsoleAsync", agentID, this, m_scene)); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs index e22670b3a9..1b8535cacb 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/IncomingPacket.cs @@ -45,12 +45,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public Packet Packet; /// - /// No arg constructor. - /// - public IncomingPacket() {} - - /// - /// Constructor + /// Default constructor /// /// Reference to the client this packet came from /// Packet data diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index c9aa4ca404..ae9ed7f422 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -47,7 +47,6 @@ using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; using Timer = System.Timers.Timer; using AssetLandmark = OpenSim.Framework.AssetLandmark; -using RegionFlags = OpenMetaverse.RegionFlags; using Nini.Config; using System.IO; @@ -356,17 +355,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool m_deliverPackets = true; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; - - /// - /// We retain a single AgentUpdateArgs so that we can constantly reuse it rather than construct a new one for - /// every single incoming AgentUpdate. Every client sends 10 AgentUpdate UDP messages per second, even if it - /// is doing absolutely nothing. - /// - /// - /// This does mean that agent updates must be processed synchronously, at least for each client, and called methods - /// cannot retain a reference to it outside of that method. - /// - private AgentUpdateArgs m_lastAgentUpdateArgs; + private AgentUpdateArgs lastarg; protected Dictionary m_packetHandlers = new Dictionary(); protected Dictionary m_genericPacketHandlers = new Dictionary(); //PauPaw:Local Generic Message handlers @@ -521,18 +510,19 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public void Close() { - Close(true, false); + Close(true); } - public void Close(bool sendStop, bool force) + /// + /// Shut down the client view + /// + public void Close(bool sendStop) { // We lock here to prevent race conditions between two threads calling close simultaneously (e.g. // a simultaneous relog just as a client is being closed out due to no packet ack from the old connection. lock (CloseSyncLock) { - // We still perform a force close inside the sync lock since this is intended to attempt close where - // there is some unidentified connection problem, not where we have issues due to deadlock - if (!IsActive && !force) + if (!IsActive) return; IsActive = false; @@ -847,9 +837,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP OutPacket(mov, ThrottleOutPacketType.Unknown); } - public void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible) + public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) { ChatFromSimulatorPacket reply = (ChatFromSimulatorPacket)PacketPool.Instance.GetPacket(PacketType.ChatFromSimulator); reply.ChatData.Audible = audible; @@ -858,7 +847,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.ChatData.SourceType = source; reply.ChatData.Position = fromPos; reply.ChatData.FromName = Util.StringToBytes256(fromName); - reply.ChatData.OwnerID = ownerID; + reply.ChatData.OwnerID = fromAgentID; reply.ChatData.SourceID = fromAgentID; OutPacket(reply, ThrottleOutPacketType.Unknown); @@ -3996,8 +3985,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseAgentUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -4042,9 +4030,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { List blocks = terseUpdateBlocks.Value; - ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[blocks.Count]; @@ -4052,7 +4038,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP for (int i = 0; i < blocks.Count; i++) packet.ObjectData[i] = blocks[i]; - OutPacket(packet, ThrottleOutPacketType.Task, true, delegate(OutgoingPacket oPacket) { ResendPrimUpdates(terseUpdates.Value, oPacket); }); + OutPacket(packet, ThrottleOutPacketType.Task, true); } #endregion Packet Sending @@ -4549,7 +4535,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { returnblock[j] = new EstateOwnerMessagePacket.ParamListBlock(); } - j = 0; + j = 0; returnblock[j].Parameter = Utils.StringToBytes(estateID.ToString()); j++; returnblock[j].Parameter = Utils.StringToBytes(((int)Constants.EstateAccessCodex.EstateBans).ToString()); j++; @@ -5053,9 +5039,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.Z, -64.0f, 64.0f), data, pos); pos += 2; - ImprovedTerseObjectUpdatePacket.ObjectDataBlock block - = PacketPool.Instance.GetDataBlock(); - + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock(); block.Data = data; if (textureEntry != null && textureEntry.Length > 0) @@ -5305,18 +5289,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected virtual void RegisterLocalPacketHandlers() { AddLocalPacketHandler(PacketType.LogoutRequest, HandleLogout); - - // If AgentUpdate is ever handled asynchronously, then we will also need to construct a new AgentUpdateArgs - // for each AgentUpdate packet. AddLocalPacketHandler(PacketType.AgentUpdate, HandleAgentUpdate, false); - AddLocalPacketHandler(PacketType.ViewerEffect, HandleViewerEffect, false); AddLocalPacketHandler(PacketType.AgentCachedTexture, HandleAgentTextureCached, false); AddLocalPacketHandler(PacketType.MultipleObjectUpdate, HandleMultipleObjUpdate, false); AddLocalPacketHandler(PacketType.MoneyTransferRequest, HandleMoneyTransferRequest, false); AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); - AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); - AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); + AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest, false); + AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest, false); AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); @@ -5538,84 +5518,81 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Scene/Avatar - private bool HandleAgentUpdate(IClientAPI sener, Packet packet) + private bool HandleAgentUpdate(IClientAPI sener, Packet Pack) { if (OnAgentUpdate != null) { - AgentUpdatePacket agentUpdate = (AgentUpdatePacket)packet; + bool update = false; + AgentUpdatePacket agenUpdate = (AgentUpdatePacket)Pack; #region Packet Session and User Check - if (agentUpdate.AgentData.SessionID != SessionId || agentUpdate.AgentData.AgentID != AgentId) - { - PacketPool.Instance.ReturnPacket(packet); + if (agenUpdate.AgentData.SessionID != SessionId || agenUpdate.AgentData.AgentID != AgentId) return false; - } #endregion - bool update = false; - AgentUpdatePacket.AgentDataBlock x = agentUpdate.AgentData; + AgentUpdatePacket.AgentDataBlock x = agenUpdate.AgentData; - if (m_lastAgentUpdateArgs != null) + // We can only check when we have something to check + // against. + + if (lastarg != null) { - // These should be ordered from most-likely to - // least likely to change. I've made an initial - // guess at that. update = ( - (x.BodyRotation != m_lastAgentUpdateArgs.BodyRotation) || - (x.CameraAtAxis != m_lastAgentUpdateArgs.CameraAtAxis) || - (x.CameraCenter != m_lastAgentUpdateArgs.CameraCenter) || - (x.CameraLeftAxis != m_lastAgentUpdateArgs.CameraLeftAxis) || - (x.CameraUpAxis != m_lastAgentUpdateArgs.CameraUpAxis) || - (x.ControlFlags != m_lastAgentUpdateArgs.ControlFlags) || + (x.BodyRotation != lastarg.BodyRotation) || + (x.CameraAtAxis != lastarg.CameraAtAxis) || + (x.CameraCenter != lastarg.CameraCenter) || + (x.CameraLeftAxis != lastarg.CameraLeftAxis) || + (x.CameraUpAxis != lastarg.CameraUpAxis) || + (x.ControlFlags != lastarg.ControlFlags) || (x.ControlFlags != 0) || - (x.Far != m_lastAgentUpdateArgs.Far) || - (x.Flags != m_lastAgentUpdateArgs.Flags) || - (x.State != m_lastAgentUpdateArgs.State) || - (x.HeadRotation != m_lastAgentUpdateArgs.HeadRotation) || - (x.SessionID != m_lastAgentUpdateArgs.SessionID) || - (x.AgentID != m_lastAgentUpdateArgs.AgentID) + (x.Far != lastarg.Far) || + (x.Flags != lastarg.Flags) || + (x.State != lastarg.State) || + (x.HeadRotation != lastarg.HeadRotation) || + (x.SessionID != lastarg.SessionID) || + (x.AgentID != lastarg.AgentID) ); } else { - m_lastAgentUpdateArgs = new AgentUpdateArgs(); update = true; } + // These should be ordered from most-likely to + // least likely to change. I've made an initial + // guess at that. + if (update) { // m_log.DebugFormat("[LLCLIENTVIEW]: Triggered AgentUpdate for {0}", sener.Name); - m_lastAgentUpdateArgs.AgentID = x.AgentID; - m_lastAgentUpdateArgs.BodyRotation = x.BodyRotation; - m_lastAgentUpdateArgs.CameraAtAxis = x.CameraAtAxis; - m_lastAgentUpdateArgs.CameraCenter = x.CameraCenter; - m_lastAgentUpdateArgs.CameraLeftAxis = x.CameraLeftAxis; - m_lastAgentUpdateArgs.CameraUpAxis = x.CameraUpAxis; - m_lastAgentUpdateArgs.ControlFlags = x.ControlFlags; - m_lastAgentUpdateArgs.Far = x.Far; - m_lastAgentUpdateArgs.Flags = x.Flags; - m_lastAgentUpdateArgs.HeadRotation = x.HeadRotation; - m_lastAgentUpdateArgs.SessionID = x.SessionID; - m_lastAgentUpdateArgs.State = x.State; - + AgentUpdateArgs arg = new AgentUpdateArgs(); + arg.AgentID = x.AgentID; + arg.BodyRotation = x.BodyRotation; + arg.CameraAtAxis = x.CameraAtAxis; + arg.CameraCenter = x.CameraCenter; + arg.CameraLeftAxis = x.CameraLeftAxis; + arg.CameraUpAxis = x.CameraUpAxis; + arg.ControlFlags = x.ControlFlags; + arg.Far = x.Far; + arg.Flags = x.Flags; + arg.HeadRotation = x.HeadRotation; + arg.SessionID = x.SessionID; + arg.State = x.State; UpdateAgent handlerAgentUpdate = OnAgentUpdate; UpdateAgent handlerPreAgentUpdate = OnPreAgentUpdate; - + lastarg = arg; // save this set of arguments for nexttime if (handlerPreAgentUpdate != null) - OnPreAgentUpdate(this, m_lastAgentUpdateArgs); - + OnPreAgentUpdate(this, arg); if (handlerAgentUpdate != null) - OnAgentUpdate(this, m_lastAgentUpdateArgs); + OnAgentUpdate(this, arg); handlerAgentUpdate = null; handlerPreAgentUpdate = null; } } - PacketPool.Instance.ReturnPacket(packet); - return true; } @@ -5987,8 +5964,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP msgpack.MessageBlock.ID, msgpack.MessageBlock.Offline != 0 ? true : false, msgpack.MessageBlock.Position, - msgpack.MessageBlock.BinaryBucket, - true); + msgpack.MessageBlock.BinaryBucket); handlerInstantMessage(this, im); } @@ -9275,9 +9251,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - string method = Utils.BytesToString(messagePacket.MethodData.Method); - - switch (method) + switch (Utils.BytesToString(messagePacket.MethodData.Method)) { case "getinfo": if (((Scene)m_scene).Permissions.CanIssueEstateCommand(AgentId, false)) @@ -9593,17 +9567,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; default: - m_log.WarnFormat( - "[LLCLIENTVIEW]: EstateOwnerMessage: Unknown method {0} requested for {1} in {2}", - method, Name, Scene.Name); - - for (int i = 0; i < messagePacket.ParamList.Length; i++) - { - EstateOwnerMessagePacket.ParamListBlock block = messagePacket.ParamList[i]; - string data = (string)Utils.BytesToString(block.Parameter); - m_log.DebugFormat("[LLCLIENTVIEW]: Param {0}={1}", i, data); - } - + m_log.Error("EstateOwnerMessage: Unknown method requested\n" + messagePacket); return true; } @@ -11996,7 +11960,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP logPacket = false; if (DebugPacketLevel <= 50 - && (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) + & (packet.Type == PacketType.ImprovedTerseObjectUpdate || packet.Type == PacketType.ObjectUpdate)) logPacket = false; if (DebugPacketLevel <= 25 && packet.Type == PacketType.ObjectPropertiesFamily) @@ -12070,6 +12034,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!ProcessPacketMethod(packet)) m_log.Warn("[CLIENT]: unhandled packet " + packet.Type); + + PacketPool.Instance.ReturnPacket(packet); } private static PrimitiveBaseShape GetShapeFromAddPacket(ObjectAddPacket addPacket) @@ -12238,7 +12204,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { Kick(reason); Thread.Sleep(1000); - Disconnect(); + Close(); } public void Disconnect() @@ -12526,10 +12492,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); - ImprovedTerseObjectUpdatePacket packet - = (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket( - PacketType.ImprovedTerseObjectUpdate); - + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; packet.RegionData.TimeDilation = timeDilation; packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index b8951d966c..d6513c5403 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -37,7 +37,6 @@ using log4net; using Nini.Config; using OpenMetaverse.Packets; using OpenSim.Framework; -using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Scenes; using OpenMetaverse; @@ -101,11 +100,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// The measured resolution of Environment.TickCount public readonly float TickCountResolution; - /// Number of prim updates to put on the queue each time the /// OnQueueEmpty event is triggered for updates public readonly int PrimUpdatesPerCallback; - /// Number of texture packets to put on the queue each time the /// OnQueueEmpty event is triggered for textures public readonly int TextureSendLimit; @@ -127,37 +124,28 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Manages authentication for agent circuits private AgentCircuitManager m_circuitManager; - /// Reference to the scene this UDP server is attached to protected Scene m_scene; - /// The X/Y coordinates of the scene this UDP server is attached to private Location m_location; - /// The size of the receive buffer for the UDP socket. This value /// is passed up to the operating system and used in the system networking /// stack. Use zero to leave this value as the default private int m_recvBufferSize; - /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// Tracks whether or not a packet was sent each round so we know /// whether or not to sleep private bool m_packetSent; /// Environment.TickCount of the last time that packet stats were reported to the scene private int m_elapsedMSSinceLastStatReport = 0; - /// Environment.TickCount of the last time the outgoing packet handler executed private int m_tickLastOutgoingPacketHandler; - /// Keeps track of the number of elapsed milliseconds since the last time the outgoing packet handler looped private int m_elapsedMSOutgoingPacketHandler; - /// Keeps track of the number of 100 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed100MSOutgoingPacketHandler; - /// Keeps track of the number of 500 millisecond periods elapsed in the outgoing packet handler executed private int m_elapsed500MSOutgoingPacketHandler; @@ -171,9 +159,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected bool m_sendPing; private ExpiringCache> m_pendingCache = new ExpiringCache>(); - private Pool m_incomingPacketPool; - - private Stat m_incomingPacketPoolStat; private int m_defaultRTO = 0; private int m_maxRTO = 0; @@ -195,9 +180,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private IClientAPI m_currentIncomingClient; - public LLUDPServer( - IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, - IConfigSource configSource, AgentCircuitManager circuitManager) + public LLUDPServer(IPAddress listenIP, ref uint port, int proxyPortOffsetParm, bool allow_alternate_port, IConfigSource configSource, AgentCircuitManager circuitManager) : base(listenIP, (int)port) { #region Environment.TickCount Measurement @@ -219,7 +202,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_circuitManager = circuitManager; int sceneThrottleBps = 0; - bool usePools = false; IConfig config = configSource.Configs["ClientStack.LindenUDP"]; if (config != null) @@ -245,16 +227,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_pausedAckTimeout = 1000 * 300; // 5 minutes } - // FIXME: This actually only needs to be done once since the PacketPool is shared across all servers. - // However, there is no harm in temporarily doing it multiple times. - IConfig packetConfig = configSource.Configs["PacketPool"]; - if (packetConfig != null) - { - PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); - PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); - usePools = packetConfig.GetBoolean("RecycleBaseUDPPackets", usePools); - } - #region BinaryStats config = configSource.Configs["Statistics.Binary"]; m_shouldCollectStats = false; @@ -282,28 +254,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_throttle = new TokenBucket(null, sceneThrottleBps); ThrottleRates = new ThrottleRates(configSource); - - if (usePools) - EnablePools(); } public void Start() { - StartInbound(); - StartOutbound(); + if (m_scene == null) + throw new InvalidOperationException("[LLUDPSERVER]: Cannot LLUDPServer.Start() without an IScene reference"); - m_elapsedMSSinceLastStatReport = Environment.TickCount; - } - - private void StartInbound() - { m_log.InfoFormat( - "[LLUDPSERVER]: Starting inbound packet processing for the LLUDP server in {0} mode with UsePools = {1}", - m_asyncPacketHandling ? "asynchronous" : "synchronous", UsePools); + "[LLUDPSERVER]: Starting the LLUDP server in {0} mode", + m_asyncPacketHandling ? "asynchronous" : "synchronous"); - base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); + base.Start(m_recvBufferSize, m_asyncPacketHandling); - // This thread will process the packets received that are placed on the packetInbox + // Start the packet processing threads Watchdog.StartThread( IncomingPacketHandler, string.Format("Incoming Packets ({0})", m_scene.RegionInfo.RegionName), @@ -312,13 +276,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogIncomingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); - } - - private new void StartOutbound() - { - m_log.Info("[LLUDPSERVER]: Starting outbound packet processing for the LLUDP server"); - - base.StartOutbound(); Watchdog.StartThread( OutgoingPacketHandler, @@ -328,57 +285,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP true, GetWatchdogOutgoingAlarmData, Watchdog.DEFAULT_WATCHDOG_TIMEOUT_MS); - } - public void Stop() - { - m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); - base.StopOutbound(); - base.StopInbound(); - } - - protected override bool EnablePools() - { - if (!UsePools) - { - base.EnablePools(); - - m_incomingPacketPool = new Pool(() => new IncomingPacket(), 500); - - m_incomingPacketPoolStat - = new Stat( - "IncomingPacketPoolCount", - "Objects within incoming packet pool", - "The number of objects currently stored within the incoming packet pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => stat.Value = m_incomingPacketPool.Count, - StatVerbosity.Debug); - - StatsManager.RegisterStat(m_incomingPacketPoolStat); - - return true; - } - - return false; - } - - protected override bool DisablePools() - { - if (UsePools) - { - base.DisablePools(); - - StatsManager.DeregisterStat(m_incomingPacketPoolStat); - - // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. - - return true; - } - - return false; + m_elapsedMSSinceLastStatReport = Environment.TickCount; } /// @@ -403,6 +311,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_currentOutgoingClient != null ? m_currentOutgoingClient.Name : "none"); } + public new void Stop() + { + m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + m_scene.RegionInfo.RegionName); + base.Stop(); + } + public void AddScene(IScene scene) { if (m_scene != null) @@ -419,117 +333,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_scene = (Scene)scene; m_location = new Location(m_scene.RegionInfo.RegionHandle); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp start", - "debug lludp start ", - "Control LLUDP packet processing.", - "No effect if packet processing has already started.\n" - + "in - start inbound processing.\n" - + "out - start outbound processing.\n" - + "all - start in and outbound processing.\n", - HandleStartCommand); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp stop", - "debug lludp stop ", - "Stop LLUDP packet processing.", - "No effect if packet processing has already stopped.\n" - + "in - stop inbound processing.\n" - + "out - stop outbound processing.\n" - + "all - stop in and outbound processing.\n", - HandleStopCommand); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp pool", - "debug lludp pool ", - "Turn object pooling within the lludp component on or off.", - HandlePoolCommand); - - MainConsole.Instance.Commands.AddCommand( - "Debug", - false, - "debug lludp status", - "debug lludp status", - "Return status of LLUDP packet processing.", - HandleStatusCommand); - } - - private void HandleStartCommand(string module, string[] args) - { - if (args.Length != 4) - { - MainConsole.Instance.Output("Usage: debug lludp start "); - return; - } - - string subCommand = args[3]; - - if (subCommand == "in" || subCommand == "all") - StartInbound(); - - if (subCommand == "out" || subCommand == "all") - StartOutbound(); - } - - private void HandleStopCommand(string module, string[] args) - { - if (args.Length != 4) - { - MainConsole.Instance.Output("Usage: debug lludp stop "); - return; - } - - string subCommand = args[3]; - - if (subCommand == "in" || subCommand == "all") - StopInbound(); - - if (subCommand == "out" || subCommand == "all") - StopOutbound(); - } - - private void HandlePoolCommand(string module, string[] args) - { - if (args.Length != 4) - { - MainConsole.Instance.Output("Usage: debug lludp pool "); - return; - } - - string enabled = args[3]; - - if (enabled == "on") - { - if (EnablePools()) - MainConsole.Instance.OutputFormat("Packet pools enabled on {0}", m_scene.Name); - } - else if (enabled == "off") - { - if (DisablePools()) - MainConsole.Instance.OutputFormat("Packet pools disabled on {0}", m_scene.Name); - } - else - { - MainConsole.Instance.Output("Usage: debug lludp pool "); - } - } - - private void HandleStatusCommand(string module, string[] args) - { - MainConsole.Instance.OutputFormat( - "IN LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningInbound ? "enabled" : "disabled"); - - MainConsole.Instance.OutputFormat( - "OUT LLUDP packet processing for {0} is {1}", m_scene.Name, IsRunningOutbound ? "enabled" : "disabled"); - - MainConsole.Instance.OutputFormat("LLUDP pools in {0} are {1}", m_scene.Name, UsePools ? "on" : "off"); } public bool HandlesRegion(Location x) @@ -613,8 +416,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP byte[] data = packet.ToBytes(); SendPacketData(udpClient, data, packet.Type, category, method); } - - PacketPool.Instance.ReturnPacket(packet); } /// @@ -899,7 +700,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP LLUDPClient udpClient = null; Packet packet = null; int packetEnd = buffer.DataLength - 1; - IPEndPoint endPoint = (IPEndPoint)buffer.RemoteEndPoint; + IPEndPoint address = (IPEndPoint)buffer.RemoteEndPoint; #region Decoding @@ -909,7 +710,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // "[LLUDPSERVER]: Dropping undersized packet with {0} bytes received from {1} in {2}", // buffer.DataLength, buffer.RemoteEndPoint, m_scene.RegionInfo.RegionName); - return; // Drop undersized packet + return; // Drop undersizd packet } int headerLen = 7; @@ -932,13 +733,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP try { -// packet = Packet.BuildPacket(buffer.Data, ref packetEnd, -// // Only allocate a buffer for zerodecoding if the packet is zerocoded -// ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); - // If OpenSimUDPBase.UsePool == true (which is currently separate from the PacketPool) then we - // assume that packet construction does not retain a reference to byte[] buffer.Data (instead, all - // bytes are copied out). - packet = PacketPool.Instance.GetPacket(buffer.Data, ref packetEnd, + packet = Packet.BuildPacket(buffer.Data, ref packetEnd, // Only allocate a buffer for zerodecoding if the packet is zerocoded ((buffer.Data[0] & Helpers.MSG_ZEROCODED) != 0) ? new byte[4096] : null); } @@ -953,13 +748,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP return; // Drop short packet } - catch (Exception e) + catch(Exception e) { if (m_malformedCount < 100) m_log.DebugFormat("[LLUDPSERVER]: Dropped malformed packet: " + e.ToString()); - m_malformedCount++; - if ((m_malformedCount % 100000) == 0) m_log.DebugFormat("[LLUDPSERVER]: Received {0} malformed packets so far, probable network attack.", m_malformedCount); } @@ -979,7 +772,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // If there is already a client for this endpoint, don't process UseCircuitCode IClientAPI client = null; - if (!m_scene.TryGetClient(endPoint, out client) || !(client is LLClientView)) + if (!m_scene.TryGetClient(address, out client)) { // UseCircuitCode handling if (packet.Type == PacketType.UseCircuitCode) @@ -987,15 +780,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP // And if there is a UseCircuitCode pending, also drop it lock (m_pendingCache) { - if (m_pendingCache.Contains(endPoint)) + if (m_pendingCache.Contains(address)) return; - m_pendingCache.AddOrUpdate(endPoint, new Queue(), 60); + m_pendingCache.AddOrUpdate(address, new Queue(), 60); } - // We need to copy the endpoint so that it doesn't get changed when another thread reuses the - // buffer. - object[] array = new object[] { new IPEndPoint(endPoint.Address, endPoint.Port), packet }; + object[] array = new object[] { buffer, packet }; Util.FireAndForget(HandleUseCircuitCode, array); @@ -1007,7 +798,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_pendingCache) { Queue queue; - if (m_pendingCache.TryGetValue(endPoint, out queue)) + if (m_pendingCache.TryGetValue(address, out queue)) { //m_log.DebugFormat("[LLUDPSERVER]: Enqueued a {0} packet into the pending queue", packet.Type); queue.Enqueue(buffer); @@ -1043,10 +834,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Handle appended ACKs if (packet.Header.AppendedAcks && packet.Header.AckList != null) { -// m_log.DebugFormat( -// "[LLUDPSERVER]: Handling {0} appended acks from {1} in {2}", -// packet.Header.AckList.Length, client.Name, m_scene.Name); - for (int i = 0; i < packet.Header.AckList.Length; i++) udpClient.NeedAcks.Acknowledge(packet.Header.AckList[i], now, packet.Header.Resent); } @@ -1056,10 +843,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { PacketAckPacket ackPacket = (PacketAckPacket)packet; -// m_log.DebugFormat( -// "[LLUDPSERVER]: Handling {0} packet acks for {1} in {2}", -// ackPacket.Packets.Length, client.Name, m_scene.Name); - for (int i = 0; i < ackPacket.Packets.Length; i++) udpClient.NeedAcks.Acknowledge(ackPacket.Packets[i].ID, now, packet.Header.Resent); @@ -1073,10 +856,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Header.Reliable) { -// m_log.DebugFormat( -// "[LLUDPSERVER]: Adding ack request for {0} {1} from {2} in {3}", -// packet.Type, packet.Header.Sequence, client.Name, m_scene.Name); - udpClient.PendingAcks.Enqueue(packet.Header.Sequence); // This is a somewhat odd sequence of steps to pull the client.BytesSinceLastACK value out, @@ -1123,8 +902,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (packet.Type == PacketType.StartPingCheck) { -// m_log.DebugFormat("[LLUDPSERVER]: Handling ping from {0} in {1}", client.Name, m_scene.Name); - // We don't need to do anything else with ping checks StartPingCheckPacket startPing = (StartPingCheckPacket)packet; CompletePing(udpClient, startPing.PingID.PingID); @@ -1144,25 +921,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Ping Check Handling - IncomingPacket incomingPacket; - // Inbox insertion - if (UsePools) - { - incomingPacket = m_incomingPacketPool.GetObject(); - incomingPacket.Client = (LLClientView)client; - incomingPacket.Packet = packet; - } + if (packet.Type == PacketType.AgentUpdate || + packet.Type == PacketType.ChatFromViewer) + packetInbox.EnqueueHigh(new IncomingPacket((LLClientView)client, packet)); else - { - incomingPacket = new IncomingPacket((LLClientView)client, packet); - } - - if (incomingPacket.Packet.Type == PacketType.AgentUpdate || - incomingPacket.Packet.Type == PacketType.ChatFromViewer) - packetInbox.EnqueueHigh(incomingPacket); - else - packetInbox.EnqueueLow(incomingPacket); + packetInbox.EnqueueLow(new IncomingPacket((LLClientView)client, packet)); +// packetInbox.Enqueue(new IncomingPacket((LLClientView)client, packet)); } #region BinaryStats @@ -1248,19 +1013,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP private void HandleUseCircuitCode(object o) { - IPEndPoint endPoint = null; + IPEndPoint remoteEndPoint = null; IClientAPI client = null; try { // DateTime startTime = DateTime.Now; object[] array = (object[])o; - endPoint = (IPEndPoint)array[0]; + UDPPacketBuffer buffer = (UDPPacketBuffer)array[0]; UseCircuitCodePacket uccp = (UseCircuitCodePacket)array[1]; m_log.DebugFormat( "[LLUDPSERVER]: Handling UseCircuitCode request for circuit {0} to {1} from IP {2}", - uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, endPoint); + uccp.CircuitCode.Code, m_scene.RegionInfo.RegionName, buffer.RemoteEndPoint); + + remoteEndPoint = (IPEndPoint)buffer.RemoteEndPoint; AuthenticateResponse sessionInfo; if (IsClientAuthorized(uccp, out sessionInfo)) @@ -1271,13 +1038,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP uccp.CircuitCode.Code, uccp.CircuitCode.ID, uccp.CircuitCode.SessionID, - endPoint, + remoteEndPoint, sessionInfo); // Send ack straight away to let the viewer know that the connection is active. // The client will be null if it already exists (e.g. if on a region crossing the client sends a use // circuit code to the existing child agent. This is not particularly obvious. - SendAckImmediate(endPoint, uccp.Header.Sequence); + SendAckImmediate(remoteEndPoint, uccp.Header.Sequence); // We only want to send initial data to new clients, not ones which are being converted from child to root. if (client != null) @@ -1291,12 +1058,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP lock (m_pendingCache) { - if (!m_pendingCache.TryGetValue(endPoint, out queue)) + if (!m_pendingCache.TryGetValue(remoteEndPoint, out queue)) { m_log.DebugFormat("[LLUDPSERVER]: Client created but no pending queue present"); return; } - m_pendingCache.Remove(endPoint); + m_pendingCache.Remove(remoteEndPoint); } m_log.DebugFormat("[LLUDPSERVER]: Client created, processing pending queue, {0} entries", queue.Count); @@ -1314,9 +1081,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Don't create clients for unauthorized requesters. m_log.WarnFormat( "[LLUDPSERVER]: Ignoring connection request for {0} to {1} with unknown circuit code {2} from IP {3}", - uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, endPoint); + uccp.CircuitCode.ID, m_scene.RegionInfo.RegionName, uccp.CircuitCode.Code, remoteEndPoint); lock (m_pendingCache) - m_pendingCache.Remove(endPoint); + m_pendingCache.Remove(remoteEndPoint); } // m_log.DebugFormat( @@ -1328,7 +1095,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { m_log.ErrorFormat( "[LLUDPSERVER]: UseCircuitCode handling from endpoint {0}, client {1} {2} failed. Exception {3}{4}", - endPoint != null ? endPoint.ToString() : "n/a", + remoteEndPoint != null ? remoteEndPoint.ToString() : "n/a", client != null ? client.Name : "unknown", client != null ? client.AgentId.ToString() : "unknown", e.Message, @@ -1393,20 +1160,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP { IClientAPI client = null; - // We currently synchronize this code across the whole scene to avoid issues such as - // http://opensimulator.org/mantis/view.php?id=5365 However, once locking per agent circuit can be done - // consistently, this lock could probably be removed. - lock (this) + // In priciple there shouldn't be more than one thread here, ever. + // But in case that happens, we need to synchronize this piece of code + // because it's too important + lock (this) { if (!m_scene.TryGetClient(agentID, out client)) { LLUDPClient udpClient = new LLUDPClient(this, ThrottleRates, m_throttle, circuitCode, agentID, remoteEndPoint, m_defaultRTO, m_maxRTO); - + client = new LLClientView(m_scene, this, udpClient, sessionInfo, agentID, sessionID, circuitCode); client.OnLogout += LogoutHandler; - + ((LLClientView)client).DisableFacelights = m_disableFacelights; - + client.Start(); } } @@ -1445,7 +1212,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // on to en-US to avoid number parsing issues Culture.SetCurrentCulture(); - while (IsRunningInbound) + while (base.IsRunning) { m_scene.ThreadAlive(1); try @@ -1461,12 +1228,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (packetInbox.Dequeue(100, ref incomingPacket)) - { ProcessInPacket(incomingPacket);//, incomingPacket); Util.FireAndForget(ProcessInPacket, incomingPacket); - - if (UsePools) - m_incomingPacketPool.ReturnObject(incomingPacket); - } } catch (Exception ex) { @@ -1493,7 +1255,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Action generic every round Action clientPacketHandler = ClientOutgoingPacketHandler; - while (base.IsRunningOutbound) + while (base.IsRunning) { m_scene.ThreadAlive(2); try @@ -1761,7 +1523,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!client.IsLoggingOut) { client.IsLoggingOut = true; - client.Close(false, false); + client.Close(false); } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 8bd346149e..cfe7c9d09d 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -30,8 +30,6 @@ using System.Net; using System.Net.Sockets; using System.Threading; using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Monitoring; namespace OpenMetaverse { @@ -60,31 +58,17 @@ namespace OpenMetaverse /// Flag to process packets asynchronously or synchronously private bool m_asyncPacketHandling; - /// - /// Pool to use for handling data. May be null if UsePools = false; - /// - protected OpenSim.Framework.Pool m_pool; + /// The all important shutdown flag + private volatile bool m_shutdownFlag = true; - /// - /// Are we to use object pool(s) to reduce memory churn when receiving data? - /// - public bool UsePools { get; protected set; } - - /// Returns true if the server is currently listening for inbound packets, otherwise false - public bool IsRunningInbound { get; private set; } - - /// Returns true if the server is currently sending outbound packets, otherwise false - /// If IsRunningOut = false, then any request to send a packet is simply dropped. - public bool IsRunningOutbound { get; private set; } - - private Stat m_poolCountStat; + /// Returns true if the server is currently listening, otherwise false + public bool IsRunning { get { return !m_shutdownFlag; } } /// /// Default constructor /// /// Local IP address to bind the server to /// Port to listening for incoming UDP packets on - /// /// Are we to use an object pool to get objects for handing inbound data? public OpenSimUDPBase(IPAddress bindAddress, int port) { m_localBindAddress = bindAddress; @@ -92,7 +76,7 @@ namespace OpenMetaverse } /// - /// Start inbound UDP packet handling. + /// Start the UDP server /// /// The size of the receive buffer for /// the UDP socket. This value is passed up to the operating system @@ -107,11 +91,11 @@ namespace OpenMetaverse /// manner (not throwing an exception when the remote side resets the /// connection). This call is ignored on Mono where the flag is not /// necessary - public void StartInbound(int recvBufferSize, bool asyncPacketHandling) + public void Start(int recvBufferSize, bool asyncPacketHandling) { m_asyncPacketHandling = asyncPacketHandling; - if (!IsRunningInbound) + if (m_shutdownFlag) { const int SIO_UDP_CONNRESET = -1744830452; @@ -139,7 +123,8 @@ namespace OpenMetaverse m_udpSocket.Bind(ipep); - IsRunningInbound = true; + // we're not shutting down, we're starting up + m_shutdownFlag = false; // kick off an async receive. The Start() method will return, the // actual receives will occur asynchronously and will be caught in @@ -149,84 +134,28 @@ namespace OpenMetaverse } /// - /// Start outbound UDP packet handling. + /// Stops the UDP server /// - public void StartOutbound() + public void Stop() { - IsRunningOutbound = true; - } - - public void StopInbound() - { - if (IsRunningInbound) + if (!m_shutdownFlag) { // wait indefinitely for a writer lock. Once this is called, the .NET runtime // will deny any more reader locks, in effect blocking all other send/receive - // threads. Once we have the lock, we set IsRunningInbound = false to inform the other + // threads. Once we have the lock, we set shutdownFlag to inform the other // threads that the socket is closed. - IsRunningInbound = false; + m_shutdownFlag = true; m_udpSocket.Close(); } } - public void StopOutbound() - { - IsRunningOutbound = false; - } - - protected virtual bool EnablePools() - { - if (!UsePools) - { - m_pool = new Pool(() => new UDPPacketBuffer(), 500); - - m_poolCountStat - = new Stat( - "UDPPacketBufferPoolCount", - "Objects within the UDPPacketBuffer pool", - "The number of objects currently stored within the UDPPacketBuffer pool", - "", - "clientstack", - "packetpool", - StatType.Pull, - stat => stat.Value = m_pool.Count, - StatVerbosity.Debug); - - StatsManager.RegisterStat(m_poolCountStat); - - UsePools = true; - - return true; - } - - return false; - } - - protected virtual bool DisablePools() - { - if (UsePools) - { - UsePools = false; - StatsManager.DeregisterStat(m_poolCountStat); - - // We won't null out the pool to avoid a race condition with code that may be in the middle of using it. - - return true; - } - - return false; - } - private void AsyncBeginReceive() { - UDPPacketBuffer buf; + // allocate a packet buffer + //WrappedObject wrappedBuffer = Pool.CheckOut(); + UDPPacketBuffer buf = new UDPPacketBuffer(); - if (UsePools) - buf = m_pool.GetObject(); - else - buf = new UDPPacketBuffer(); - - if (IsRunningInbound) + if (!m_shutdownFlag) { try { @@ -279,7 +208,7 @@ namespace OpenMetaverse { // Asynchronous receive operations will complete here through the call // to AsyncBeginReceive - if (IsRunningInbound) + if (!m_shutdownFlag) { // Asynchronous mode will start another receive before the // callback for this packet is even fired. Very parallel :-) @@ -288,6 +217,8 @@ namespace OpenMetaverse // get the buffer that was created in AsyncBeginReceive // this is the received data + //WrappedObject wrappedBuffer = (WrappedObject)iar.AsyncState; + //UDPPacketBuffer buffer = wrappedBuffer.Instance; UDPPacketBuffer buffer = (UDPPacketBuffer)iar.AsyncState; try @@ -304,8 +235,7 @@ namespace OpenMetaverse catch (ObjectDisposedException) { } finally { - if (UsePools) - m_pool.ReturnObject(buffer); + //wrappedBuffer.Dispose(); // Synchronous mode waits until the packet callback completes // before starting the receive to fetch another packet @@ -318,7 +248,7 @@ namespace OpenMetaverse public void AsyncBeginSend(UDPPacketBuffer buf) { - if (IsRunningOutbound) + if (!m_shutdownFlag) { try { diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 556df305ab..109a8e1914 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -43,7 +43,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests /// This will contain basic tests for the LindenUDP client stack /// [TestFixture] - public class BasicCircuitTests : OpenSimTestCase + public class BasicCircuitTests { private Scene m_scene; private TestLLUDPServer m_udpServer; @@ -65,9 +65,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests } [SetUp] - public override void SetUp() + public void SetUp() { - base.SetUp(); m_scene = new SceneHelpers().SetupScene(); } @@ -144,7 +143,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests public void TestAddClient() { TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); +// XmlConfigurator.Configure(); AddUdpServer(); diff --git a/OpenSim/Region/ClientStack/RegionApplicationBase.cs b/OpenSim/Region/ClientStack/RegionApplicationBase.cs index 853b72d9e7..4672f8aa8a 100644 --- a/OpenSim/Region/ClientStack/RegionApplicationBase.cs +++ b/OpenSim/Region/ClientStack/RegionApplicationBase.cs @@ -76,7 +76,7 @@ namespace OpenSim.Region.ClientStack protected override void StartupSpecific() { - SceneManager = SceneManager.Instance; + SceneManager = new SceneManager(); m_clientStackManager = CreateClientStackManager(); Initialize(); diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index da1ff2ecbb..8a4fd8f041 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -57,36 +57,39 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Return the xfer uploader for the given transaction. + /// Return a xfer uploader if one does not already exist. /// - /// - /// If an uploader does not already exist for this transaction then it is created, otherwise the existing - /// uploader is returned. - /// /// - /// The asset xfer uploader - public AssetXferUploader RequestXferUploader(UUID transactionID) + /// + /// We must transfer the new asset ID into the uploader on creation, otherwise + /// we can see race conditions with other threads which can retrieve an item before it is updated with the new + /// asset id. + /// + /// + /// The xfer uploader requested. Null if one is already in existence. + /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple + /// transfers are made. Needs to be corrected. + /// + public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID) { - AssetXferUploader uploader; - lock (XferUploaders) { if (!XferUploaders.ContainsKey(transactionID)) { - uploader = new AssetXferUploader(this, m_Scene, transactionID, m_dumpAssetsToFile); + AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); // m_log.DebugFormat( // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); XferUploaders.Add(transactionID, uploader); - } - else - { - uploader = XferUploaders[transactionID]; + + return uploader; } } - return uploader; + m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); + + return null; } public void HandleXfer(ulong xferID, uint packetID, byte[] data) @@ -148,30 +151,117 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - AssetXferUploader uploader = RequestXferUploader(transactionID); + AssetXferUploader uploader = null; - uploader.RequestCreateInventoryItem( - remoteClient, folderID, callbackID, - description, name, invType, type, wearableType, nextOwnerMask); + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } - return true; + if (uploader != null) + { + uploader.RequestCreateInventoryItem( + remoteClient, transactionID, folderID, + callbackID, description, name, invType, type, + wearableType, nextOwnerMask); + + return true; + } + + return false; + } + + /// + /// Get an uploaded asset. If the data is successfully retrieved, + /// the transaction will be removed. + /// + /// + /// The asset if the upload has completed, null if it has not. + private AssetBase GetTransactionAsset(UUID transactionID) + { + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + { + AssetXferUploader uploader = XferUploaders[transactionID]; + AssetBase asset = uploader.GetAssetData(); + RemoveXferUploader(transactionID); + + return asset; + } + } + + return null; } public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { - AssetXferUploader uploader = RequestXferUploader(transactionID); + AssetXferUploader uploader = null; - uploader.RequestUpdateTaskInventoryItem(remoteClient, item); + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } + + if (uploader != null) + { + AssetBase asset = GetTransactionAsset(transactionID); + + // Only legacy viewers use this, and they prefer CAPS, which + // we have, so this really never runs. + // Allow it, but only for "safe" types. + if ((InventoryType)item.InvType != InventoryType.Notecard && + (InventoryType)item.InvType != InventoryType.LSL) + return; + + if (asset != null) + { +// m_log.DebugFormat( +// "[AGENT ASSETS TRANSACTIONS]: Updating item {0} in {1} for transaction {2}", +// item.Name, part.Name, transactionID); + + asset.FullID = UUID.Random(); + asset.Name = item.Name; + asset.Description = item.Description; + asset.Type = (sbyte)item.Type; + item.AssetID = asset.FullID; + + m_Scene.AssetService.Store(asset); + } + } + else + { + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}", + transactionID, item.Name, part.Name); + } } public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { - AssetXferUploader uploader = RequestXferUploader(transactionID); + AssetXferUploader uploader = null; - uploader.RequestUpdateInventoryItem(remoteClient, item); + lock (XferUploaders) + { + if (XferUploaders.ContainsKey(transactionID)) + uploader = XferUploaders[transactionID]; + } + + if (uploader != null) + { + uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); + } + else + { + m_log.ErrorFormat( + "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}", + transactionID, item.Name, remoteClient.Name); + } } } } diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 4bb8986e08..441c4ff405 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -215,7 +215,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction IClientAPI remoteClient, SceneObjectPart part, UUID transactionID, TaskInventoryItem item) { m_log.DebugFormat( - "[ASSET TRANSACTION MODULE] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", + "[TRANSACTIONS MANAGER] Called HandleTaskItemUpdateFromTransaction with item {0} in {1} for {2} in {3}", item.Name, part.Name, remoteClient.Name, m_Scene.RegionInfo.RegionName); AgentAssetTransactions transactions = @@ -274,8 +274,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); - AssetXferUploader uploader = transactions.RequestXferUploader(transaction); - uploader.StartUpload(remoteClient, assetID, transaction, type, data, storeLocal, tempFile); + AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); + + if (uploader != null) + { + uploader.Initialise(remoteClient, assetID, transaction, type, + data, storeLocal, tempFile); + } } /// diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index f6dd5af2d3..4cedfe6154 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -48,76 +48,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction }; private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Upload state. - /// - /// - /// New -> Uploading -> Complete - /// - private enum UploadState - { - New, - Uploading, - Complete - } - /// /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we /// are performing a delayed update. /// AgentAssetTransactions m_transactions; - private UploadState m_uploadState = UploadState.New; - private AssetBase m_asset; private UUID InventFolder = UUID.Zero; private sbyte invType = 0; - private bool m_createItem; - private uint m_createItemCallback; - - private bool m_updateItem; + private bool m_createItem = false; + private uint m_createItemCallback = 0; + private bool m_updateItem = false; private InventoryItemBase m_updateItemData; - private bool m_updateTaskItem; - private TaskInventoryItem m_updateTaskItemData; - private string m_description = String.Empty; private bool m_dumpAssetToFile; + private bool m_finished = false; private string m_name = String.Empty; -// private bool m_storeLocal; + private bool m_storeLocal; private uint nextPerm = 0; private IClientAPI ourClient; - - private UUID m_transactionID; - + private UUID TransactionID = UUID.Zero; private sbyte type = 0; private byte wearableType = 0; private byte[] m_oldData = null; public ulong XferID; private Scene m_Scene; - /// - /// AssetXferUploader constructor - /// - /// /param> - /// - /// - /// - /// If true then when the asset is uploaded it is dumped to a file with the format - /// String.Format("{6}_{7}_{0:d2}{1:d2}{2:d2}_{3:d2}{4:d2}{5:d2}.dat", - /// now.Year, now.Month, now.Day, now.Hour, now.Minute, - /// now.Second, m_asset.Name, m_asset.Type); - /// for debugging purposes. - /// - public AssetXferUploader( - AgentAssetTransactions transactions, Scene scene, UUID transactionID, bool dumpAssetToFile) + public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) { - m_asset = new AssetBase(); - m_transactions = transactions; - m_transactionID = transactionID; m_Scene = scene; + m_asset = new AssetBase() { FullID = assetID }; m_dumpAssetToFile = dumpAssetToFile; } @@ -163,50 +127,30 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } /// - /// Start asset transfer from the client + /// Initialise asset transfer from the client /// - /// - /// - /// - /// - /// - /// Optional data. If present then the asset is created immediately with this data - /// rather than requesting an upload from the client. The data must be longer than 2 bytes. - /// - /// - /// - public void StartUpload( - IClientAPI remoteClient, UUID assetID, UUID transaction, sbyte type, byte[] data, bool storeLocal, - bool tempFile) + /// + /// + /// + public void Initialise(IClientAPI remoteClient, UUID assetID, + UUID transaction, sbyte type, byte[] data, bool storeLocal, + bool tempFile) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); - lock (this) - { - if (m_uploadState != UploadState.New) - { - m_log.WarnFormat( - "[ASSET XFER UPLOADER]: Tried to start upload of asset {0}, transaction {1} for {2} but this is already in state {3}. Aborting.", - assetID, transaction, remoteClient.Name, m_uploadState); - - return; - } - - m_uploadState = UploadState.Uploading; - } - ourClient = remoteClient; - - m_asset.FullID = assetID; + m_asset.Name = "blank"; + m_asset.Description = "empty"; m_asset.Type = type; m_asset.CreatorID = remoteClient.AgentId.ToString(); m_asset.Data = data; m_asset.Local = storeLocal; m_asset.Temporary = tempFile; -// m_storeLocal = storeLocal; + TransactionID = transaction; + m_storeLocal = storeLocal; if (m_asset.Data.Length > 2) { @@ -231,35 +175,36 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction protected void SendCompleteMessage() { + ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, + m_asset.FullID); + // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create // message from other client UDP. lock (this) { - m_uploadState = UploadState.Complete; - - ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); - + m_finished = true; if (m_createItem) { - CompleteCreateItem(m_createItemCallback); + DoCreateItem(m_createItemCallback); } else if (m_updateItem) { - CompleteItemUpdate(m_updateItemData); + StoreAssetForItemUpdate(m_updateItemData); + + // Remove ourselves from the list of transactions if completion was delayed until the transaction + // was complete. + // TODO: Should probably do the same for create item. + m_transactions.RemoveXferUploader(TransactionID); } - else if (m_updateTaskItem) + else if (m_storeLocal) { - CompleteTaskItemUpdate(m_updateTaskItemData); + m_Scene.AssetService.Store(m_asset); } -// else if (m_storeLocal) -// { -// m_Scene.AssetService.Store(m_asset); -// } } m_log.DebugFormat( "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", - m_asset.FullID, m_transactionID); + m_asset.FullID, TransactionID); if (m_dumpAssetToFile) { @@ -287,37 +232,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } public void RequestCreateInventoryItem(IClientAPI remoteClient, - UUID folderID, uint callbackID, + UUID transactionID, UUID folderID, uint callbackID, string description, string name, sbyte invType, sbyte type, byte wearableType, uint nextOwnerMask) { - InventFolder = folderID; - m_name = name; - m_description = description; - this.type = type; - this.invType = invType; - this.wearableType = wearableType; - nextPerm = nextOwnerMask; - m_asset.Name = name; - m_asset.Description = description; - m_asset.Type = type; - - // We must lock to avoid a race with a separate thread uploading the asset. - lock (this) + if (TransactionID == transactionID) { - if (m_uploadState == UploadState.Complete) + InventFolder = folderID; + m_name = name; + m_description = description; + this.type = type; + this.invType = invType; + this.wearableType = wearableType; + nextPerm = nextOwnerMask; + m_asset.Name = name; + m_asset.Description = description; + m_asset.Type = type; + + // We must lock to avoid a race with a separate thread uploading the asset. + lock (this) { - CompleteCreateItem(callbackID); - } - else - { - m_createItem = true; //set flag so the inventory item is created when upload is complete - m_createItemCallback = callbackID; + if (m_finished) + { + DoCreateItem(callbackID); + } + else + { + m_createItem = true; //set flag so the inventory item is created when upload is complete + m_createItemCallback = callbackID; + } } } } - public void RequestUpdateInventoryItem(IClientAPI remoteClient, InventoryItemBase item) + public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) { // We must lock to avoid a race with a separate thread uploading the asset. lock (this) @@ -332,9 +280,9 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction item.AssetID = m_asset.FullID; m_Scene.InventoryService.UpdateItem(item); - if (m_uploadState == UploadState.Complete) + if (m_finished) { - CompleteItemUpdate(item); + StoreAssetForItemUpdate(item); } else { @@ -348,59 +296,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } - public void RequestUpdateTaskInventoryItem(IClientAPI remoteClient, TaskInventoryItem taskItem) - { - // We must lock to avoid a race with a separate thread uploading the asset. - lock (this) - { - m_asset.Name = taskItem.Name; - m_asset.Description = taskItem.Description; - m_asset.Type = (sbyte)taskItem.Type; - taskItem.AssetID = m_asset.FullID; - - if (m_uploadState == UploadState.Complete) - { - CompleteTaskItemUpdate(taskItem); - } - else - { - m_updateTaskItem = true; - m_updateTaskItemData = taskItem; - } - } - } - /// - /// Store the asset for the given item when it has been uploaded. + /// Store the asset for the given item. /// /// - private void CompleteItemUpdate(InventoryItemBase item) + private void StoreAssetForItemUpdate(InventoryItemBase item) { // m_log.DebugFormat( // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", // m_asset.FullID, item.Name, ourClient.Name); m_Scene.AssetService.Store(m_asset); - - m_transactions.RemoveXferUploader(m_transactionID); } - /// - /// Store the asset for the given task item when it has been uploaded. - /// - /// - private void CompleteTaskItemUpdate(TaskInventoryItem taskItem) - { -// m_log.DebugFormat( -// "[ASSET XFER UPLOADER]: Storing asset {0} for earlier task item update for {1} for {2}", -// m_asset.FullID, taskItem.Name, ourClient.Name); - - m_Scene.AssetService.Store(m_asset); - - m_transactions.RemoveXferUploader(m_transactionID); - } - - private void CompleteCreateItem(uint callbackID) + private void DoCreateItem(uint callbackID) { ValidateAssets(); m_Scene.AssetService.Store(m_asset); @@ -430,8 +339,6 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient.SendInventoryItemCreateUpdate(item, callbackID); else ourClient.SendAlertMessage("Unable to create inventory item"); - - m_transactions.RemoveXferUploader(m_transactionID); } private void ValidateAssets() @@ -509,7 +416,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// null if the asset has not finished uploading public AssetBase GetAssetData() { - if (m_uploadState == UploadState.Complete) + if (m_finished) { ValidateAssets(); return m_asset; @@ -562,3 +469,4 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction } } } + diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index d1a563cdce..7d7176fc07 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -52,7 +52,7 @@ using OpenSim.Services.Interfaces; [assembly: Addin("FlotsamAssetCache", "1.1")] [assembly: AddinDependency("OpenSim", "0.5")] -namespace OpenSim.Region.CoreModules.Asset +namespace Flotsam.RegionModules.AssetCache { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class FlotsamAssetCache : ISharedRegionModule, IImprovedAssetCache, IAssetService @@ -107,6 +107,8 @@ namespace OpenSim.Region.CoreModules.Asset private IAssetService m_AssetService; private List m_Scenes = new List(); + private bool m_DeepScanBeforePurge; + public FlotsamAssetCache() { m_InvalidChars.AddRange(Path.GetInvalidPathChars()); @@ -168,6 +170,8 @@ namespace OpenSim.Region.CoreModules.Asset m_CacheDirectoryTierLen = assetConfig.GetInt("CacheDirectoryTierLength", m_CacheDirectoryTierLen); m_CacheWarnAt = assetConfig.GetInt("CacheWarnAt", m_CacheWarnAt); + + m_DeepScanBeforePurge = assetConfig.GetBoolean("DeepScanBeforePurge", m_DeepScanBeforePurge); } m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Cache Directory {0}", m_CacheDirectory); @@ -515,10 +519,13 @@ namespace OpenSim.Region.CoreModules.Asset // Purge all files last accessed prior to this point DateTime purgeLine = DateTime.Now - m_FileExpiration; - // An asset cache may contain local non-temporary assets that are not in the asset service. Therefore, - // before cleaning up expired files we must scan the objects in the scene to make sure that we retain - // such local assets if they have not been recently accessed. - TouchAllSceneAssets(false); + // An optional deep scan at this point will ensure assets present in scenes, + // or referenced by objects in the scene, but not recently accessed + // are not purged. + if (m_DeepScanBeforePurge) + { + CacheScenes(); + } foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { @@ -711,14 +718,11 @@ namespace OpenSim.Region.CoreModules.Asset /// /// Iterates through all Scenes, doing a deep scan through assets - /// to update the access time of all assets present in the scene or referenced by assets - /// in the scene. + /// to cache all assets present in the scene or referenced by assets + /// in the scene /// - /// - /// If true, then assets scanned which are not found in cache are added to the cache. - /// - /// Number of distinct asset references found in the scene. - private int TouchAllSceneAssets(bool storeUncached) + /// + private int CacheScenes() { UuidGatherer gatherer = new UuidGatherer(m_AssetService); @@ -741,7 +745,7 @@ namespace OpenSim.Region.CoreModules.Asset { File.SetLastAccessTime(filename, DateTime.Now); } - else if (storeUncached) + else { m_AssetService.Get(assetID.ToString()); } @@ -869,14 +873,13 @@ namespace OpenSim.Region.CoreModules.Asset break; + case "assets": - m_log.Info("[FLOTSAM ASSET CACHE]: Ensuring assets are cached for all scenes."); + m_log.Info("[FLOTSAM ASSET CACHE]: Caching all assets, in all scenes."); Util.FireAndForget(delegate { - int assetReferenceTotal = TouchAllSceneAssets(true); - m_log.InfoFormat( - "[FLOTSAM ASSET CACHE]: Completed check with {0} assets.", - assetReferenceTotal); + int assetsCached = CacheScenes(); + m_log.InfoFormat("[FLOTSAM ASSET CACHE]: Completed Scene Caching, {0} assets found.", assetsCached); }); break; diff --git a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs index 1c2bfd0dff..c91b25fac2 100644 --- a/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs +++ b/OpenSim/Region/CoreModules/Asset/Tests/FlotsamAssetCacheTests.cs @@ -35,6 +35,7 @@ using Nini.Config; using NUnit.Framework; using OpenMetaverse; using OpenMetaverse.Assets; +using Flotsam.RegionModules.AssetCache; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index acd156e855..951afd740d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -285,20 +285,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } public bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) - { - if (!Enabled) - return false; - - if (AttachObjectInternal(sp, group, attachmentPt, silent, useAttachData, temp)) - { - m_scene.EventManager.TriggerOnAttach(group.LocalId, group.FromItemID, sp.UUID); - return true; - } - - return false; - } - - private bool AttachObjectInternal(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent, bool useAttachData, bool temp) { lock (sp.AttachmentsSyncLock) { @@ -474,11 +460,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId) - { - DetachSingleAttachmentToGround(sp, soLocalId, sp.AbsolutePosition, Quaternion.Identity); - } - - public void DetachSingleAttachmentToGround(IScenePresence sp, uint soLocalId, Vector3 absolutePos, Quaternion absoluteRot) { if (!Enabled) return; @@ -521,11 +502,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments so.FromItemID = UUID.Zero; SceneObjectPart rootPart = so.RootPart; - so.AbsolutePosition = absolutePos; - if (absoluteRot != Quaternion.Identity) - { - so.UpdateGroupRotationR(absoluteRot); - } + so.AbsolutePosition = sp.AbsolutePosition; so.AttachedAvatar = UUID.Zero; rootPart.SetParentLocalId(0); so.ClearPartAttachmentData(); @@ -639,9 +616,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (grp.HasGroupChanged) { - m_log.DebugFormat( - "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", - grp.UUID, grp.AttachmentPoint); +// m_log.DebugFormat( +// "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", +// grp.UUID, grp.AttachmentPoint); string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, scriptedState); @@ -885,7 +862,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // This will throw if the attachment fails try { - AttachObjectInternal(sp, objatt, attachmentPt, false, false, false); + AttachObject(sp, objatt, attachmentPt, false, false, false); } catch (Exception e) { @@ -956,9 +933,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID); item = m_scene.InventoryService.GetItem(item); - if (item == null) - return; - bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); if (changed && m_scene.AvatarFactory != null) { diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 4e9d3f9e57..d9a619d15b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs @@ -62,10 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests public class AttachmentsModuleTests : OpenSimTestCase { private AutoResetEvent m_chatEvent = new AutoResetEvent(false); -// private OSChatMessage m_osChatMessageReceived; - - // Used to test whether the operations have fired the attach event. Must be reset after each test. - private int m_numberOfAttachEventsFired; + private OSChatMessage m_osChatMessageReceived; [TestFixtureSetUp] public void FixtureInit() @@ -86,7 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests { // Console.WriteLine("Got chat [{0}]", oscm.Message); -// m_osChatMessageReceived = oscm; + m_osChatMessageReceived = oscm; m_chatEvent.Set(); } @@ -102,8 +99,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests "attachments-test-scene", TestHelpers.ParseTail(999), 1000, 1000, config); SceneHelpers.SetupSceneModules(scene, config, modules.ToArray()); - scene.EventManager.OnAttach += (localID, itemID, avatarID) => m_numberOfAttachEventsFired++; - return scene; } @@ -186,8 +181,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - m_numberOfAttachEventsFired = 0; - Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -196,7 +189,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup so = SceneHelpers.AddSceneObject(scene, attName, sp.UUID); - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.AttachObject(sp, so, (uint)AttachmentPoint.Chest, false, false, false); // Check status on scene presence @@ -224,8 +216,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); +// TestHelpers.DisableLogging(); } /// @@ -237,8 +228,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests TestHelpers.InMethod(); // TestHelpers.EnableLogging(); - m_numberOfAttachEventsFired = 0; - Scene scene = CreateTestScene(); UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(scene, 0x1); ScenePresence sp = SceneHelpers.AddScenePresence(scene, ua1); @@ -258,9 +247,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.HasAttachments(), Is.False); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -275,7 +261,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests InventoryItemBase attItem = CreateAttachmentItem(scene, ua1.PrincipalID, "att", 0x10, 0x20); - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); @@ -295,9 +280,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// @@ -356,8 +338,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests ISceneEntity so = scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); - - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.DetachSingleAttachmentToGround(sp, so.LocalId); // Check scene presence status @@ -373,9 +353,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests // Check object in scene Assert.That(scene.GetSceneObjectGroup("att"), Is.Not.Null); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } [Test] @@ -392,8 +369,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup so = (SceneObjectGroup)scene.AttachmentsModule.RezSingleAttachmentFromInventory( sp, attItem.ID, (uint)AttachmentPoint.Chest); - - m_numberOfAttachEventsFired = 0; scene.AttachmentsModule.DetachSingleAttachmentToInv(sp, so); // Check status on scene presence @@ -405,9 +380,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(sp.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo(0)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(0)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } /// @@ -489,14 +461,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; - m_numberOfAttachEventsFired = 0; - scene.IncomingCloseAgent(presence.UUID, false); + scene.IncomingCloseAgent(presence.UUID); // Check that we can't retrieve this attachment from the scene. Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -512,8 +480,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests AgentCircuitData acd = SceneHelpers.GenerateAgentData(ua1.PrincipalID); acd.Appearance = new AvatarAppearance(); acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); - - m_numberOfAttachEventsFired = 0; ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); Assert.That(presence.HasAttachments(), Is.True); @@ -536,9 +502,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(presence.Appearance.GetAttachpoint(attItem.ID), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(scene.GetSceneObjectGroups().Count, Is.EqualTo(1)); - - // Check events. We expect OnAttach to fire on login. - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(1)); } [Test] @@ -559,14 +522,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Vector3 newPosition = new Vector3(1, 2, 4); - m_numberOfAttachEventsFired = 0; scene.SceneGraph.UpdatePrimGroupPosition(attSo.LocalId, newPosition, sp.ControllingClient); Assert.That(attSo.AbsolutePosition, Is.EqualTo(sp.AbsolutePosition)); Assert.That(attSo.RootPart.AttachedPos, Is.EqualTo(newPosition)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } [Test] @@ -615,7 +574,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Vector3 teleportPosition = new Vector3(10, 11, 12); Vector3 teleportLookAt = new Vector3(20, 21, 22); - m_numberOfAttachEventsFired = 0; sceneA.RequestTeleportLocation( beforeTeleportSp.ControllingClient, sceneB.RegionInfo.RegionHandle, @@ -658,9 +616,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests Assert.That(actualSceneAAttachments.Count, Is.EqualTo(0)); Assert.That(sceneA.GetSceneObjectGroups().Count, Is.EqualTo(0)); - - // Check events - Assert.That(m_numberOfAttachEventsFired, Is.EqualTo(0)); } + + // I'm commenting this test because scene setup NEEDS InventoryService to + // be non-null + //[Test] +// public void T032_CrossAttachments() +// { +// TestHelpers.InMethod(); +// +// ScenePresence presence = scene.GetScenePresence(agent1); +// ScenePresence presence2 = scene2.GetScenePresence(agent1); +// presence2.AddAttachment(sog1); +// presence2.AddAttachment(sog2); +// +// ISharedRegionModule serialiser = new SerialiserModule(); +// SceneHelpers.SetupSceneModules(scene, new IniConfigSource(), serialiser); +// SceneHelpers.SetupSceneModules(scene2, new IniConfigSource(), serialiser); +// +// Assert.That(presence.HasAttachments(), Is.False, "Presence has attachments before cross"); +// +// //Assert.That(presence2.CrossAttachmentsIntoNewRegion(region1, true), Is.True, "Cross was not successful"); +// Assert.That(presence2.HasAttachments(), Is.False, "Presence2 objects were not deleted"); +// Assert.That(presence.HasAttachments(), Is.True, "Presence has not received new objects"); +// } } } diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index e3bf997a5d..4cb4370212 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -533,7 +533,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // Ignore ruth's assets if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) continue; - InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); baseItem = invService.GetItem(baseItem); diff --git a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs index 4407e40392..dbbb0aec7d 100644 --- a/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Chat/ChatModule.cs @@ -197,7 +197,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat string fromName = c.From; string fromNamePrefix = ""; UUID fromID = UUID.Zero; - UUID ownerID = UUID.Zero; string message = c.Message; IScene scene = c.Scene; UUID destination = c.Destination; @@ -225,16 +224,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat fromNamePrefix = m_adminPrefix; } destination = UUID.Zero; // Avatars cant "SayTo" - ownerID = c.Sender.AgentId; - break; case ChatSourceType.Object: fromID = c.SenderUUID; - if (c.SenderObject != null && c.SenderObject is SceneObjectPart) - ownerID = ((SceneObjectPart)c.SenderObject).OwnerID; - break; } @@ -268,16 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat // objects on a parcel with access restrictions if (c.Sender == null || Presencecheck.IsEitherBannedOrRestricted(c.Sender.AgentId) != true) { - if (destination != UUID.Zero) - { - if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, true)) - receiverIDs.Add(presence.UUID); - } - else - { - if (TrySendChatMessage(presence, fromPos, regionPos, fromID, ownerID, fromNamePrefix + fromName, c.Type, message, sourceType, false)) - receiverIDs.Add(presence.UUID); - } + if (TrySendChatMessage(presence, fromPos, regionPos, fromID, fromNamePrefix + fromName, c.Type, message, sourceType)) + receiverIDs.Add(presence.UUID); } } } @@ -338,7 +324,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat (((SceneObjectPart)c.SenderObject).OwnerID != client.AgentId)) return; - client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, fromID, + client.SendChatMessage(c.Message, (byte)cType, CenterOfRegion, fromName, fromID, (byte)sourceType, (byte)ChatAudibleLevel.Fully); receiverIDs.Add(client.AgentId); } @@ -355,20 +341,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat /// /// /param> /// - /// - /// Owner of the message. For at least some messages from objects, this has to be correctly filled with the owner's UUID. - /// This is the case for script error messages in viewer 3 since LLViewer change EXT-7762 - /// /// /// /// /// /// true if the message was sent to the receiver, false if it was not sent due to failing a /// precondition - protected virtual bool TrySendChatMessage( - ScenePresence presence, Vector3 fromPos, Vector3 regionPos, - UUID fromAgentID, UUID ownerID, string fromName, ChatTypeEnum type, - string message, ChatSourceType src, bool ignoreDistance) + protected virtual bool TrySendChatMessage(ScenePresence presence, Vector3 fromPos, Vector3 regionPos, + UUID fromAgentID, string fromName, ChatTypeEnum type, + string message, ChatSourceType src) { // don't send chat to child agents if (presence.IsChildAgent) return false; @@ -388,9 +369,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Chat } // TODO: should change so the message is sent through the avatar rather than direct to the ClientView - presence.ControllingClient.SendChatMessage( - message, (byte) type, fromPos, fromName, - fromAgentID, ownerID, (byte)src, (byte)ChatAudibleLevel.Fully); + presence.ControllingClient.SendChatMessage(message, (byte) type, fromPos, fromName, + fromAgentID, (byte)src, (byte)ChatAudibleLevel.Fully); return true; } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs index 5ec0ea94b4..d942e8742a 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.FirstName+" "+client.LastName, destID, (byte)211, false, String.Empty, - transactionID, false, new Vector3(), new byte[0], true), + transactionID, false, new Vector3(), new byte[0]), delegate(bool success) {} ); } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index f1903c3e27..24ec435d17 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Linq; using System.Reflection; using System.Threading; using log4net; @@ -483,9 +482,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends Util.FireAndForget( delegate { -// m_log.DebugFormat( -// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", -// friendList.Count, agentID, online); + m_log.DebugFormat( + "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", + friendList.Count, agentID, online); // Notify about this user status StatusNotify(friendList, agentID, online); @@ -496,36 +495,42 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected virtual void StatusNotify(List friendList, UUID userID, bool online) { - List friendStringIds = friendList.ConvertAll(friend => friend.Friend); - List remoteFriendStringIds = new List(); - foreach (string friendStringId in friendStringIds) + foreach (FriendInfo friend in friendList) { - UUID friendUuid; - if (UUID.TryParse(friendStringId, out friendUuid)) + UUID friendID; + if (UUID.TryParse(friend.Friend, out friendID)) { - if (LocalStatusNotification(userID, friendUuid, online)) + // Try local + if (LocalStatusNotification(userID, friendID, online)) continue; - remoteFriendStringIds.Add(friendStringId); + // The friend is not here [as root]. Let's forward. + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); + if (friendSessions != null && friendSessions.Length > 0) + { + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + { + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } + } + + if (friendSession != null) + { + GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); + m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); + } + } + + // Friend is not online. Ignore. } else { - m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friendStringId); - } - } - - // We do this regrouping so that we can efficiently send a single request rather than one for each - // friend in what may be a very large friends list. - PresenceInfo[] friendSessions = PresenceService.GetAgents(remoteFriendStringIds.ToArray()); - - foreach (PresenceInfo friendSession in friendSessions) - { - // let's guard against sessions-gone-bad - if (friendSession.RegionID != UUID.Zero) - { - GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); - m_FriendsSimConnector.StatusNotify(region, userID, friendSession.UserID, online); + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index 82816d918f..716cc69736 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs @@ -206,7 +206,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods transferModule.SendInstantMessage(new GridInstantMessage( m_scene, godID, "God", agentID, (byte)250, false, Utils.BytesToString(reason), UUID.Zero, true, - new Vector3(), new byte[] {(byte)kickflags}, true), + new Vector3(), new byte[] {(byte)kickflags}), delegate(bool success) {} ); } return; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index d0e88f697f..6587eadf57 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -166,7 +166,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (options.ContainsKey("verbose")) m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Saving item {0} {1} (asset UUID {2})", + "[INVENTORY ARCHIVER]: Saving item {0} {1} with asset {2}", inventoryItem.ID, inventoryItem.Name, inventoryItem.AssetID); string filename = path + CreateArchiveItemName(inventoryItem); @@ -337,14 +337,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { m_log.DebugFormat("[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetUuids.Count); - AssetsRequest ar - = new AssetsRequest( - new AssetsArchiver(m_archiveWriter), - m_assetUuids, m_scene.AssetService, - m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, - options, ReceivedAllAssets); - - Util.FireAndForget(o => ar.Execute()); + new AssetsRequest( + new AssetsArchiver(m_archiveWriter), + m_assetUuids, m_scene.AssetService, + m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, + options, ReceivedAllAssets).Execute(); } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 765b960c75..7d1fe68e8c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -35,7 +35,6 @@ using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; -using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -210,9 +209,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver Guid id, string firstName, string lastName, string invPath, string pass, string savePath, Dictionary options) { -// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, savePath)) -// return false; - if (m_scenes.Count > 0) { UserAccount userInfo = GetUserInfo(firstName, lastName, pass); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs index 00727a45a6..1056865590 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiveTestCase.cs @@ -82,25 +82,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests protected string m_item1Name = "Ray Gun Item"; protected string m_coaItemName = "Coalesced Item"; - - [TestFixtureSetUp] - public void FixtureSetup() - { - // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. - Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; - - ConstructDefaultIarBytesForTestLoad(); - } - - [TestFixtureTearDown] - public void TearDown() - { - // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple - // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression - // tests really shouldn't). - Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; - } - + [SetUp] public override void SetUp() { @@ -108,6 +90,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests m_iarStream = new MemoryStream(m_iarStreamBytes); } + [TestFixtureSetUp] + public void FixtureSetup() + { + ConstructDefaultIarBytesForTestLoad(); + } + protected void ConstructDefaultIarBytesForTestLoad() { // log4net.Config.XmlConfigurator.Configure(); diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index 06f6e49ab6..b112b6db52 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -49,7 +49,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { [TestFixture] public class InventoryArchiverTests : InventoryArchiveTestCase - { + { protected TestScene m_scene; protected InventoryArchiverModule m_archiverModule; @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests public void TestLoadCoalesecedItem() { TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); +// log4net.Config.XmlConfigurator.Configure(); UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL1, "password"); m_archiverModule.DearchiveInventory(m_uaLL1.FirstName, m_uaLL1.LastName, "/", "password", m_iarStream); @@ -350,38 +350,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL1.PrincipalID)); } -// /// -// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where -// /// an account exists with the same name as the creator, though not the same id. -// /// -// [Test] -// public void TestLoadIarV0_1SameNameCreator() -// { -// TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); -// -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); -// UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); -// -// m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); -// InventoryItemBase foundItem1 -// = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); -// -// Assert.That( -// foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), -// "Loaded item non-uuid creator doesn't match original"); -// Assert.That( -// foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), -// "Loaded item uuid creator doesn't match original"); -// Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), -// "Loaded item owner doesn't match inventory reciever"); -// -// AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); -// string xmlData = Utils.BytesToString(asset1.Data); -// SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); -// -// Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); -// } + /// + /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where + /// an account exists with the same name as the creator, though not the same id. + /// + [Test] + public void TestLoadIarV0_1SameNameCreator() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaMT, "meowfood"); + UserAccountHelpers.CreateUserWithInventory(m_scene, m_uaLL2, "hampshire"); + + m_archiverModule.DearchiveInventory(m_uaMT.FirstName, m_uaMT.LastName, "/", "meowfood", m_iarStream); + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, m_uaMT.PrincipalID, m_item1Name); + + Assert.That( + foundItem1.CreatorId, Is.EqualTo(m_uaLL2.PrincipalID.ToString()), + "Loaded item non-uuid creator doesn't match original"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(m_uaLL2.PrincipalID), + "Loaded item uuid creator doesn't match original"); + Assert.That(foundItem1.Owner, Is.EqualTo(m_uaMT.PrincipalID), + "Loaded item owner doesn't match inventory reciever"); + + AssetBase asset1 = m_scene.AssetService.Get(foundItem1.AssetID.ToString()); + string xmlData = Utils.BytesToString(asset1.Data); + SceneObjectGroup sog1 = SceneObjectSerializer.FromOriginalXmlFormat(xmlData); + + Assert.That(sog1.RootPart.CreatorID, Is.EqualTo(m_uaLL2.PrincipalID)); + } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index e26beec3e1..8176989e0b 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -38,15 +38,15 @@ using OpenSim.Services.Interfaces; namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { - public class InventoryTransferModule : ISharedRegionModule + public class InventoryTransferModule : IInventoryTransferModule, ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); /// private List m_Scenelist = new List(); -// private Dictionary m_AgentRegions = -// new Dictionary(); + private Dictionary m_AgentRegions = + new Dictionary(); private IMessageTransferModule m_TransferModule = null; private bool m_Enabled = true; @@ -76,12 +76,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Add(scene); -// scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += OnNewClient; -// scene.EventManager.OnClientClosed += ClientLoggedOut; + scene.EventManager.OnClientClosed += ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage += OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; + scene.EventManager.OnSetRootAgentScene += OnSetRootAgentScene; } public void RegionLoaded(Scene scene) @@ -96,9 +96,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_Scenelist.Clear(); scene.EventManager.OnNewClient -= OnNewClient; -// scene.EventManager.OnClientClosed -= ClientLoggedOut; + scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; + scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; } } } @@ -106,9 +106,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer public void RemoveRegion(Scene scene) { scene.EventManager.OnNewClient -= OnNewClient; -// scene.EventManager.OnClientClosed -= ClientLoggedOut; + scene.EventManager.OnClientClosed -= ClientLoggedOut; scene.EventManager.OnIncomingInstantMessage -= OnGridInstantMessage; -// scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; + scene.EventManager.OnSetRootAgentScene -= OnSetRootAgentScene; m_Scenelist.Remove(scene); } @@ -138,10 +138,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.OnInstantMessage += OnInstantMessage; } -// protected void OnSetRootAgentScene(UUID id, Scene scene) -// { -// m_AgentRegions[id] = scene; -// } + protected void OnSetRootAgentScene(UUID id, Scene scene) + { + m_AgentRegions[id] = scene; + } private Scene FindClientScene(UUID agentId) { @@ -313,11 +313,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); } } - - // XXX: This code was placed here to try and accomdate RLV which moves given folders named #RLV/~ - // to a folder called name in #RLV. However, this approach may not be ultimately correct - from analysis - // of Firestorm 4.2.2 on sending an InventoryOffered instead of TaskInventoryOffered (as was previously - // done), the viewer itself would appear to move and rename the folder, rather than the simulator doing it here. else if (im.dialog == (byte) InstantMessageDialog.TaskInventoryAccepted) { UUID destinationFolderID = UUID.Zero; @@ -329,16 +324,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (destinationFolderID != UUID.Zero) { - InventoryFolderBase destinationFolder = new InventoryFolderBase(destinationFolderID, client.AgentId); - if (destinationFolder == null) - { - m_log.WarnFormat( - "[INVENTORY TRANSFER]: TaskInventoryAccepted message from {0} in {1} specified folder {2} which does not exist", - client.Name, scene.Name, destinationFolderID); - - return; - } - IInventoryService invService = scene.InventoryService; UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip @@ -346,11 +331,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; - UUID? previousParentFolderID = null; if (item != null) // It's an item { - previousParentFolderID = item.Folder; item.Folder = destinationFolderID; invService.DeleteItems(item.Owner, new List() { item.ID }); @@ -363,22 +346,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null) // It's a folder { - previousParentFolderID = folder.ParentID; folder.ParentID = destinationFolderID; invService.MoveFolder(folder); } } - - // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). - if (previousParentFolderID != null) - { - InventoryFolderBase previousParentFolder - = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); - previousParentFolder = invService.GetFolder(previousParentFolder); - scene.SendInventoryUpdate(client, previousParentFolder, true, true); - - scene.SendInventoryUpdate(client, destinationFolder, true, true); - } } } else if ( @@ -399,11 +370,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; - UUID? previousParentFolderID = null; if (item != null && trashFolder != null) { - previousParentFolderID = item.Folder; item.Folder = trashFolder.ID; // Diva comment: can't we just update this item??? @@ -419,7 +388,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer if (folder != null & trashFolder != null) { - previousParentFolderID = folder.ParentID; folder.ParentID = trashFolder.ID; invService.MoveFolder(folder); client.SendBulkUpdateInventory(folder); @@ -440,16 +408,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer client.SendAgentAlertMessage("Unable to delete "+ "received inventory" + reason, false); } - // Tell client about updates to original parent and new parent (this should probably be factored with existing move item/folder code). - else if (previousParentFolderID != null) - { - InventoryFolderBase previousParentFolder - = new InventoryFolderBase((UUID)previousParentFolderID, client.AgentId); - previousParentFolder = invService.GetFolder(previousParentFolder); - scene.SendInventoryUpdate(client, previousParentFolder, true, true); - - scene.SendInventoryUpdate(client, trashFolder, true, true); - } if (im.dialog == (byte)InstantMessageDialog.InventoryDeclined) { @@ -468,69 +426,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer } } -// public bool NeedSceneCacheClear(UUID agentID, Scene scene) -// { -// if (!m_AgentRegions.ContainsKey(agentID)) -// { -// // Since we can get here two ways, we need to scan -// // the scenes here. This is somewhat more expensive -// // but helps avoid a nasty bug -// // -// -// foreach (Scene s in m_Scenelist) -// { -// ScenePresence presence; -// -// if (s.TryGetScenePresence(agentID, out presence)) -// { -// // If the agent is in this scene, then we -// // are being called twice in a single -// // teleport. This is wasteful of cycles -// // but harmless due to this 2nd level check -// // -// // If the agent is found in another scene -// // then the list wasn't current -// // -// // If the agent is totally unknown, then what -// // are we even doing here?? -// // -// if (s == scene) -// { -// //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); -// return true; -// } -// else -// { -// //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); -// return false; -// } -// } -// } -// //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); -// return true; -// } -// -// // The agent is left in current Scene, so we must be -// // going to another instance -// // -// if (m_AgentRegions[agentID] == scene) -// { -// //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); -// m_AgentRegions.Remove(agentID); -// return true; -// } -// -// // Another region has claimed the agent -// // -// //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); -// return false; -// } -// -// public void ClientLoggedOut(UUID agentID, Scene scene) -// { -// if (m_AgentRegions.ContainsKey(agentID)) -// m_AgentRegions.Remove(agentID); -// } + public bool NeedSceneCacheClear(UUID agentID, Scene scene) + { + if (!m_AgentRegions.ContainsKey(agentID)) + { + // Since we can get here two ways, we need to scan + // the scenes here. This is somewhat more expensive + // but helps avoid a nasty bug + // + + foreach (Scene s in m_Scenelist) + { + ScenePresence presence; + + if (s.TryGetScenePresence(agentID, out presence)) + { + // If the agent is in this scene, then we + // are being called twice in a single + // teleport. This is wasteful of cycles + // but harmless due to this 2nd level check + // + // If the agent is found in another scene + // then the list wasn't current + // + // If the agent is totally unknown, then what + // are we even doing here?? + // + if (s == scene) + { + //m_log.Debug("[INVTRANSFERMOD]: s == scene. Returning true in " + scene.RegionInfo.RegionName); + return true; + } + else + { + //m_log.Debug("[INVTRANSFERMOD]: s != scene. Returning false in " + scene.RegionInfo.RegionName); + return false; + } + } + } + //m_log.Debug("[INVTRANSFERMOD]: agent not in scene. Returning true in " + scene.RegionInfo.RegionName); + return true; + } + + // The agent is left in current Scene, so we must be + // going to another instance + // + if (m_AgentRegions[agentID] == scene) + { + //m_log.Debug("[INVTRANSFERMOD]: m_AgentRegions[agentID] == scene. Returning true in " + scene.RegionInfo.RegionName); + m_AgentRegions.Remove(agentID); + return true; + } + + // Another region has claimed the agent + // + //m_log.Debug("[INVTRANSFERMOD]: last resort. Returning false in " + scene.RegionInfo.RegionName); + return false; + } + + public void ClientLoggedOut(UUID agentID, Scene scene) + { + if (m_AgentRegions.ContainsKey(agentID)) + m_AgentRegions.Remove(agentID); + } /// /// diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index 9c369f6060..92cf9d1616 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs @@ -186,7 +186,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, sessionID, false, presence.AbsolutePosition, - new Byte[0], true); + new Byte[0]); m.RegionID = client.Scene.RegionInfo.RegionID.Guid; m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs index 1949459981..a889984daf 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/LureModule.cs @@ -173,7 +173,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.GodLikeRequestTeleport, false, message, dest, false, presence.AbsolutePosition, - new Byte[0], true); + new Byte[0]); } else { @@ -181,7 +181,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure client.FirstName+" "+client.LastName, targetid, (byte)InstantMessageDialog.RequestTeleport, false, message, dest, false, presence.AbsolutePosition, - new Byte[0], true); + new Byte[0]); } if (m_TransferModule != null) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 31e6ce9719..880b2cc2b2 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -327,14 +327,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - // Validate assorted conditions - string reason = string.Empty; - if (!ValidateGenericConditions(sp, reg, finalDestination, teleportFlags, out reason)) - { - sp.ControllingClient.SendTeleportFailed(reason); - return; - } - // // This is it // @@ -366,13 +358,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } - // Nothing to validate here - protected virtual bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) - { - reason = String.Empty; - return true; - } - /// /// Determines whether this instance is within the max transfer distance. /// @@ -488,11 +473,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // both regions if (sp.ParentID != (uint)0) sp.StandUp(); + else if (sp.Flying) teleportFlags |= (uint)TeleportFlags.IsFlying; - // At least on LL 3.3.4, this is not strictly necessary - a teleport will succeed without sending this to - // the viewer. However, it might mean that the viewer does not see the black teleport screen (untested). sp.ControllingClient.SendTeleportStart(teleportFlags); // the avatar.Close below will clear the child region list. We need this below for (possibly) @@ -568,11 +552,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // So let's wait Thread.Sleep(200); - // At least on LL 3.3.4 for teleports between different regions on the same simulator this appears - // unnecessary - teleport will succeed and SEED caps will be requested without it (though possibly - // only on TeleportFinish). This is untested for region teleport between different simulators - // though this probably also works. m_eqModule.EstablishAgentCommunication(sp.UUID, endPoint, capsPath); + } else { @@ -593,7 +574,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Updating agent..."); - if (!UpdateAgent(reg, finalDestination, agent, sp)) + if (!UpdateAgent(reg, finalDestination, agent)) { // Region doesn't take it m_log.WarnFormat( @@ -669,7 +650,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // an agent cannot teleport back to this region if it has teleported away. Thread.Sleep(3000); - sp.Scene.IncomingCloseAgent(sp.UUID, false); + sp.Scene.IncomingCloseAgent(sp.UUID); } else { @@ -677,14 +658,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Reset(); } - // Commented pending deletion since this method no longer appears to do anything at all -// // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! -// if (sp.Scene.NeedSceneCacheClear(sp.UUID)) -// { -// m_log.DebugFormat( -// "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", -// sp.UUID); -// } + // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! + if (sp.Scene.NeedSceneCacheClear(sp.UUID)) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: User {0} is going to another region, profile cache removed", + sp.UUID); + } m_entityTransferStateMachine.ResetFromTransit(sp.UUID); } @@ -721,7 +701,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return success; } - protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent, ScenePresence sp) + protected virtual bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agent) { return Scene.SimulationService.UpdateAgent(finalDestination, agent); } @@ -1033,7 +1013,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Scene initiatingScene) { Thread.Sleep(10000); - IMessageTransferModule im = initiatingScene.RequestModuleInterface(); if (im != null) { @@ -1046,22 +1025,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer (uint)(int)position.X, (uint)(int)position.Y, (uint)(int)position.Z); - - GridInstantMessage m - = new GridInstantMessage( - initiatingScene, - UUID.Zero, - "Region", - agent.UUID, - (byte)InstantMessageDialog.GodLikeRequestTeleport, - false, - "", - gotoLocation, - false, - new Vector3(127, 0, 0), - new Byte[0], - false); - + GridInstantMessage m = new GridInstantMessage(initiatingScene, UUID.Zero, + "Region", agent.UUID, + (byte)InstantMessageDialog.GodLikeRequestTeleport, false, + "", gotoLocation, false, new Vector3(127, 0, 0), + new Byte[0]); im.SendInstantMessage(m, delegate(bool success) { m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Client Initiating Teleport sending IM success = {0}", success); @@ -1223,11 +1191,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // the user may change their profile information in other region, // so the userinfo in UserProfileCache is not reliable any more, delete it // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! -// if (agent.Scene.NeedSceneCacheClear(agent.UUID)) -// { -// m_log.DebugFormat( -// "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); -// } + if (agent.Scene.NeedSceneCacheClear(agent.UUID)) + { + m_log.DebugFormat( + "[ENTITY TRANSFER MODULE]: User {0} is going to another region", agent.UUID); + } //m_log.Debug("AFTER CROSS"); //Scene.DumpChildrenSeeds(UUID); diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index b16c37ae5a..3010b59f13 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -54,59 +54,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private GatekeeperServiceConnector m_GatekeeperConnector; - protected bool m_RestrictAppearanceAbroad; - protected string m_AccountName; - protected List m_ExportedAppearances; - protected List m_Attachs; - - protected List ExportedAppearance - { - get - { - if (m_ExportedAppearances != null) - return m_ExportedAppearances; - - m_ExportedAppearances = new List(); - m_Attachs = new List(); - - string[] names = m_AccountName.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries); - - foreach (string name in names) - { - string[] parts = name.Trim().Split(); - if (parts.Length != 2) - { - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Wrong user account name format {0}. Specify 'First Last'", name); - return null; - } - UserAccount account = Scene.UserAccountService.GetUserAccount(UUID.Zero, parts[0], parts[1]); - if (account == null) - { - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unknown account {0}", m_AccountName); - return null; - } - AvatarAppearance a = Scene.AvatarService.GetAppearance(account.PrincipalID); - if (a != null) - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Successfully retrieved appearance for {0}", name); - - foreach (AvatarAttachment att in a.GetAttachments()) - { - InventoryItemBase item = new InventoryItemBase(att.ItemID, account.PrincipalID); - item = Scene.InventoryService.GetItem(item); - if (item != null) - a.SetAttachment(att.AttachPoint, att.ItemID, item.AssetID); - else - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to retrieve item {0} from inventory {1}", att.ItemID, name); - } - - m_ExportedAppearances.Add(a); - m_Attachs.AddRange(a.GetAttachments()); - } - - return m_ExportedAppearances; - } - } - #region ISharedRegionModule public override string Name @@ -125,18 +72,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { IConfig transferConfig = source.Configs["EntityTransfer"]; if (transferConfig != null) - { m_levelHGTeleport = transferConfig.GetInt("LevelHGTeleport", 0); - m_RestrictAppearanceAbroad = transferConfig.GetBoolean("RestrictAppearanceAbroad", false); - if (m_RestrictAppearanceAbroad) - { - m_AccountName = transferConfig.GetString("AccountForAppearance", string.Empty); - if (m_AccountName == string.Empty) - m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is on, but no account has been given for avatar appearance!"); - } - } - InitialiseCommon(source); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: {0} enabled.", Name); } @@ -148,36 +85,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer base.AddRegion(scene); if (m_Enabled) - { scene.RegisterModuleInterface(this); - scene.EventManager.OnIncomingSceneObject += OnIncomingSceneObject; - } - } - - void OnIncomingSceneObject(SceneObjectGroup so) - { - if (!so.IsAttachment) - return; - - if (so.Scene.UserManagementModule.IsLocalGridUser(so.AttachedAvatar)) - return; - - // foreign user - AgentCircuitData aCircuit = so.Scene.AuthenticateHandler.GetAgentCircuitData(so.AttachedAvatar); - if (aCircuit != null && (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) - { - if (aCircuit.ServiceURLs != null && aCircuit.ServiceURLs.ContainsKey("AssetServerURI")) - { - string url = aCircuit.ServiceURLs["AssetServerURI"].ToString(); - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Incoming attachement {0} for HG user {1} with asset server {2}", so.Name, so.AttachedAvatar, url); - Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(so.Scene.AssetService, url); - uuidGatherer.GatherAssetUuids(so, ids); - - foreach (KeyValuePair kvp in ids) - uuidGatherer.FetchAsset(kvp.Key); - } - } } protected override void OnNewClient(IClientAPI client) @@ -212,7 +120,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, region.RegionID); m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: region {0} flags: {1}", region.RegionID, flags); - if ((flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) + if ((flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) { m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Destination region {0} is hyperlink", region.RegionID); GridRegion real_destination = m_GatekeeperConnector.GetHyperlinkRegion(region, region.RegionID); @@ -232,7 +140,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return true; int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) return true; return false; @@ -245,8 +153,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // Log them out of this grid Scene.PresenceService.LogoutAgent(sp.ControllingClient.SessionId); - string userId = Scene.UserManagementModule.GetUserUUI(sp.UUID); - Scene.GridUserService.LoggedOut(userId, UUID.Zero, Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); } } @@ -256,11 +162,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer reason = string.Empty; logout = false; int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) + if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) { // this user is going to another grid - // for local users, check if HyperGrid teleport is allowed, based on user level - if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID) && sp.UserLevel < m_levelHGTeleport) + // check if HyperGrid teleport is allowed, based on user level + if (sp.UserLevel < m_levelHGTeleport) { m_log.WarnFormat("[HG ENTITY TRANSFER MODULE]: Unable to HG teleport agent due to insufficient UserLevel."); reason = "Hypergrid teleport not allowed"; @@ -294,124 +200,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer TeleportHome(id, client); } - protected override bool ValidateGenericConditions(ScenePresence sp, GridRegion reg, GridRegion finalDestination, uint teleportFlags, out string reason) - { - reason = "Please wear your grid's allowed appearance before teleporting to another grid"; - if (!m_RestrictAppearanceAbroad) - return true; - - // The rest is only needed for controlling appearance - - int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Framework.RegionFlags.Hyperlink) != 0) - { - // this user is going to another grid - if (Scene.UserManagementModule.IsLocalGridUser(sp.UUID)) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Checking generic appearance"); - - // Check wearables - for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) - { - for (int j = 0; j < sp.Appearance.Wearables[i].Count; j++) - { - if (sp.Appearance.Wearables[i] == null) - continue; - - bool found = false; - foreach (AvatarAppearance a in ExportedAppearance) - if (a.Wearables[i] != null) - { - found = true; - break; - } - - if (!found) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); - return false; - } - - found = false; - foreach (AvatarAppearance a in ExportedAppearance) - if (sp.Appearance.Wearables[i][j].AssetID == a.Wearables[i][j].AssetID) - { - found = true; - break; - } - - if (!found) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Wearable not allowed to go outside {0}", i); - return false; - } - } - } - - // Check attachments - foreach (AvatarAttachment att in sp.Appearance.GetAttachments()) - { - bool found = false; - foreach (AvatarAttachment att2 in m_Attachs) - { - if (att2.AssetID == att.AssetID) - { - found = true; - break; - } - } - if (!found) - { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Attachment not allowed to go outside {0}", att.AttachPoint); - return false; - } - } - } - } - - reason = string.Empty; - return true; - } - - - //protected override bool UpdateAgent(GridRegion reg, GridRegion finalDestination, AgentData agentData, ScenePresence sp) - //{ - // int flags = Scene.GridService.GetRegionFlags(Scene.RegionInfo.ScopeID, reg.RegionID); - // if (flags == -1 /* no region in DB */ || (flags & (int)OpenSim.Data.RegionFlags.Hyperlink) != 0) - // { - // // this user is going to another grid - // if (m_RestrictAppearanceAbroad && Scene.UserManagementModule.IsLocalGridUser(agentData.AgentID)) - // { - // // We need to strip the agent off its appearance - // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: RestrictAppearanceAbroad is ON. Sending generic appearance"); - - // // Delete existing npc attachments - // Scene.AttachmentsModule.DeleteAttachmentsFromScene(sp, false); - - // // XXX: We can't just use IAvatarFactoryModule.SetAppearance() yet since it doesn't transfer attachments - // AvatarAppearance newAppearance = new AvatarAppearance(ExportedAppearance, true); - // sp.Appearance = newAppearance; - - // // Rez needed npc attachments - // Scene.AttachmentsModule.RezAttachments(sp); - - - // IAvatarFactoryModule module = Scene.RequestModuleInterface(); - // //module.SendAppearance(sp.UUID); - // module.RequestRebake(sp, false); - - // Scene.AttachmentsModule.CopyAttachments(sp, agentData); - // agentData.Appearance = sp.Appearance; - // } - // } - - // foreach (AvatarAttachment a in agentData.Appearance.GetAttachments()) - // m_log.DebugFormat("[XXX]: {0}-{1}", a.ItemID, a.AssetID); - - - // return base.UpdateAgent(reg, finalDestination, agentData, sp); - //} - public override bool TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat( @@ -587,4 +375,4 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return region; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index f8ec6de85d..eaadc1b8be 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -71,19 +71,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Internal functions - public AssetMetadata FetchMetadata(string url, UUID assetID) + public AssetBase FetchAsset(string url, UUID assetID) { if (!url.EndsWith("/") && !url.EndsWith("=")) url = url + "/"; - AssetMetadata meta = m_scene.AssetService.GetMetadata(url + assetID.ToString()); + AssetBase asset = m_scene.AssetService.Get(url + assetID.ToString()); - if (meta != null) - m_log.DebugFormat("[HG ASSET MAPPER]: Fetched metadata for asset {0} of type {1} from {2} ", assetID, meta.Type, url); - else - m_log.DebugFormat("[HG ASSET MAPPER]: Unable to fetched metadata for asset {0} from {1} ", assetID, url); - - return meta; + if (asset != null) + { + m_log.DebugFormat("[HG ASSET MAPPER]: Copied asset {0} from {1} to local asset server. ", asset.ID, url); + return asset; + } + return null; } public bool PostAsset(string url, AssetBase asset) @@ -93,7 +93,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (!url.EndsWith("/") && !url.EndsWith("=")) url = url + "/"; - bool success = true; // See long comment in AssetCache.AddAsset if (!asset.Temporary || asset.Local) { @@ -104,7 +103,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // not having a global naming infrastructure AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type, asset.Metadata.CreatorID); Copy(asset, asset1); - asset1.ID = url + asset.ID; + try + { + asset1.ID = url + asset.ID; + } + catch + { + m_log.Warn("[HG ASSET MAPPER]: Oops."); + } AdjustIdentifiers(asset1.Metadata); if (asset1.Metadata.Type == (sbyte)AssetType.Object) @@ -112,17 +118,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess else asset1.Data = asset.Data; - string id = m_scene.AssetService.Store(asset1); - if (id == string.Empty) - { - m_log.DebugFormat("[HG ASSET MAPPER]: Asset server {0} did not accept {1}", url, asset.ID); - success = false; - } - else - m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); + m_scene.AssetService.Store(asset1); + m_log.DebugFormat("[HG ASSET MAPPER]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url); } - return success; - } + return true; + } else m_log.Warn("[HG ASSET MAPPER]: Tried to post asset to remote server, but asset not in local cache."); @@ -222,17 +222,28 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess public void Get(UUID assetID, UUID ownerID, string userAssetURL) { - // Get the item from the remote asset server onto the local AssetService + // Get the item from the remote asset server onto the local AssetCache + // and place an entry in m_assetMap - AssetMetadata meta = FetchMetadata(userAssetURL, assetID); - if (meta == null) - return; + m_log.Debug("[HG ASSET MAPPER]: Fetching object " + assetID + " from asset server " + userAssetURL); + AssetBase asset = FetchAsset(userAssetURL, assetID); - // The act of gathering UUIDs downloads the assets from the remote server - Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, userAssetURL); - uuidGatherer.GatherAssetUuids(assetID, (AssetType)meta.Type, ids); + if (asset != null) + { + // OK, now fetch the inside. + Dictionary ids = new Dictionary(); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL); + uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); + if (ids.ContainsKey(assetID)) + ids.Remove(assetID); + foreach (UUID uuid in ids.Keys) + FetchAsset(userAssetURL, uuid); + m_log.DebugFormat("[HG ASSET MAPPER]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL); + + } + else + m_log.Warn("[HG ASSET MAPPER]: Could not fetch asset from remote asset server " + userAssetURL); } @@ -246,23 +257,19 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (asset != null) { Dictionary ids = new Dictionary(); - HGUuidGatherer uuidGatherer = new HGUuidGatherer(m_scene.AssetService, string.Empty); + HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty); uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); - bool success = false; foreach (UUID uuid in ids.Keys) { asset = m_scene.AssetService.Get(uuid.ToString()); if (asset == null) m_log.DebugFormat("[HG ASSET MAPPER]: Could not find asset {0}", uuid); else - success = PostAsset(userAssetURL, asset); + PostAsset(userAssetURL, asset); } - // maybe all pieces got there... - if (!success) - m_log.DebugFormat("[HG ASSET MAPPER]: Problems posting item {0} to asset server {1}", assetID, userAssetURL); - else - m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); + // maybe all pieces got there... + m_log.DebugFormat("[HG ASSET MAPPER]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL); } else diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 6bb758ea07..cf72b58832 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_HomeURI = thisModuleConfig.GetString("HomeURI", m_HomeURI); m_OutboundPermission = thisModuleConfig.GetBoolean("OutboundPermission", true); m_ThisGatekeeper = thisModuleConfig.GetString("Gatekeeper", string.Empty); - m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", true); + m_RestrictInventoryAccessAbroad = thisModuleConfig.GetBoolean("RestrictInventoryAccessAbroad", false); } else m_log.Warn("[HG INVENTORY ACCESS MODULE]: HGInventoryAccessModule configs not found. ProfileServerURI not set!"); @@ -263,13 +263,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess //} // OK, we're done fetching. Pass it up to the default RezObject - SceneObjectGroup sog = base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, - RezSelected, RemoveItem, fromTaskID, attachment); - - if (sog == null) - remoteClient.SendAgentAlertMessage("Unable to rez: problem accessing inventory or locating assets", false); - - return sog; + return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, + RezSelected, RemoveItem, fromTaskID, attachment); } @@ -313,8 +308,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) { InventoryItemBase item = base.GetItem(agentID, itemID); - if (item == null) - return null; string userAssetServer = string.Empty; if (IsForeignUser(agentID, out userAssetServer)) @@ -351,7 +344,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private void ProcessInventoryForArriving(IClientAPI client) { - // No-op for now, but we may need to do something for freign users inventory } // @@ -398,7 +390,6 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess private void ProcessInventoryForLeaving(IClientAPI client) { - // No-op for now } #endregion diff --git a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs similarity index 65% rename from OpenSim/Region/ScriptEngine/Shared/ScriptException.cs rename to OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs index f55ba7e6c5..fcb544f27a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/ScriptException.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGUuidGatherer.cs @@ -26,19 +26,32 @@ */ using System; -using System.Runtime.Serialization; +using System.Collections.Generic; -namespace OpenSim.Region.ScriptEngine.Shared +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenMetaverse; + +namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { - [Serializable] - public class ScriptException : Exception + public class HGUuidGatherer : UuidGatherer { - public ScriptException() : base() {} + protected string m_assetServerURL; + protected HGAssetMapper m_assetMapper; - public ScriptException(string message) : base(message) {} + public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache) + { + m_assetMapper = assMap; + m_assetServerURL = assetServerURL; + } - public ScriptException(string message, Exception innerException) : base(message, innerException) {} - - public ScriptException(SerializationInfo info, StreamingContext context) :base(info, context) {} + protected override AssetBase GetAsset(UUID uuid) + { + if (string.Empty == m_assetServerURL) + return m_assetCache.Get(uuid.ToString()); + else + return m_assetMapper.FetchAsset(m_assetServerURL, uuid); + } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs index e4115851af..e135c21b79 100644 --- a/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Monitoring/MonitorModule.cs @@ -95,14 +95,14 @@ namespace OpenSim.Region.CoreModules.Framework.Monitoring { foreach (IMonitor monitor in m_staticMonitors) { - MainConsole.Instance.OutputFormat( + m_log.InfoFormat( "[MONITOR MODULE]: {0} reports {1} = {2}", m_scene.RegionInfo.RegionName, monitor.GetFriendlyName(), monitor.GetFriendlyValue()); } foreach (KeyValuePair tuple in m_scene.StatsReporter.GetExtraSimStats()) { - MainConsole.Instance.OutputFormat( + m_log.InfoFormat( "[MONITOR MODULE]: {0} reports {1} = {2}", m_scene.RegionInfo.RegionName, tuple.Key, tuple.Value); } diff --git a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs index fd8d5e32bd..65e4c90ba5 100755 --- a/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs +++ b/OpenSim/Region/CoreModules/Framework/Statistics/Logging/LogWriter.cs @@ -1,170 +1,161 @@ -/* - * 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.Text; -using log4net; - -namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging -{ - /// - /// Class for writing a high performance, high volume log file. - /// Sometimes, to debug, one has a high volume logging to do and the regular - /// log file output is not appropriate. - /// Create a new instance with the parameters needed and - /// call Write() to output a line. Call Close() when finished. - /// If created with no parameters, it will not log anything. - /// - public class LogWriter : IDisposable - { - public bool Enabled { get; private set; } - - private string m_logDirectory = "."; - private int m_logMaxFileTimeMin = 5; // 5 minutes - public String LogFileHeader { get; set; } - - private StreamWriter m_logFile = null; - private TimeSpan m_logFileLife; - private DateTime m_logFileEndTime; - private Object m_logFileWriteLock = new Object(); - - // set externally when debugging. If let 'null', this does not write any error messages. - public ILog ErrorLogger = null; - private string LogHeader = "[LOG WRITER]"; - - /// - /// Create a log writer that will not write anything. Good for when not enabled - /// but the write statements are still in the code. - /// - public LogWriter() - { - Enabled = false; - m_logFile = null; - } - - /// - /// Create a log writer instance. - /// - /// The directory to create the log file in. May be 'null' for default. - /// The characters that begin the log file name. May be 'null' for default. - /// Maximum age of a log file in minutes. If zero, will set default. - public LogWriter(string dir, string headr, int maxFileTime) - { - m_logDirectory = dir == null ? "." : dir; - - LogFileHeader = headr == null ? "log-" : headr; - - m_logMaxFileTimeMin = maxFileTime; - if (m_logMaxFileTimeMin < 1) - m_logMaxFileTimeMin = 5; - - m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); - m_logFileEndTime = DateTime.Now + m_logFileLife; - - Enabled = true; - } - - public void Dispose() - { - this.Close(); - } - - public void Close() - { - Enabled = false; - if (m_logFile != null) - { - m_logFile.Close(); - m_logFile.Dispose(); - m_logFile = null; - } - } - - public void Write(string line, params object[] args) - { - if (!Enabled) return; - Write(String.Format(line, args)); - } - - public void Flush() - { - if (!Enabled) return; - if (m_logFile != null) - { - m_logFile.Flush(); - } - } - - public void Write(string line) - { - if (!Enabled) return; - try - { - lock (m_logFileWriteLock) - { - DateTime now = DateTime.Now; - if (m_logFile == null || now > m_logFileEndTime) - { - if (m_logFile != null) - { - m_logFile.Close(); - m_logFile.Dispose(); - m_logFile = null; - } - - // First log file or time has expired, start writing to a new log file - m_logFileEndTime = now + m_logFileLife; - string path = (m_logDirectory.Length > 0 ? m_logDirectory - + System.IO.Path.DirectorySeparatorChar.ToString() : "") - + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); - m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); - } - if (m_logFile != null) - { - StringBuilder buff = new StringBuilder(line.Length + 25); - buff.Append(now.ToString("yyyyMMddHHmmssfff")); - // buff.Append(now.ToString("yyyyMMddHHmmss")); - buff.Append(","); - buff.Append(line); - buff.Append("\r\n"); - m_logFile.Write(buff.ToString()); - } - } - } - catch (Exception e) - { - if (ErrorLogger != null) - { - ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); - } - Enabled = false; - } - return; - } - } -} +/* + * 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.Text; +using log4net; + +namespace OpenSim.Region.CoreModules.Framework.Statistics.Logging +{ + /// + /// Class for writing a high performance, high volume log file. + /// Sometimes, to debug, one has a high volume logging to do and the regular + /// log file output is not appropriate. + /// Create a new instance with the parameters needed and + /// call Write() to output a line. Call Close() when finished. + /// If created with no parameters, it will not log anything. + /// + public class LogWriter : IDisposable + { + public bool Enabled { get; private set; } + + private string m_logDirectory = "."; + private int m_logMaxFileTimeMin = 5; // 5 minutes + public String LogFileHeader { get; set; } + + private StreamWriter m_logFile = null; + private TimeSpan m_logFileLife; + private DateTime m_logFileEndTime; + private Object m_logFileWriteLock = new Object(); + + // set externally when debugging. If let 'null', this does not write any error messages. + public ILog ErrorLogger = null; + private string LogHeader = "[LOG WRITER]"; + + /// + /// Create a log writer that will not write anything. Good for when not enabled + /// but the write statements are still in the code. + /// + public LogWriter() + { + Enabled = false; + m_logFile = null; + } + + /// + /// Create a log writer instance. + /// + /// The directory to create the log file in. May be 'null' for default. + /// The characters that begin the log file name. May be 'null' for default. + /// Maximum age of a log file in minutes. If zero, will set default. + public LogWriter(string dir, string headr, int maxFileTime) + { + m_logDirectory = dir == null ? "." : dir; + + LogFileHeader = headr == null ? "log-" : headr; + + m_logMaxFileTimeMin = maxFileTime; + if (m_logMaxFileTimeMin < 1) + m_logMaxFileTimeMin = 5; + + m_logFileLife = new TimeSpan(0, m_logMaxFileTimeMin, 0); + m_logFileEndTime = DateTime.Now + m_logFileLife; + + Enabled = true; + } + + public void Dispose() + { + this.Close(); + } + + public void Close() + { + Enabled = false; + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + } + + public void Write(string line, params object[] args) + { + if (!Enabled) return; + Write(String.Format(line, args)); + } + + public void Write(string line) + { + if (!Enabled) return; + try + { + lock (m_logFileWriteLock) + { + DateTime now = DateTime.Now; + if (m_logFile == null || now > m_logFileEndTime) + { + if (m_logFile != null) + { + m_logFile.Close(); + m_logFile.Dispose(); + m_logFile = null; + } + + // First log file or time has expired, start writing to a new log file + m_logFileEndTime = now + m_logFileLife; + string path = (m_logDirectory.Length > 0 ? m_logDirectory + + System.IO.Path.DirectorySeparatorChar.ToString() : "") + + String.Format("{0}{1}.log", LogFileHeader, now.ToString("yyyyMMddHHmmss")); + m_logFile = new StreamWriter(File.Open(path, FileMode.Append, FileAccess.Write)); + } + if (m_logFile != null) + { + StringBuilder buff = new StringBuilder(line.Length + 25); + buff.Append(now.ToString("yyyyMMddHHmmssfff")); + // buff.Append(now.ToString("yyyyMMddHHmmss")); + buff.Append(","); + buff.Append(line); + buff.Append("\r\n"); + m_logFile.Write(buff.ToString()); + } + } + } + catch (Exception e) + { + if (ErrorLogger != null) + { + ErrorLogger.ErrorFormat("{0}: FAILURE WRITING TO LOGFILE: {1}", LogHeader, e); + } + Enabled = false; + } + return; + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs index acefc97276..4eecaa2080 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs @@ -137,9 +137,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement ud.FirstName = words[0]; ud.LastName = "@" + words[1]; users.Add(ud); - // WARNING! that uriStr is not quite right... it may be missing the / at the end, - // which will cause trouble (duplicate entries on some tables). We should - // get the UUI instead from the UAS. TO BE FIXED. AddUser(userID, names[0], names[1], uriStr); m_log.DebugFormat("[USER MANAGEMENT MODULE]: User {0}@{1} found", words[0], words[1]); } diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index b4811dadce..f4ed67b864 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -31,7 +31,6 @@ using System.Reflection; using OpenSim.Framework; using OpenSim.Framework.Console; -using OpenSim.Region.ClientStack.LindenUDP; using OpenSim.Region.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -430,7 +429,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public void AddUser(UUID uuid, string first, string last, string homeURL) { - //m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); + // m_log.DebugFormat("[USER MANAGEMENT MODULE]: Adding user with id {0}, first {1}, last {2}, url {3}", uuid, first, last, homeURL); + AddUser(uuid, homeURL + ";" + first + " " + last); } @@ -553,8 +553,8 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement MainConsole.Instance.Output("-----------------------------------------------------------------------------"); foreach (KeyValuePair kvp in m_UserCache) { - MainConsole.Instance.Output(String.Format("{0} {1} {2} ({3})", - kvp.Key, kvp.Value.FirstName, kvp.Value.LastName, kvp.Value.HomeURL)); + MainConsole.Instance.Output(String.Format("{0} {1} {2}", + kvp.Key, kvp.Value.FirstName, kvp.Value.LastName)); } return; diff --git a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml index 6c73d911e0..424e0ab384 100644 --- a/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml +++ b/OpenSim/Region/CoreModules/Resources/CoreModulePlugin.addin.xml @@ -15,7 +15,6 @@ - diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs deleted file mode 100644 index fce9490da6..0000000000 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTexture.cs +++ /dev/null @@ -1,61 +0,0 @@ -/* - * 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.Drawing; -using OpenSim.Region.Framework.Interfaces; - -namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture -{ - public class DynamicTexture : IDynamicTexture - { - public string InputCommands { get; private set; } - public Uri InputUri { get; private set; } - public string InputParams { get; private set; } - public byte[] Data { get; private set; } - public Size Size { get; private set; } - public bool IsReuseable { get; private set; } - - public DynamicTexture(string inputCommands, string inputParams, byte[] data, Size size, bool isReuseable) - { - InputCommands = inputCommands; - InputParams = inputParams; - Data = data; - Size = size; - IsReuseable = isReuseable; - } - - public DynamicTexture(Uri inputUri, string inputParams, byte[] data, Size size, bool isReuseable) - { - InputUri = inputUri; - InputParams = inputParams; - Data = data; - Size = size; - IsReuseable = isReuseable; - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index 93a045eff7..18bd0186b8 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -42,29 +42,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture { public class DynamicTextureModule : IRegionModule, IDynamicTextureManager { -// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + //private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private const int ALL_SIDES = -1; public const int DISP_EXPIRE = 1; public const int DISP_TEMP = 2; - /// - /// If true then where possible dynamic textures are reused. - /// - public bool ReuseTextures { get; set; } - - /// - /// If false, then textures which have a low data size are not reused when ReuseTextures = true. - /// - /// - /// LL viewers 3.3.4 and before appear to not fully render textures pulled from the viewer cache if those - /// textures have a relatively high pixel surface but a small data size. Typically, this appears to happen - /// if the data size is smaller than the viewer's discard level 2 size estimate. So if this is setting is - /// false, textures smaller than the calculation in IsSizeReuseable are always regenerated rather than reused - /// to work around this problem. - public bool ReuseLowDataTextures { get; set; } - private Dictionary RegisteredScenes = new Dictionary(); private Dictionary RenderPlugins = @@ -72,15 +56,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture private Dictionary Updaters = new Dictionary(); - /// - /// Record dynamic textures that we can reuse for a given data and parameter combination rather than - /// regenerate. - /// - /// - /// Key is string.Format("{0}{1}", data - /// - private Cache m_reuseableDynamicTextures; - #region IDynamicTextureManager Members public void RegisterRender(string handleType, IDynamicTextureRender render) @@ -94,17 +69,17 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture /// /// Called by code which actually renders the dynamic texture to supply texture data. /// - /// - /// - public void ReturnData(UUID updaterId, IDynamicTexture texture) + /// + /// + public void ReturnData(UUID id, byte[] data) { DynamicTextureUpdater updater = null; lock (Updaters) { - if (Updaters.ContainsKey(updaterId)) + if (Updaters.ContainsKey(id)) { - updater = Updaters[updaterId]; + updater = Updaters[id]; } } @@ -113,16 +88,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture if (RegisteredScenes.ContainsKey(updater.SimUUID)) { Scene scene = RegisteredScenes[updater.SimUUID]; - UUID newTextureID = updater.DataReceived(texture.Data, scene); - - if (ReuseTextures - && !updater.BlendWithOldTexture - && texture.IsReuseable - && (ReuseLowDataTextures || IsDataSizeReuseable(texture))) - { - m_reuseableDynamicTextures.Store( - GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); - } + updater.DataReceived(data, scene); } } @@ -138,27 +104,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } - /// - /// Determines whether the texture is reuseable based on its data size. - /// - /// - /// This is a workaround for a viewer bug where very small data size textures relative to their pixel size - /// are not redisplayed properly when pulled from cache. The calculation here is based on the typical discard - /// level of 2, a 'rate' of 0.125 and 4 components (which makes for a factor of 0.5). - /// - /// - private bool IsDataSizeReuseable(IDynamicTexture texture) - { -// Console.WriteLine("{0} {1}", texture.Size.Width, texture.Size.Height); - int discardLevel2DataThreshold = (int)Math.Ceiling((texture.Size.Width >> 2) * (texture.Size.Height >> 2) * 0.5); - -// m_log.DebugFormat( -// "[DYNAMIC TEXTURE MODULE]: Discard level 2 threshold {0}, texture data length {1}", -// discardLevel2DataThreshold, texture.Data.Length); - - return discardLevel2DataThreshold < texture.Data.Length; - } - public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer) { @@ -222,61 +167,22 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) { - if (!RenderPlugins.ContainsKey(contentType)) - return UUID.Zero; - - Scene scene; - RegisteredScenes.TryGetValue(simID, out scene); - - if (scene == null) - return UUID.Zero; - - SceneObjectPart part = scene.GetSceneObjectPart(primID); - - if (part == null) - return UUID.Zero; - - // If we want to reuse dynamic textures then we have to ignore any request from the caller to expire - // them. - if (ReuseTextures) - disp = disp & ~DISP_EXPIRE; - - DynamicTextureUpdater updater = new DynamicTextureUpdater(); - updater.SimUUID = simID; - updater.PrimID = primID; - updater.ContentType = contentType; - updater.BodyData = data; - updater.UpdateTimer = updateTimer; - updater.UpdaterID = UUID.Random(); - updater.Params = extraParams; - updater.BlendWithOldTexture = SetBlending; - updater.FrontAlpha = AlphaValue; - updater.Face = face; - updater.Url = "Local image"; - updater.Disp = disp; - - object objReusableTextureUUID = null; - - if (ReuseTextures && !updater.BlendWithOldTexture) + if (RenderPlugins.ContainsKey(contentType)) { - string reuseableTextureKey = GenerateReusableTextureKey(data, extraParams); - objReusableTextureUUID = m_reuseableDynamicTextures.Get(reuseableTextureKey); + DynamicTextureUpdater updater = new DynamicTextureUpdater(); + updater.SimUUID = simID; + updater.PrimID = primID; + updater.ContentType = contentType; + updater.BodyData = data; + updater.UpdateTimer = updateTimer; + updater.UpdaterID = UUID.Random(); + updater.Params = extraParams; + updater.BlendWithOldTexture = SetBlending; + updater.FrontAlpha = AlphaValue; + updater.Face = face; + updater.Url = "Local image"; + updater.Disp = disp; - if (objReusableTextureUUID != null) - { - // If something else has removed this temporary asset from the cache, detect and invalidate - // our cached uuid. - if (scene.AssetService.GetMetadata(objReusableTextureUUID.ToString()) == null) - { - m_reuseableDynamicTextures.Invalidate(reuseableTextureKey); - objReusableTextureUUID = null; - } - } - } - - // We cannot reuse a dynamic texture if the data is going to be blended with something already there. - if (objReusableTextureUUID == null) - { lock (Updaters) { if (!Updaters.ContainsKey(updater.UpdaterID)) @@ -285,29 +191,11 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } -// m_log.DebugFormat( -// "[DYNAMIC TEXTURE MODULE]: Requesting generation of new dynamic texture for {0} in {1}", -// part.Name, part.ParentGroup.Scene.Name); - RenderPlugins[contentType].AsyncConvertData(updater.UpdaterID, data, extraParams); + return updater.UpdaterID; } - else - { -// m_log.DebugFormat( -// "[DYNAMIC TEXTURE MODULE]: Reusing cached texture {0} for {1} in {2}", -// objReusableTextureUUID, part.Name, part.ParentGroup.Scene.Name); - - // No need to add to updaters as the texture is always the same. Not that this functionality - // apppears to be implemented anyway. - updater.UpdatePart(part, (UUID)objReusableTextureUUID); - } - - return updater.UpdaterID; - } - - private string GenerateReusableTextureKey(string data, string extraParams) - { - return string.Format("{0}{1}", data, extraParams); + + return UUID.Zero; } public void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, @@ -327,13 +215,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void Initialise(Scene scene, IConfigSource config) { - IConfig texturesConfig = config.Configs["Textures"]; - if (texturesConfig != null) - { - ReuseTextures = texturesConfig.GetBoolean("ReuseDynamicTextures", false); - ReuseLowDataTextures = texturesConfig.GetBoolean("ReuseDynamicLowDataTextures", false); - } - if (!RegisteredScenes.ContainsKey(scene.RegionInfo.RegionID)) { RegisteredScenes.Add(scene.RegionInfo.RegionID, scene); @@ -343,11 +224,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public void PostInitialise() { - if (ReuseTextures) - { - m_reuseableDynamicTextures = new Cache(CacheMedium.Memory, CacheStrategy.Conservative); - m_reuseableDynamicTextures.DefaultTTL = new TimeSpan(24, 0, 0); - } } public void Close() @@ -392,61 +268,10 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture BodyData = null; } - /// - /// Update the given part with the new texture. - /// - /// - /// The old texture UUID. - /// - public UUID UpdatePart(SceneObjectPart part, UUID textureID) - { - UUID oldID; - - lock (part) - { - // mostly keep the values from before - Primitive.TextureEntry tmptex = part.Shape.Textures; - - // FIXME: Need to return the appropriate ID if only a single face is replaced. - oldID = tmptex.DefaultTexture.TextureID; - - if (Face == ALL_SIDES) - { - oldID = tmptex.DefaultTexture.TextureID; - tmptex.DefaultTexture.TextureID = textureID; - } - else - { - try - { - Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); - texface.TextureID = textureID; - tmptex.FaceTextures[Face] = texface; - } - catch (Exception) - { - tmptex.DefaultTexture.TextureID = textureID; - } - } - - // I'm pretty sure we always want to force this to true - // I'm pretty sure noone whats to set fullbright true if it wasn't true before. - // tmptex.DefaultTexture.Fullbright = true; - - part.UpdateTextureEntry(tmptex.GetBytes()); - } - - return oldID; - } - /// /// Called once new texture data has been received for this updater. /// - /// - /// - /// True if the data given is reuseable. - /// The asset UUID given to the incoming data. - public UUID DataReceived(byte[] data, Scene scene) + public void DataReceived(byte[] data, Scene scene) { SceneObjectPart part = scene.GetSceneObjectPart(PrimID); @@ -456,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture String.Format("DynamicTextureModule: Error preparing image using URL {0}", Url); scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Say, 0, part.ParentGroup.RootPart.AbsolutePosition, part.Name, part.UUID, false); - - return UUID.Zero; + return; } byte[] assetData = null; @@ -495,29 +319,56 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture IJ2KDecoder cacheLayerDecode = scene.RequestModuleInterface(); if (cacheLayerDecode != null) { - if (!cacheLayerDecode.Decode(asset.FullID, asset.Data)) - m_log.WarnFormat( - "[DYNAMIC TEXTURE MODULE]: Decoding of dynamically generated asset {0} for {1} in {2} failed", - asset.ID, part.Name, part.ParentGroup.Scene.Name); + cacheLayerDecode.Decode(asset.FullID, asset.Data); + cacheLayerDecode = null; } - UUID oldID = UpdatePart(part, asset.FullID); + UUID oldID = UUID.Zero; + + lock (part) + { + // mostly keep the values from before + Primitive.TextureEntry tmptex = part.Shape.Textures; + + // remove the old asset from the cache + oldID = tmptex.DefaultTexture.TextureID; + + if (Face == ALL_SIDES) + { + tmptex.DefaultTexture.TextureID = asset.FullID; + } + else + { + try + { + Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); + texface.TextureID = asset.FullID; + tmptex.FaceTextures[Face] = texface; + } + catch (Exception) + { + tmptex.DefaultTexture.TextureID = asset.FullID; + } + } + + // I'm pretty sure we always want to force this to true + // I'm pretty sure noone whats to set fullbright true if it wasn't true before. + // tmptex.DefaultTexture.Fullbright = true; + + part.UpdateTextureEntry(tmptex.GetBytes()); + } if (oldID != UUID.Zero && ((Disp & DISP_EXPIRE) != 0)) { - if (oldAsset == null) - oldAsset = scene.AssetService.Get(oldID.ToString()); - + if (oldAsset == null) oldAsset = scene.AssetService.Get(oldID.ToString()); if (oldAsset != null) { - if (oldAsset.Temporary) + if (oldAsset.Temporary == true) { scene.AssetService.Delete(oldID.ToString()); } } } - - return asset.FullID; } private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index 0b9174f799..56221aa9ce 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -58,7 +58,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public string body; public int responseCode; public string responseBody; - public string responseType = "text/plain"; //public ManualResetEvent ev; public bool requestDone; public int startTime; @@ -271,22 +270,6 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } } - public void HttpContentType(UUID request, string type) - { - lock (m_UrlMap) - { - if (m_RequestMap.ContainsKey(request)) - { - UrlData urlData = m_RequestMap[request]; - urlData.requests[request].responseType = type; - } - else - { - m_log.Info("[HttpRequestHandler] There is no http-in request with id " + request.ToString()); - } - } - } - public void HttpResponse(UUID request, int status, string body) { lock (m_RequestMap) diff --git a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs index 45e652788a..6f839485ec 100644 --- a/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LoadImageURL/LoadImageURLModule.cs @@ -32,7 +32,6 @@ using System.Net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; -using OpenSim.Region.CoreModules.Scripting.DynamicTexture; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using log4net; @@ -68,18 +67,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL return true; } -// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) -// { -// // We don't support conversion of body data. -// return false; -// } - - public IDynamicTexture ConvertUrl(string url, string extraParams) + public byte[] ConvertUrl(string url, string extraParams) { return null; } - public IDynamicTexture ConvertData(string bodyData, string extraParams) + public byte[] ConvertStream(Stream data, string extraParams) { return null; } @@ -172,11 +165,11 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL private void HttpRequestReturn(IAsyncResult result) { + RequestState state = (RequestState) result.AsyncState; WebRequest request = (WebRequest) state.Request; Stream stream = null; byte[] imageJ2000 = new byte[0]; - Size newSize = new Size(0, 0); try { @@ -189,43 +182,37 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL try { Bitmap image = new Bitmap(stream); + Size newsize; // TODO: make this a bit less hard coded if ((image.Height < 64) && (image.Width < 64)) { - newSize.Width = 32; - newSize.Height = 32; + newsize = new Size(32, 32); } else if ((image.Height < 128) && (image.Width < 128)) { - newSize.Width = 64; - newSize.Height = 64; + newsize = new Size(64, 64); } else if ((image.Height < 256) && (image.Width < 256)) { - newSize.Width = 128; - newSize.Height = 128; + newsize = new Size(128, 128); } else if ((image.Height < 512 && image.Width < 512)) { - newSize.Width = 256; - newSize.Height = 256; + newsize = new Size(256, 256); } else if ((image.Height < 1024 && image.Width < 1024)) { - newSize.Width = 512; - newSize.Height = 512; + newsize = new Size(512, 512); } else { - newSize.Width = 1024; - newSize.Height = 1024; + newsize = new Size(1024, 1024); } - using (Bitmap resize = new Bitmap(image, newSize)) - { - imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); - } + Bitmap resize = new Bitmap(image, newsize); + + imageJ2000 = OpenJPEG.EncodeFromImage(resize, true); } catch (Exception) { @@ -240,6 +227,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL } catch (WebException) { + } finally { @@ -248,14 +236,9 @@ namespace OpenSim.Region.CoreModules.Scripting.LoadImageURL stream.Close(); } } - - m_log.DebugFormat("[LOADIMAGEURLMODULE]: Returning {0} bytes of image data for request {1}", + m_log.DebugFormat("[LOADIMAGEURLMODULE] Returning {0} bytes of image data for request {1}", imageJ2000.Length, state.RequestID); - - m_textureManager.ReturnData( - state.RequestID, - new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( - request.RequestUri, null, imageJ2000, newSize, false)); + m_textureManager.ReturnData(state.RequestID, imageJ2000); } #region Nested type: RequestState diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index 41bacccf9e..9787c8c173 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -45,292 +45,31 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests { [TestFixture] - public class VectorRenderModuleTests : OpenSimTestCase + public class VectorRenderModuleTests { - Scene m_scene; - DynamicTextureModule m_dtm; - VectorRenderModule m_vrm; - - private void SetupScene(bool reuseTextures) - { - m_scene = new SceneHelpers().SetupScene(); - - m_dtm = new DynamicTextureModule(); - m_dtm.ReuseTextures = reuseTextures; -// m_dtm.ReuseLowDataTextures = reuseTextures; - - m_vrm = new VectorRenderModule(); - - SceneHelpers.SetupSceneModules(m_scene, m_dtm, m_vrm); - } - [Test] public void TestDraw() { TestHelpers.InMethod(); - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); + Scene scene = new SceneHelpers().SetupScene(); + DynamicTextureModule dtm = new DynamicTextureModule(); + VectorRenderModule vrm = new VectorRenderModule(); + SceneHelpers.SetupSceneModules(scene, dtm, vrm); + + SceneObjectGroup so = SceneHelpers.AddSceneObject(scene); UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, + dtm.AddDynamicTextureData( + scene.RegionInfo.RegionID, so.UUID, - m_vrm.GetContentType(), + vrm.GetContentType(), "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", "", 0); - Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDraw() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawDifferentExtraParams() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "alpha:250", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawContainingImage() - { - TestHelpers.InMethod(); - - string dtText - = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; - - SetupScene(false); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestDrawReusingTexture() - { - TestHelpers.InMethod(); - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - UUID originalTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;", - "", - 0); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } - - [Test] - public void TestRepeatSameDrawReusingTexture() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - /// - /// Test a low data dynamically generated texture such that it is treated as a low data texture that causes - /// problems for current viewers. - /// - /// - /// As we do not set DynamicTextureModule.ReuseLowDataTextures = true in this test, it should not reuse the - /// texture - /// - [Test] - public void TestRepeatSameDrawLowDataTexture() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "1024", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "1024", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawDifferentExtraParamsReusingTexture() - { - TestHelpers.InMethod(); - - string dtText = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World;"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "alpha:250", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } - - [Test] - public void TestRepeatSameDrawContainingImageReusingTexture() - { - TestHelpers.InMethod(); - - string dtText - = "PenColour BLACK; MoveTo 40,220; FontSize 32; Text Hello World; Image http://localhost/shouldnotexist.png"; - - SetupScene(true); - SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; - - m_dtm.AddDynamicTextureData( - m_scene.RegionInfo.RegionID, - so.UUID, - m_vrm.GetContentType(), - dtText, - "", - 0); - - Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index 673c2d1725..8b2f2f84e9 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -30,12 +30,10 @@ using System.Drawing; using System.Drawing.Imaging; using System.Globalization; using System.IO; -using System.Linq; using System.Net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.Imaging; -using OpenSim.Region.CoreModules.Scripting.DynamicTexture; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using log4net; @@ -47,13 +45,9 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { public class VectorRenderModule : IRegionModule, IDynamicTextureRender { - // These fields exist for testing purposes, please do not remove. -// private static bool s_flipper; -// private static byte[] s_asset1Data; -// private static byte[] s_asset2Data; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private string m_name = "VectorRenderModule"; private Scene m_scene; private IDynamicTextureManager m_textureManager; private Graphics m_graph; @@ -67,12 +61,12 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string GetContentType() { - return "vector"; + return ("vector"); } public string GetName() { - return Name; + return m_name; } public bool SupportsAsynchronous() @@ -80,20 +74,14 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender return true; } -// public bool AlwaysIdenticalConversion(string bodyData, string extraParams) -// { -// string[] lines = GetLines(bodyData); -// return lines.Any((str, r) => str.StartsWith("Image")); -// } - - public IDynamicTexture ConvertUrl(string url, string extraParams) + public byte[] ConvertUrl(string url, string extraParams) { return null; } - public IDynamicTexture ConvertData(string bodyData, string extraParams) + public byte[] ConvertStream(Stream data, string extraParams) { - return Draw(bodyData, extraParams); + return null; } public bool AsyncConvertUrl(UUID id, string url, string extraParams) @@ -103,28 +91,21 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public bool AsyncConvertData(UUID id, string bodyData, string extraParams) { - // XXX: This isn't actually being done asynchronously! - m_textureManager.ReturnData(id, ConvertData(bodyData, extraParams)); - + Draw(bodyData, id, extraParams); return true; } public void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize) { - lock (this) + using (Font myFont = new Font(fontName, fontSize)) { - using (Font myFont = new Font(fontName, fontSize)) + SizeF stringSize = new SizeF(); + lock (m_graph) { - SizeF stringSize = new SizeF(); - - // XXX: This lock may be unnecessary. - lock (m_graph) - { - stringSize = m_graph.MeasureString(text, myFont); - xSize = stringSize.Width; - ySize = stringSize.Height; - } + stringSize = m_graph.MeasureString(text, myFont); + xSize = stringSize.Width; + ySize = stringSize.Height; } } } @@ -163,13 +144,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender { m_textureManager.RegisterRender(GetContentType(), this); } - - // This code exists for testing purposes, please do not remove. -// s_asset1Data = m_scene.AssetService.Get("00000000-0000-1111-9999-000000000001").Data; -// s_asset1Data = m_scene.AssetService.Get("9f4acf0d-1841-4e15-bdb8-3a12efc9dd8f").Data; - - // Terrain dirt - smallest bin/assets file (6004 bytes) -// s_asset2Data = m_scene.AssetService.Get("b8d3965a-ad78-bf43-699b-bff8eca6c975").Data; } public void Close() @@ -178,7 +152,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender public string Name { - get { return "VectorRenderModule"; } + get { return m_name; } } public bool IsSharedModule @@ -188,7 +162,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender #endregion - private IDynamicTexture Draw(string data, string extraParams) + private void Draw(string data, UUID id, string extraParams) { // We need to cater for old scripts that didnt use extraParams neatly, they use either an integer size which represents both width and height, or setalpha // we will now support multiple comma seperated params in the form width:256,height:512,alpha:255 @@ -331,57 +305,40 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender Bitmap bitmap = null; Graphics graph = null; - bool reuseable = false; try { - // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, - // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to - // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were - // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed - // under lock. - lock (this) - { - if (alpha == 256) - bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); - else - bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + if (alpha == 256) + bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); + else + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + + graph = Graphics.FromImage(bitmap); - graph = Graphics.FromImage(bitmap); - - // this is really just to save people filling the - // background color in their scripts, only do when fully opaque - if (alpha >= 255) + // this is really just to save people filling the + // background color in their scripts, only do when fully opaque + if (alpha >= 255) + { + using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) { - using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) - { - graph.FillRectangle(bgFillBrush, 0, 0, width, height); - } + graph.FillRectangle(bgFillBrush, 0, 0, width, height); } - - for (int w = 0; w < bitmap.Width; w++) - { - if (alpha <= 255) - { - for (int h = 0; h < bitmap.Height; h++) - { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); - } - } - } - - GDIDraw(data, graph, altDataDelim, out reuseable); } + for (int w = 0; w < bitmap.Width; w++) + { + if (alpha <= 255) + { + for (int h = 0; h < bitmap.Height; h++) + { + bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); + } + } + } + + GDIDraw(data, graph, altDataDelim); + byte[] imageJ2000 = new byte[0]; - - // This code exists for testing purposes, please do not remove. -// if (s_flipper) -// imageJ2000 = s_asset1Data; -// else -// imageJ2000 = s_asset2Data; -// -// s_flipper = !s_flipper; try { @@ -394,24 +351,15 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender e.Message, e.StackTrace); } - return new OpenSim.Region.CoreModules.Scripting.DynamicTexture.DynamicTexture( - data, extraParams, imageJ2000, new Size(width, height), reuseable); + m_textureManager.ReturnData(id, imageJ2000); } finally { - // XXX: In testing, it appears that if multiple threads dispose of separate GDI+ objects simultaneously, - // the native malloc heap can become corrupted, possibly due to a double free(). This may be due to - // bugs in the underlying libcairo used by mono's libgdiplus.dll on Linux/OSX. These problems were - // seen with both libcario 1.10.2-6.1ubuntu3 and 1.8.10-2ubuntu1. They go away if disposal is perfomed - // under lock. - lock (this) - { - if (graph != null) - graph.Dispose(); - - if (bitmap != null) - bitmap.Dispose(); - } + if (graph != null) + graph.Dispose(); + + if (bitmap != null) + bitmap.Dispose(); } } @@ -470,21 +418,8 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } */ - /// - /// Split input data into discrete command lines. - /// - /// - /// - /// - private string[] GetLines(string data, char dataDelim) + private void GDIDraw(string data, Graphics graph, char dataDelim) { - char[] lineDelimiter = { dataDelim }; - return data.Split(lineDelimiter); - } - - private void GDIDraw(string data, Graphics graph, char dataDelim, out bool reuseable) - { - reuseable = true; Point startPoint = new Point(0, 0); Point endPoint = new Point(0, 0); Pen drawPen = null; @@ -499,9 +434,11 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender myFont = new Font(fontName, fontSize); myBrush = new SolidBrush(Color.Black); + char[] lineDelimiter = {dataDelim}; char[] partsDelimiter = {','}; + string[] lines = data.Split(lineDelimiter); - foreach (string line in GetLines(data, dataDelim)) + foreach (string line in lines) { string nextLine = line.Trim(); //replace with switch, or even better, do some proper parsing @@ -532,10 +469,6 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } else if (nextLine.StartsWith("Image")) { - // We cannot reuse any generated texture involving fetching an image via HTTP since that image - // can change. - reuseable = false; - float x = 0; float y = 0; GetParams(partsDelimiter, ref nextLine, 5, ref x, ref y); diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index e167e312da..07bb291241 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -28,7 +28,6 @@ using System; using System.Collections; using System.Collections.Generic; -using System.Text.RegularExpressions; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; @@ -173,42 +172,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm /// UUID of the SceneObjectPart /// channel to listen on /// name to filter on - /// - /// key to filter on (user given, could be totally faked) - /// + /// key to filter on (user given, could be totally faked) /// msg to filter on /// number of the scripts handle - public int Listen(uint localID, UUID itemID, UUID hostID, int channel, - string name, UUID id, string msg) + public int Listen(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) { - return m_listenerManager.AddListener(localID, itemID, hostID, - channel, name, id, msg); - } - - /// - /// Create a listen event callback with the specified filters. - /// The parameters localID,itemID are needed to uniquely identify - /// the script during 'peek' time. Parameter hostID is needed to - /// determine the position of the script. - /// - /// localID of the script engine - /// UUID of the script engine - /// UUID of the SceneObjectPart - /// channel to listen on - /// name to filter on - /// - /// key to filter on (user given, could be totally faked) - /// - /// msg to filter on - /// - /// Bitfield indicating which strings should be processed as regex. - /// - /// number of the scripts handle - public int Listen(uint localID, UUID itemID, UUID hostID, int channel, - string name, UUID id, string msg, int regexBitfield) - { - return m_listenerManager.AddListener(localID, itemID, hostID, - channel, name, id, msg, regexBitfield); + return m_listenerManager.AddListener(localID, itemID, hostID, channel, name, id, msg); } /// @@ -357,7 +326,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (channel == 0) { // Channel 0 goes to viewer ONLY - m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, target, false, false); + m_scene.SimChat(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false, false, target); return true; } @@ -501,25 +470,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_curlisteners = 0; } - public int AddListener(uint localID, UUID itemID, UUID hostID, - int channel, string name, UUID id, string msg) - { - return AddListener(localID, itemID, hostID, channel, name, id, - msg, 0); - } - - public int AddListener(uint localID, UUID itemID, UUID hostID, - int channel, string name, UUID id, string msg, - int regexBitfield) + public int AddListener(uint localID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg) { // do we already have a match on this particular filter event? - List coll = GetListeners(itemID, channel, name, id, - msg); + List coll = GetListeners(itemID, channel, name, id, msg); if (coll.Count > 0) { - // special case, called with same filter settings, return same - // handle (2008-05-02, tested on 1.21.1 server, still holds) + // special case, called with same filter settings, return same handle + // (2008-05-02, tested on 1.21.1 server, still holds) return coll[0].GetHandle(); } @@ -531,9 +490,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm if (newHandle > 0) { - ListenerInfo li = new ListenerInfo(newHandle, localID, - itemID, hostID, channel, name, id, msg, - regexBitfield); + ListenerInfo li = new ListenerInfo(newHandle, localID, itemID, hostID, channel, name, id, msg); List listeners; if (!m_listeners.TryGetValue(channel,out listeners)) @@ -674,22 +631,6 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm return -1; } - /// These are duplicated from ScriptBaseClass - /// http://opensimulator.org/mantis/view.php?id=6106#c21945 - #region Constants for the bitfield parameter of osListenRegex - - /// - /// process name parameter as regex - /// - public const int OS_LISTEN_REGEX_NAME = 0x1; - - /// - /// process message parameter as regex - /// - public const int OS_LISTEN_REGEX_MESSAGE = 0x2; - - #endregion - // Theres probably a more clever and efficient way to // do this, maybe with regex. // PM2008: Ha, one could even be smart and define a specialized Enumerator. @@ -715,10 +656,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetName().Length > 0 && ( - ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) != OS_LISTEN_REGEX_NAME && !li.GetName().Equals(name)) || - ((li.RegexBitfield & OS_LISTEN_REGEX_NAME) == OS_LISTEN_REGEX_NAME && !Regex.IsMatch(name, li.GetName())) - )) + if (li.GetName().Length > 0 && !li.GetName().Equals(name)) { continue; } @@ -726,10 +664,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { continue; } - if (li.GetMessage().Length > 0 && ( - ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) != OS_LISTEN_REGEX_MESSAGE && !li.GetMessage().Equals(msg)) || - ((li.RegexBitfield & OS_LISTEN_REGEX_MESSAGE) == OS_LISTEN_REGEX_MESSAGE && !Regex.IsMatch(msg, li.GetMessage())) - )) + if (li.GetMessage().Length > 0 && !li.GetMessage().Equals(msg)) { continue; } @@ -762,13 +697,10 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { int idx = 0; Object[] item = new Object[6]; - int dataItemLength = 6; while (idx < data.Length) { - dataItemLength = (idx + 7 == data.Length || (idx + 7 < data.Length && data[idx + 7] is bool)) ? 7 : 6; - item = new Object[dataItemLength]; - Array.Copy(data, idx, item, 0, dataItemLength); + Array.Copy(data, idx, item, 0, 6); ListenerInfo info = ListenerInfo.FromData(localID, itemID, hostID, item); @@ -780,12 +712,12 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_listeners[(int)item[2]].Add(info); } - idx+=dataItemLength; + idx+=6; } } } - public class ListenerInfo : IWorldCommListenerInfo + public class ListenerInfo: IWorldCommListenerInfo { private bool m_active; // Listener is active or not private int m_handle; // Assigned handle of this listener @@ -799,29 +731,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm public ListenerInfo(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message) { - Initialise(handle, localID, ItemID, hostID, channel, name, id, - message, 0); - } - - public ListenerInfo(int handle, uint localID, UUID ItemID, - UUID hostID, int channel, string name, UUID id, - string message, int regexBitfield) - { - Initialise(handle, localID, ItemID, hostID, channel, name, id, - message, regexBitfield); + Initialise(handle, localID, ItemID, hostID, channel, name, id, message); } public ListenerInfo(ListenerInfo li, string name, UUID id, string message) { - Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, 0); + Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message); } - public ListenerInfo(ListenerInfo li, string name, UUID id, string message, int regexBitfield) - { - Initialise(li.m_handle, li.m_localID, li.m_itemID, li.m_hostID, li.m_channel, name, id, message, regexBitfield); - } - - private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, UUID id, string message, int regexBitfield) + private void Initialise(int handle, uint localID, UUID ItemID, UUID hostID, int channel, string name, + UUID id, string message) { m_active = true; m_handle = handle; @@ -832,12 +751,11 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm m_name = name; m_id = id; m_message = message; - RegexBitfield = regexBitfield; } public Object[] GetSerializationData() { - Object[] data = new Object[7]; + Object[] data = new Object[6]; data[0] = m_active; data[1] = m_handle; @@ -845,19 +763,16 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm data[3] = m_name; data[4] = m_id; data[5] = m_message; - data[6] = RegexBitfield; return data; } public static ListenerInfo FromData(uint localID, UUID ItemID, UUID hostID, Object[] data) { - ListenerInfo linfo = new ListenerInfo((int)data[1], localID, ItemID, hostID, (int)data[2], (string)data[3], (UUID)data[4], (string)data[5]); - linfo.m_active = (bool)data[0]; - if (data.Length >= 7) - { - linfo.RegexBitfield = (int)data[6]; - } + ListenerInfo linfo = new ListenerInfo((int)data[1], localID, + ItemID, hostID, (int)data[2], (string)data[3], + (UUID)data[4], (string)data[5]); + linfo.m_active=(bool)data[0]; return linfo; } @@ -916,7 +831,5 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm { return m_id; } - - public int RegexBitfield { get; private set; } } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index 1e1c7d00e0..008465fcc9 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -56,8 +56,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset private bool m_Enabled = false; - private AssetPermissions m_AssetPerms; - public Type ReplaceableInterface { get { return null; } @@ -130,9 +128,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (m_LocalAssetServiceURI != string.Empty) m_LocalAssetServiceURI = m_LocalAssetServiceURI.Trim('/'); - IConfig hgConfig = source.Configs["HGAssetService"]; - m_AssetPerms = new AssetPermissions(hgConfig); // it's ok if arg is null - m_Enabled = true; m_log.Info("[HG ASSET CONNECTOR]: HG asset broker enabled"); } @@ -211,11 +206,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset asset = m_HGService.Get(id); if (asset != null) { - // Now store it locally, if allowed - if (m_AssetPerms.AllowedImport(asset.Type)) + // Now store it locally + // For now, let me just do it for textures and scripts + if (((AssetType)asset.Type == AssetType.Texture) || + ((AssetType)asset.Type == AssetType.LSLBytecode) || + ((AssetType)asset.Type == AssetType.LSLText)) + { m_GridService.Store(asset); - else - return null; + } } } else @@ -330,12 +328,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset string id = string.Empty; if (IsHG(asset.ID)) - { - if (m_AssetPerms.AllowedExport(asset.Type)) - id = m_HGService.Store(asset); - else - return String.Empty; - } + id = m_HGService.Store(asset); else id = m_GridService.Store(asset); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 449c1f1108..c78915f970 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -204,11 +204,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset public byte[] GetData(string id) { // m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Requesting data for asset {0}", id); - - AssetBase asset = null; - - if (m_Cache != null) - asset = m_Cache.Get(id); + + AssetBase asset = m_Cache.Get(id); if (asset != null) return asset.Data; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs deleted file mode 100644 index 198247317b..0000000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/Tests/AssetConnectorTests.cs +++ /dev/null @@ -1,136 +0,0 @@ -/* - * 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.Threading; -using log4net.Config; -using Nini.Config; -using NUnit.Framework; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset; -using OpenSim.Tests.Common; - -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset.Tests -{ - [TestFixture] - public class AssetConnectorsTests : OpenSimTestCase - { - [Test] - public void TestAddAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - lasc.Store(a1); - - AssetBase retreivedA1 = lasc.Get(a1.ID); - Assert.That(retreivedA1.ID, Is.EqualTo(a1.ID)); - Assert.That(retreivedA1.Metadata.ID, Is.EqualTo(a1.Metadata.ID)); - Assert.That(retreivedA1.Data.Length, Is.EqualTo(a1.Data.Length)); - - AssetMetadata retrievedA1Metadata = lasc.GetMetadata(a1.ID); - Assert.That(retrievedA1Metadata.ID, Is.EqualTo(a1.ID)); - - byte[] retrievedA1Data = lasc.GetData(a1.ID); - Assert.That(retrievedA1Data.Length, Is.EqualTo(a1.Data.Length)); - - // TODO: Add cache and check that this does receive a copy of the asset - } - - [Test] - public void TestAddTemporaryAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - a1.Temporary = true; - - lasc.Store(a1); - - Assert.That(lasc.Get(a1.ID), Is.Null); - Assert.That(lasc.GetData(a1.ID), Is.Null); - Assert.That(lasc.GetMetadata(a1.ID), Is.Null); - - // TODO: Add cache and check that this does receive a copy of the asset - } - - [Test] - public void TestAddLocalAsset() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - IConfigSource config = new IniConfigSource(); - config.AddConfig("Modules"); - config.Configs["Modules"].Set("AssetServices", "LocalAssetServicesConnector"); - config.AddConfig("AssetService"); - config.Configs["AssetService"].Set("LocalServiceModule", "OpenSim.Services.AssetService.dll:AssetService"); - config.Configs["AssetService"].Set("StorageProvider", "OpenSim.Tests.Common.dll"); - - LocalAssetServicesConnector lasc = new LocalAssetServicesConnector(); - lasc.Initialise(config); - - AssetBase a1 = AssetHelpers.CreateNotecardAsset(); - a1.Local = true; - - lasc.Store(a1); - - Assert.That(lasc.Get(a1.ID), Is.Null); - Assert.That(lasc.GetData(a1.ID), Is.Null); - Assert.That(lasc.GetMetadata(a1.ID), Is.Null); - - // TODO: Add cache and check that this does receive a copy of the asset - } - } -} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs index 43381337c7..b286d172e4 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/Tests/GridConnectorsTests.cs @@ -43,15 +43,11 @@ using OpenSim.Tests.Common; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests { [TestFixture] - public class GridConnectorsTests : OpenSimTestCase + public class GridConnectorsTests { LocalGridServicesConnector m_LocalConnector; - - [SetUp] - public override void SetUp() + private void SetUp() { - base.SetUp(); - IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); config.AddConfig("GridService"); @@ -75,6 +71,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); + SetUp(); + // Create 4 regions GridRegion r1 = new GridRegion(); r1.RegionName = "Test Region 1"; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs index 221f81584d..b0edce7a91 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/ActivityDetector.cs @@ -65,13 +65,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser public void OnMakeRootAgent(ScenePresence sp) { +// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", sp.UUID, sp.Scene.RegionInfo.RegionName); + if (sp.PresenceType != PresenceType.Npc) - { - string userid = sp.Scene.UserManagementModule.GetUserUUI(sp.UUID); - //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected root presence {0} in {1}", userid, sp.Scene.RegionInfo.RegionName); m_GridUserService.SetLastPosition( - userid, UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); - } + sp.UUID.ToString(), UUID.Zero, sp.Scene.RegionInfo.RegionID, sp.AbsolutePosition, sp.Lookat); } public void OnNewClient(IClientAPI client) @@ -84,16 +82,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser if (client.SceneAgent.IsChildAgent) return; - string userId = client.AgentId.ToString(); - if (client.Scene is Scene) - { - Scene s = (Scene)client.Scene; - userId = s.UserManagementModule.GetUserUUI(client.AgentId); - } - //m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", userId, client.Scene.RegionInfo.RegionName); - +// m_log.DebugFormat("[ACTIVITY DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); m_GridUserService.LoggedOut( - userId, client.SessionId, client.Scene.RegionInfo.RegionID, + client.AgentId.ToString(), client.SessionId, client.Scene.RegionInfo.RegionID, client.SceneAgent.AbsolutePosition, client.SceneAgent.Lookat); } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs index 04acf6732f..badb5527fa 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/GridUser/RemoteGridUserServiceConnector.cs @@ -44,9 +44,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private const int KEEPTIME = 30; // 30 secs - private ExpiringCache m_Infos = new ExpiringCache(); - #region ISharedRegionModule private bool m_Enabled = false; @@ -131,60 +128,23 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.GridUser public bool LoggedOut(string userID, UUID sessionID, UUID region, Vector3 position, Vector3 lookat) { - if (m_Infos.Contains(userID)) - m_Infos.Remove(userID); - return m_RemoteConnector.LoggedOut(userID, sessionID, region, position, lookat); } public bool SetHome(string userID, UUID regionID, Vector3 position, Vector3 lookAt) { - if (m_RemoteConnector.SetHome(userID, regionID, position, lookAt)) - { - // Update the cache too - GridUserInfo info = null; - if (m_Infos.TryGetValue(userID, out info)) - { - info.HomeRegionID = regionID; - info.HomePosition = position; - info.HomeLookAt = lookAt; - } - return true; - } - - return false; + return m_RemoteConnector.SetHome(userID, regionID, position, lookAt); } public bool SetLastPosition(string userID, UUID sessionID, UUID regionID, Vector3 position, Vector3 lookAt) { - if (m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt)) - { - // Update the cache too - GridUserInfo info = null; - if (m_Infos.TryGetValue(userID, out info)) - { - info.LastRegionID = regionID; - info.LastPosition = position; - info.LastLookAt = lookAt; - } - return true; - } - - return false; + return m_RemoteConnector.SetLastPosition(userID, sessionID, regionID, position, lookAt); } public GridUserInfo GetGridUserInfo(string userID) { - GridUserInfo info = null; - if (m_Infos.TryGetValue(userID, out info)) - return info; - - info = m_RemoteConnector.GetGridUserInfo(userID); - - m_Infos.AddOrUpdate(userID, info, KEEPTIME); - - return info; + return m_RemoteConnector.GetGridUserInfo(userID); } public GridUserInfo[] GetGridUserInfo(string[] userID) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs index 8ed1833aca..6eb99ea710 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/LocalSimulationConnector.cs @@ -313,11 +313,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation if (m_scenes.ContainsKey(destination.RegionID)) { -// m_log.DebugFormat( -// "[LOCAL SIMULATION CONNECTOR]: Found region {0} {1} to send AgentUpdate", -// s.RegionInfo.RegionName, destination.RegionHandle); - - Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id, false); }); + Util.FireAndForget(delegate { m_scenes[destination.RegionID].IncomingCloseAgent(id); }); return true; } //m_log.Debug("[LOCAL COMMS]: region not found in SendCloseAgent"); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index ade5e76b99..619550c1c5 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -43,7 +43,6 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; -using System.Threading; namespace OpenSim.Region.CoreModules.World.Archiver { @@ -53,30 +52,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public class ArchiveReadRequest { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// Contains data used while dearchiving a single scene. - /// - private class DearchiveContext - { - public Scene Scene { get; set; } - - public List SerialisedSceneObjects { get; set; } - - public List SerialisedParcels { get; set; } - - public List SceneObjects { get; set; } - - public DearchiveContext(Scene scene) - { - Scene = scene; - SerialisedSceneObjects = new List(); - SerialisedParcels = new List(); - SceneObjects = new List(); - } - } - /// /// The maximum major version of OAR that we can read. Minor versions shouldn't need a max number since version /// bumps here should be compatible. @@ -86,10 +62,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Has the control file been loaded for this archive? /// - public bool ControlFileLoaded { get; private set; } + public bool ControlFileLoaded { get; private set; } - protected string m_loadPath; - protected Scene m_rootScene; + protected Scene m_scene; protected Stream m_loadStream; protected Guid m_requestId; protected string m_errorMessage; @@ -116,27 +91,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (m_UserMan == null) { - m_UserMan = m_rootScene.RequestModuleInterface(); + m_UserMan = m_scene.RequestModuleInterface(); } return m_UserMan; } } - /// - /// Used to cache lookups for valid groups. - /// - private IDictionary m_validGroupUuids = new Dictionary(); - - private IGroupsModule m_groupsModule; - - private IAssetService m_assetService = null; - - public ArchiveReadRequest(Scene scene, string loadPath, bool merge, bool skipAssets, Guid requestId) { - m_rootScene = scene; + m_scene = scene; - m_loadPath = loadPath; try { m_loadStream = new GZipStream(ArchiveHelpers.GetStream(loadPath), CompressionMode.Decompress); @@ -156,15 +120,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - - m_groupsModule = m_rootScene.RequestModuleInterface(); - m_assetService = m_rootScene.AssetService; } public ArchiveReadRequest(Scene scene, Stream loadStream, bool merge, bool skipAssets, Guid requestId) { - m_rootScene = scene; - m_loadPath = null; + m_scene = scene; m_loadStream = loadStream; m_merge = merge; m_skipAssets = skipAssets; @@ -172,35 +132,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; - - m_groupsModule = m_rootScene.RequestModuleInterface(); - m_assetService = m_rootScene.AssetService; } /// /// Dearchive the region embodied in this request. /// public void DearchiveRegion() + { + // The same code can handle dearchiving 0.1 and 0.2 OpenSim Archive versions + DearchiveRegion0DotStar(); + } + + private void DearchiveRegion0DotStar() { int successfulAssetRestores = 0; int failedAssetRestores = 0; + List serialisedSceneObjects = new List(); + List serialisedParcels = new List(); + string filePath = "NONE"; - DearchiveScenesInfo dearchivedScenes; - - // We dearchive all the scenes at once, because the files in the TAR archive might be mixed. - // Therefore, we have to keep track of the dearchive context of all the scenes. - Dictionary sceneContexts = new Dictionary(); - - string fullPath = "NONE"; - TarArchiveReader archive = null; + TarArchiveReader archive = new TarArchiveReader(m_loadStream); byte[] data; TarArchiveReader.TarEntryType entryType; - + try { - FindAndLoadControlFile(out archive, out dearchivedScenes); - - while ((data = archive.ReadEntry(out fullPath, out entryType)) != null) + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { //m_log.DebugFormat( // "[ARCHIVER]: Successfully read {0} ({1} bytes)", filePath, data.Length); @@ -208,30 +165,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) continue; - - // Find the scene that this file belongs to - - Scene scene; - string filePath; - if (!dearchivedScenes.GetRegionFromPath(fullPath, out scene, out filePath)) - continue; // this file belongs to a region that we're not loading - - DearchiveContext sceneContext = null; - if (scene != null) - { - if (!sceneContexts.TryGetValue(scene.RegionInfo.RegionID, out sceneContext)) - { - sceneContext = new DearchiveContext(scene); - sceneContexts.Add(scene.RegionInfo.RegionID, sceneContext); - } - } - - - // Process the file - if (filePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) { - sceneContext.SerialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); + serialisedSceneObjects.Add(Encoding.UTF8.GetString(data)); } else if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH) && !m_skipAssets) { @@ -245,19 +181,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver } else if (!m_merge && filePath.StartsWith(ArchiveConstants.TERRAINS_PATH)) { - LoadTerrain(scene, filePath, data); + LoadTerrain(filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.SETTINGS_PATH)) { - LoadRegionSettings(scene, filePath, data, dearchivedScenes); + LoadRegionSettings(filePath, data); } else if (!m_merge && filePath.StartsWith(ArchiveConstants.LANDDATA_PATH)) { - sceneContext.SerialisedParcels.Add(Encoding.UTF8.GetString(data)); + serialisedParcels.Add(Encoding.UTF8.GetString(data)); } else if (filePath == ArchiveConstants.CONTROL_FILE_PATH) { - // Ignore, because we already read the control file + LoadControlFile(filePath, data); } } @@ -265,16 +201,15 @@ namespace OpenSim.Region.CoreModules.World.Archiver } catch (Exception e) { - m_log.Error( - String.Format("[ARCHIVER]: Aborting load with error in archive file {0} ", fullPath), e); + m_log.ErrorFormat( + "[ARCHIVER]: Aborting load with error in archive file {0}. {1}", filePath, e); m_errorMessage += e.ToString(); - m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); + m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); return; } finally { - if (archive != null) - archive.Close(); + archive.Close(); } if (!m_skipAssets) @@ -288,143 +223,32 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - foreach (DearchiveContext sceneContext in sceneContexts.Values) + if (!m_merge) { - m_log.InfoFormat("[ARCHIVER]: Loading region {0}", sceneContext.Scene.RegionInfo.RegionName); - - if (!m_merge) - { - m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); - sceneContext.Scene.DeleteAllSceneObjects(); - } - - try - { - LoadParcels(sceneContext.Scene, sceneContext.SerialisedParcels); - LoadObjects(sceneContext.Scene, sceneContext.SerialisedSceneObjects, sceneContext.SceneObjects); - - // Inform any interested parties that the region has changed. We waited until now so that all - // of the region's objects will be loaded when we send this notification. - IEstateModule estateModule = sceneContext.Scene.RequestModuleInterface(); - if (estateModule != null) - estateModule.TriggerRegionInfoChange(); - } - catch (Exception e) - { - m_log.Error("[ARCHIVER]: Error loading parcels or objects ", e); - m_errorMessage += e.ToString(); - m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, new List(), m_errorMessage); - return; - } + m_log.Info("[ARCHIVER]: Clearing all existing scene objects"); + m_scene.DeleteAllSceneObjects(); } - // Start the scripts. We delayed this because we want the OAR to finish loading ASAP, so - // that users can enter the scene. If we allow the scripts to start in the loop above - // then they significantly increase the time until the OAR finishes loading. - Util.FireAndForget(delegate(object o) - { - Thread.Sleep(15000); - m_log.Info("[ARCHIVER]: Starting scripts in scene objects"); - - foreach (DearchiveContext sceneContext in sceneContexts.Values) - { - foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) - { - sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart - sceneObject.ResumeScripts(); - } - - sceneContext.SceneObjects.Clear(); - } - }); + LoadParcels(serialisedParcels); + LoadObjects(serialisedSceneObjects); m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); - m_rootScene.EventManager.TriggerOarFileLoaded(m_requestId, dearchivedScenes.GetLoadedScenes(), m_errorMessage); - } - - /// - /// Searches through the files in the archive for the control file, and reads it. - /// We must read the control file first, in order to know which regions are available. - /// - /// - /// In most cases the control file *is* first, since that's how we create archives. However, - /// it's possible that someone rewrote the archive externally so we can't rely on this fact. - /// - /// - /// - private void FindAndLoadControlFile(out TarArchiveReader archive, out DearchiveScenesInfo dearchivedScenes) - { - archive = new TarArchiveReader(m_loadStream); - dearchivedScenes = new DearchiveScenesInfo(); - - string filePath; - byte[] data; - TarArchiveReader.TarEntryType entryType; - bool firstFile = true; - - while ((data = archive.ReadEntry(out filePath, out entryType)) != null) - { - if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType) - continue; - - if (filePath == ArchiveConstants.CONTROL_FILE_PATH) - { - LoadControlFile(filePath, data, dearchivedScenes); - - // Find which scenes are available in the simulator - ArchiveScenesGroup simulatorScenes = new ArchiveScenesGroup(); - SceneManager.Instance.ForEachScene(delegate(Scene scene2) - { - simulatorScenes.AddScene(scene2); - }); - simulatorScenes.CalcSceneLocations(); - dearchivedScenes.SetSimulatorScenes(m_rootScene, simulatorScenes); - - // If the control file wasn't the first file then reset the read pointer - if (!firstFile) - { - m_log.Warn("Control file wasn't the first file in the archive"); - if (m_loadStream.CanSeek) - { - m_loadStream.Seek(0, SeekOrigin.Begin); - } - else if (m_loadPath != null) - { - archive.Close(); - archive = null; - m_loadStream.Close(); - m_loadStream = null; - m_loadStream = new GZipStream(ArchiveHelpers.GetStream(m_loadPath), CompressionMode.Decompress); - archive = new TarArchiveReader(m_loadStream); - } - else - { - // There isn't currently a scenario where this happens, but it's best to add a check just in case - throw new Exception("Error reading archive: control file wasn't the first file, and the input stream doesn't allow seeking"); - } - } - - return; - } - - firstFile = false; - } - - throw new Exception("Control file not found"); + m_scene.EventManager.TriggerOarFileLoaded(m_requestId, m_errorMessage); } /// /// Load serialized scene objects. /// - protected void LoadObjects(Scene scene, List serialisedSceneObjects, List sceneObjects) + /// + protected void LoadObjects(List serialisedSceneObjects) { // Reload serialized prims m_log.InfoFormat("[ARCHIVER]: Loading {0} scene objects. Please wait.", serialisedSceneObjects.Count); - UUID oldTelehubUUID = scene.RegionInfo.RegionSettings.TelehubObject; + UUID oldTelehubUUID = m_scene.RegionInfo.RegionSettings.TelehubObject; - IRegionSerialiserModule serialiser = scene.RequestModuleInterface(); + IRegionSerialiserModule serialiser = m_scene.RequestModuleInterface(); int sceneObjectsLoadedCount = 0; foreach (string serialisedSceneObject in serialisedSceneObjects) @@ -445,7 +269,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver SceneObjectGroup sceneObject = serialiser.DeserializeGroupFromXml2(serialisedSceneObject); - bool isTelehub = (sceneObject.UUID == oldTelehubUUID) && (oldTelehubUUID != UUID.Zero); + bool isTelehub = (sceneObject.UUID == oldTelehubUUID); // For now, give all incoming scene objects new uuids. This will allow scenes to be cloned // on the same region server and multiple examples a single object archive to be imported @@ -455,8 +279,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (isTelehub) { // Change the Telehub Object to the new UUID - scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; - scene.RegionInfo.RegionSettings.Save(); + m_scene.RegionInfo.RegionSettings.TelehubObject = sceneObject.UUID; + m_scene.RegionInfo.RegionSettings.Save(); oldTelehubUUID = UUID.Zero; } @@ -466,20 +290,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (part.CreatorData == null || part.CreatorData == string.Empty) { - if (!ResolveUserUuid(scene, part.CreatorID)) - part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.CreatorID)) + part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; } if (UserManager != null) UserManager.AddUser(part.CreatorID, part.CreatorData); - if (!ResolveUserUuid(scene, part.OwnerID)) - part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.OwnerID)) + part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveUserUuid(scene, part.LastOwnerID)) - part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; - - if (!ResolveGroupUuid(part.GroupID)) - part.GroupID = UUID.Zero; + if (!ResolveUserUuid(part.LastOwnerID)) + part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; // And zap any troublesome sit target information // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); @@ -490,14 +311,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver // being no copy/no mod for everyone lock (part.TaskInventory) { - if (!ResolveUserUuid(scene, part.CreatorID)) - part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.CreatorID)) + part.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveUserUuid(scene, part.OwnerID)) - part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.OwnerID)) + part.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - if (!ResolveUserUuid(scene, part.LastOwnerID)) - part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(part.LastOwnerID)) + part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; // And zap any troublesome sit target information part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); @@ -510,31 +331,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver TaskInventoryDictionary inv = part.TaskInventory; foreach (KeyValuePair kvp in inv) { - if (!ResolveUserUuid(scene, kvp.Value.OwnerID)) + if (!ResolveUserUuid(kvp.Value.OwnerID)) { - kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + kvp.Value.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; } - if (kvp.Value.CreatorData == null || kvp.Value.CreatorData == string.Empty) { - if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) - kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + if (!ResolveUserUuid(kvp.Value.CreatorID)) + kvp.Value.CreatorID = m_scene.RegionInfo.EstateSettings.EstateOwner; } - if (UserManager != null) UserManager.AddUser(kvp.Value.CreatorID, kvp.Value.CreatorData); - - if (!ResolveGroupUuid(kvp.Value.GroupID)) - kvp.Value.GroupID = UUID.Zero; } part.TaskInventory.LockItemsForRead(false); } } - if (scene.AddRestoredSceneObject(sceneObject, true, false)) + if (m_scene.AddRestoredSceneObject(sceneObject, true, false)) { sceneObjectsLoadedCount++; - sceneObject.CreateScriptInstances(0, false, scene.DefaultScriptEngine, 0); + sceneObject.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, 0); sceneObject.ResumeScripts(); } } @@ -549,17 +365,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (oldTelehubUUID != UUID.Zero) { m_log.WarnFormat("Telehub object not found: {0}", oldTelehubUUID); - scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; - scene.RegionInfo.RegionSettings.ClearSpawnPoints(); + m_scene.RegionInfo.RegionSettings.TelehubObject = UUID.Zero; + m_scene.RegionInfo.RegionSettings.ClearSpawnPoints(); } } /// /// Load serialized parcels. /// - /// /// - protected void LoadParcels(Scene scene, List serialisedParcels) + protected void LoadParcels(List serialisedParcels) { // Reload serialized parcels m_log.InfoFormat("[ARCHIVER]: Loading {0} parcels. Please wait.", serialisedParcels.Count); @@ -567,27 +382,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (string serialisedParcel in serialisedParcels) { LandData parcel = LandDataSerializer.Deserialize(serialisedParcel); + if (!ResolveUserUuid(parcel.OwnerID)) + parcel.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - // Validate User and Group UUID's - - if (!ResolveUserUuid(scene, parcel.OwnerID)) - parcel.OwnerID = m_rootScene.RegionInfo.EstateSettings.EstateOwner; - - if (!ResolveGroupUuid(parcel.GroupID)) - { - parcel.GroupID = UUID.Zero; - parcel.IsGroupOwned = false; - } - - List accessList = new List(); - foreach (LandAccessEntry entry in parcel.ParcelAccessList) - { - if (ResolveUserUuid(scene, entry.AgentID)) - accessList.Add(entry); - // else, drop this access rule - } - parcel.ParcelAccessList = accessList; - // m_log.DebugFormat( // "[ARCHIVER]: Adding parcel {0}, local id {1}, area {2}", // parcel.Name, parcel.LocalID, parcel.Area); @@ -598,24 +395,23 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (!m_merge) { bool setupDefaultParcel = (landData.Count == 0); - scene.LandChannel.Clear(setupDefaultParcel); + m_scene.LandChannel.Clear(setupDefaultParcel); } - scene.EventManager.TriggerIncomingLandDataFromStorage(landData); + m_scene.EventManager.TriggerIncomingLandDataFromStorage(landData); m_log.InfoFormat("[ARCHIVER]: Restored {0} parcels.", landData.Count); } /// /// Look up the given user id to check whether it's one that is valid for this grid. /// - /// /// /// - private bool ResolveUserUuid(Scene scene, UUID uuid) + private bool ResolveUserUuid(UUID uuid) { if (!m_validUserUuids.ContainsKey(uuid)) { - UserAccount account = scene.UserAccountService.GetUserAccount(scene.RegionInfo.ScopeID, uuid); + UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, uuid); m_validUserUuids.Add(uuid, account != null); } @@ -623,30 +419,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver } /// - /// Look up the given group id to check whether it's one that is valid for this grid. - /// - /// - /// - private bool ResolveGroupUuid(UUID uuid) - { - if (uuid == UUID.Zero) - return true; // this means the object has no group - - if (!m_validGroupUuids.ContainsKey(uuid)) - { - bool exists; - - if (m_groupsModule == null) - exists = false; - else - exists = (m_groupsModule.GetGroupRecord(uuid) != null); - - m_validGroupUuids.Add(uuid, exists); - } - - return m_validGroupUuids[uuid]; - } - /// Load an asset /// /// @@ -670,7 +442,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver string extension = filename.Substring(i); string uuid = filename.Remove(filename.Length - extension.Length); - if (m_assetService.GetMetadata(uuid) != null) + if (m_scene.AssetService.GetMetadata(uuid) != null) { // m_log.DebugFormat("[ARCHIVER]: found existing asset {0}",uuid); return true; @@ -690,7 +462,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // We're relying on the asset service to do the sensible thing and not store the asset if it already // exists. - m_assetService.Store(asset); + m_scene.AssetService.Store(asset); /** * Create layers on decode for image assets. This is likely to significantly increase the time to load archives so @@ -718,14 +490,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load region settings data /// - /// /// /// - /// /// /// true if settings were loaded successfully, false otherwise /// - private bool LoadRegionSettings(Scene scene, string settingsPath, byte[] data, DearchiveScenesInfo dearchivedScenes) + private bool LoadRegionSettings(string settingsPath, byte[] data) { RegionSettings loadedRegionSettings; @@ -741,7 +511,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver return false; } - RegionSettings currentRegionSettings = scene.RegionInfo.RegionSettings; + RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; currentRegionSettings.AgentLimit = loadedRegionSettings.AgentLimit; currentRegionSettings.AllowDamage = loadedRegionSettings.AllowDamage; @@ -778,14 +548,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (SpawnPoint sp in loadedRegionSettings.SpawnPoints()) currentRegionSettings.AddSpawnPoint(sp); - currentRegionSettings.LoadedCreationDateTime = dearchivedScenes.LoadedCreationDateTime; - currentRegionSettings.LoadedCreationID = dearchivedScenes.GetOriginalRegionID(scene.RegionInfo.RegionID).ToString(); - currentRegionSettings.Save(); - scene.TriggerEstateSunUpdate(); + m_scene.TriggerEstateSunUpdate(); - IEstateModule estateModule = scene.RequestModuleInterface(); + IEstateModule estateModule = m_scene.RequestModuleInterface(); + if (estateModule != null) estateModule.sendRegionHandshakeToAll(); @@ -795,15 +563,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Load terrain data /// - /// /// /// /// /// true if terrain was resolved successfully, false otherwise. /// - private bool LoadTerrain(Scene scene, string terrainPath, byte[] data) + private bool LoadTerrain(string terrainPath, byte[] data) { - ITerrainModule terrainModule = scene.RequestModuleInterface(); + ITerrainModule terrainModule = m_scene.RequestModuleInterface(); MemoryStream ms = new MemoryStream(data); terrainModule.LoadFromStream(terrainPath, ms); @@ -819,18 +586,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// /// - /// - public DearchiveScenesInfo LoadControlFile(string path, byte[] data, DearchiveScenesInfo dearchivedScenes) + public void LoadControlFile(string path, byte[] data) { XmlNamespaceManager nsmgr = new XmlNamespaceManager(new NameTable()); XmlParserContext context = new XmlParserContext(null, nsmgr, null, XmlSpace.None); XmlTextReader xtr = new XmlTextReader(Encoding.ASCII.GetString(data), XmlNodeType.Document, context); - // Loaded metadata will be empty if no information exists in the archive - dearchivedScenes.LoadedCreationDateTime = 0; - dearchivedScenes.DefaultOriginalID = ""; + RegionSettings currentRegionSettings = m_scene.RegionInfo.RegionSettings; - bool multiRegion = false; + // Loaded metadata will empty if no information exists in the archive + currentRegionSettings.LoadedCreationDateTime = 0; + currentRegionSettings.LoadedCreationID = ""; while (xtr.Read()) { @@ -856,44 +622,18 @@ namespace OpenSim.Region.CoreModules.World.Archiver { int value; if (Int32.TryParse(xtr.ReadElementContentAsString(), out value)) - dearchivedScenes.LoadedCreationDateTime = value; + currentRegionSettings.LoadedCreationDateTime = value; } - else if (xtr.Name.ToString() == "row") + else if (xtr.Name.ToString() == "id") { - multiRegion = true; - dearchivedScenes.StartRow(); - } - else if (xtr.Name.ToString() == "region") - { - dearchivedScenes.StartRegion(); - } - else if (xtr.Name.ToString() == "id") - { - string id = xtr.ReadElementContentAsString(); - dearchivedScenes.DefaultOriginalID = id; - if (multiRegion) - dearchivedScenes.SetRegionOriginalID(id); - } - else if (xtr.Name.ToString() == "dir") - { - dearchivedScenes.SetRegionDirectory(xtr.ReadElementContentAsString()); + currentRegionSettings.LoadedCreationID = xtr.ReadElementContentAsString(); } } } - - dearchivedScenes.MultiRegionFormat = multiRegion; - if (!multiRegion) - { - // Add the single scene - dearchivedScenes.StartRow(); - dearchivedScenes.StartRegion(); - dearchivedScenes.SetRegionOriginalID(dearchivedScenes.DefaultOriginalID); - dearchivedScenes.SetRegionDirectory(""); - } - + + currentRegionSettings.Save(); + ControlFileLoaded = true; - - return dearchivedScenes; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs deleted file mode 100644 index d8dace20c8..0000000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveScenesGroup.cs +++ /dev/null @@ -1,176 +0,0 @@ -/* - * 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.Linq; -using System.Text; -using OpenSim.Region.Framework.Scenes; -using OpenMetaverse; -using System.Drawing; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// A group of regions arranged in a rectangle, possibly with holes. - /// - /// - /// The regions usually (but not necessarily) belong to an archive file, in which case we - /// store additional information used to create the archive (e.g., each region's - /// directory within the archive). - /// - public class ArchiveScenesGroup - { - /// - /// All the regions. The outer dictionary contains rows (key: Y coordinate). - /// The inner dictionaries contain each row's regions (key: X coordinate). - /// - public SortedDictionary> Regions { get; set; } - - /// - /// The subdirectory where each region is stored in the archive. - /// - protected Dictionary m_regionDirs; - - /// - /// The grid coordinates of the regions' bounding box. - /// - public Rectangle Rect { get; set; } - - - public ArchiveScenesGroup() - { - Regions = new SortedDictionary>(); - m_regionDirs = new Dictionary(); - Rect = new Rectangle(0, 0, 0, 0); - } - - public void AddScene(Scene scene) - { - uint x = scene.RegionInfo.RegionLocX; - uint y = scene.RegionInfo.RegionLocY; - - SortedDictionary row; - if (!Regions.TryGetValue(y, out row)) - { - row = new SortedDictionary(); - Regions[y] = row; - } - - row[x] = scene; - } - - /// - /// Called after all the scenes have been added. Performs calculations that require - /// knowledge of all the scenes. - /// - public void CalcSceneLocations() - { - if (Regions.Count == 0) - return; - - // Find the bounding rectangle - - uint firstY = Regions.First().Key; - uint lastY = Regions.Last().Key; - - uint? firstX = null; - uint? lastX = null; - - foreach (SortedDictionary row in Regions.Values) - { - uint curFirstX = row.First().Key; - uint curLastX = row.Last().Key; - - firstX = (firstX == null) ? curFirstX : (firstX < curFirstX) ? firstX : curFirstX; - lastX = (lastX == null) ? curLastX : (lastX > curLastX) ? lastX : curLastX; - } - - Rect = new Rectangle((int)firstX, (int)firstY, (int)(lastX - firstX + 1), (int)(lastY - firstY + 1)); - - - // Calculate the subdirectory in which each region will be stored in the archive - - m_regionDirs.Clear(); - ForEachScene(delegate(Scene scene) - { - // We add the region's coordinates to ensure uniqueness even if multiple regions have the same name - string path = string.Format("{0}_{1}_{2}", - scene.RegionInfo.RegionLocX - Rect.X + 1, - scene.RegionInfo.RegionLocY - Rect.Y + 1, - scene.RegionInfo.RegionName.Replace(' ', '_')); - m_regionDirs[scene.RegionInfo.RegionID] = path; - }); - } - - /// - /// Returns the subdirectory where the region is stored. - /// - /// - /// - public string GetRegionDir(UUID regionID) - { - return m_regionDirs[regionID]; - } - - /// - /// Performs an action on all the scenes in this order: rows from South to North, - /// and within each row West to East. - /// - /// - public void ForEachScene(Action action) - { - foreach (SortedDictionary row in Regions.Values) - { - foreach (Scene scene in row.Values) - { - action(scene); - } - } - } - - /// - /// Returns the scene at position 'location'. - /// - /// A location in the grid - /// The scene at this location - /// Whether the scene was found - public bool TryGetScene(Point location, out Scene scene) - { - SortedDictionary row; - if (Regions.TryGetValue((uint)location.Y, out row)) - { - if (row.TryGetValue((uint)location.X, out scene)) - return true; - } - - scene = null; - return false; - } - - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs deleted file mode 100644 index d751b1c990..0000000000 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ /dev/null @@ -1,634 +0,0 @@ -/* - * 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.IO.Compression; -using System.Reflection; -using System.Text.RegularExpressions; -using System.Threading; -using System.Xml; -using log4net; -using OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Framework.Serialization; -using OpenSim.Region.CoreModules.World.Terrain; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using Ionic.Zlib; -using GZipStream = Ionic.Zlib.GZipStream; -using CompressionMode = Ionic.Zlib.CompressionMode; -using OpenSim.Framework.Serialization.External; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// Prepare to write out an archive. - /// - public class ArchiveWriteRequest - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// The minimum major version of OAR that we can write. - /// - public static int MIN_MAJOR_VERSION = 0; - - /// - /// The maximum major version of OAR that we can write. - /// - public static int MAX_MAJOR_VERSION = 1; - - /// - /// Whether we're saving a multi-region archive. - /// - public bool MultiRegionFormat { get; set; } - - /// - /// Determine whether this archive will save assets. Default is true. - /// - public bool SaveAssets { get; set; } - - /// - /// Determines which objects will be included in the archive, according to their permissions. - /// Default is null, meaning no permission checks. - /// - public string CheckPermissions { get; set; } - - protected Scene m_rootScene; - protected Stream m_saveStream; - protected TarArchiveWriter m_archiveWriter; - protected Guid m_requestId; - protected Dictionary m_options; - - /// - /// Constructor - /// - /// Calling module - /// The path to which to save data. - /// The id associated with this request - /// - /// If there was a problem opening a stream for the file specified by the savePath - /// - public ArchiveWriteRequest(Scene scene, string savePath, Guid requestId) : this(scene, requestId) - { - try - { - m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); - } - catch (EntryPointNotFoundException e) - { - m_log.ErrorFormat( - "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." - + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); - m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); - } - } - - /// - /// Constructor. - /// - /// The root scene to archive - /// The stream to which to save data. - /// The id associated with this request - public ArchiveWriteRequest(Scene scene, Stream saveStream, Guid requestId) : this(scene, requestId) - { - m_saveStream = saveStream; - } - - protected ArchiveWriteRequest(Scene scene, Guid requestId) - { - m_rootScene = scene; - m_requestId = requestId; - m_archiveWriter = null; - - MultiRegionFormat = false; - SaveAssets = true; - CheckPermissions = null; - } - - /// - /// Archive the region requested. - /// - /// if there was an io problem with creating the file - public void ArchiveRegion(Dictionary options) - { - m_options = options; - - if (options.ContainsKey("all") && (bool)options["all"]) - MultiRegionFormat = true; - - if (options.ContainsKey("noassets") && (bool)options["noassets"]) - SaveAssets = false; - - Object temp; - if (options.TryGetValue("checkPermissions", out temp)) - CheckPermissions = (string)temp; - - - // Find the regions to archive - ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); - if (MultiRegionFormat) - { - m_log.InfoFormat("[ARCHIVER]: Saving {0} regions", SceneManager.Instance.Scenes.Count); - SceneManager.Instance.ForEachScene(delegate(Scene scene) - { - scenesGroup.AddScene(scene); - }); - } - else - { - scenesGroup.AddScene(m_rootScene); - } - scenesGroup.CalcSceneLocations(); - - - m_archiveWriter = new TarArchiveWriter(m_saveStream); - - try - { - // Write out control file. It should be first so that it will be found ASAP when loading the file. - m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(scenesGroup)); - m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - - // Archive the regions - - Dictionary assetUuids = new Dictionary(); - - scenesGroup.ForEachScene(delegate(Scene scene) - { - string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; - ArchiveOneRegion(scene, regionDir, assetUuids); - }); - - // Archive the assets - - if (SaveAssets) - { - m_log.DebugFormat("[ARCHIVER]: Saving {0} assets", assetUuids.Count); - - // Asynchronously request all the assets required to perform this archive operation - AssetsRequest ar - = new AssetsRequest( - new AssetsArchiver(m_archiveWriter), assetUuids, - m_rootScene.AssetService, m_rootScene.UserAccountService, - m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); - - Util.FireAndForget(o => ar.Execute()); - - // CloseArchive() will be called from ReceivedAllAssets() - } - else - { - m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); - CloseArchive(string.Empty); - } - } - catch (Exception e) - { - CloseArchive(e.Message); - throw; - } - } - - - private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids) - { - m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.RegionInfo.RegionName); - - EntityBase[] entities = scene.GetEntities(); - List sceneObjects = new List(); - - int numObjectsSkippedPermissions = 0; - - // Filter entities so that we only have scene objects. - // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods - // end up having to do this - IPermissionsModule permissionsModule = scene.RequestModuleInterface(); - foreach (EntityBase entity in entities) - { - if (entity is SceneObjectGroup) - { - SceneObjectGroup sceneObject = (SceneObjectGroup)entity; - - if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) - { - if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, CheckPermissions, permissionsModule)) - { - // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. - ++numObjectsSkippedPermissions; - } - else - { - sceneObjects.Add(sceneObject); - } - } - } - } - - if (SaveAssets) - { - UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService); - int prevAssets = assetUuids.Count; - - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - assetGatherer.GatherAssetUuids(sceneObject, assetUuids); - } - - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count - prevAssets); - } - - if (numObjectsSkippedPermissions > 0) - { - m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", - numObjectsSkippedPermissions); - } - - // Make sure that we also request terrain texture assets - RegionSettings regionSettings = scene.RegionInfo.RegionSettings; - - if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) - assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; - - if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) - assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; - - if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) - assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; - - if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) - assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; - - Save(scene, sceneObjects, regionDir); - } - - /// - /// Checks whether the user has permission to export an object group to an OAR. - /// - /// The user - /// The object group - /// Which permissions to check: "C" = Copy, "T" = Transfer - /// The scene's permissions module - /// Whether the user is allowed to export the object to an OAR - private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions, IPermissionsModule permissionsModule) - { - if (checkPermissions == null) - return true; - - if (permissionsModule == null) - return true; // this shouldn't happen - - // Check whether the user is permitted to export all of the parts in the SOG. If any - // part can't be exported then the entire SOG can't be exported. - - bool permitted = true; - //int primNumber = 1; - - foreach (SceneObjectPart obj in objGroup.Parts) - { - uint perm; - PermissionClass permissionClass = permissionsModule.GetPermissionClass(user, obj); - switch (permissionClass) - { - case PermissionClass.Owner: - perm = obj.BaseMask; - break; - case PermissionClass.Group: - perm = obj.GroupMask | obj.EveryoneMask; - break; - case PermissionClass.Everyone: - default: - perm = obj.EveryoneMask; - break; - } - - bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; - bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; - - // Special case: if Everyone can copy the object then this implies it can also be - // Transferred. - // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask - // 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) - partPermitted = false; - if (checkPermissions.Contains("T") && !canTransfer) - partPermitted = false; - - // If the user is the Creator of the object then it can always be included in the OAR - bool creator = (obj.CreatorID.Guid == user.Guid); - if (creator) - partPermitted = true; - - //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); - //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", - // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, - // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); - - if (!partPermitted) - { - permitted = false; - break; - } - - //++primNumber; - } - - return permitted; - } - - /// - /// Create the control file. - /// - /// - public string CreateControlFile(ArchiveScenesGroup scenesGroup) - { - int majorVersion; - int minorVersion; - - if (MultiRegionFormat) - { - majorVersion = MAX_MAJOR_VERSION; - minorVersion = 0; - } - else - { - // To support older versions of OpenSim, we continue to create single-region OARs - // using the old file format. In the future this format will be discontinued. - majorVersion = 0; - minorVersion = 8; - } -// -// if (m_options.ContainsKey("version")) -// { -// string[] parts = m_options["version"].ToString().Split('.'); -// if (parts.Length >= 1) -// { -// majorVersion = Int32.Parse(parts[0]); -// -// if (parts.Length >= 2) -// minorVersion = Int32.Parse(parts[1]); -// } -// } -// -// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) -// { -// throw new Exception( -// string.Format( -// "OAR version number for save must be between {0} and {1}", -// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); -// } -// else if (majorVersion == MAX_MAJOR_VERSION) -// { -// // Force 1.0 -// minorVersion = 0; -// } -// else if (majorVersion == MIN_MAJOR_VERSION) -// { -// // Force 0.4 -// minorVersion = 4; -// } - - m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); - if (majorVersion == 1) - { - m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim versions prior to 0.7.4. Do not use the --all option if you want to produce a compatible OAR"); - } - - String s; - - using (StringWriter sw = new StringWriter()) - { - using (XmlTextWriter xtw = new XmlTextWriter(sw)) - { - xtw.Formatting = Formatting.Indented; - xtw.WriteStartDocument(); - xtw.WriteStartElement("archive"); - xtw.WriteAttributeString("major_version", majorVersion.ToString()); - xtw.WriteAttributeString("minor_version", minorVersion.ToString()); - - xtw.WriteStartElement("creation_info"); - DateTime now = DateTime.UtcNow; - TimeSpan t = now - new DateTime(1970, 1, 1); - xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); - if (!MultiRegionFormat) - xtw.WriteElementString("id", m_rootScene.RegionInfo.RegionID.ToString()); - xtw.WriteEndElement(); - - xtw.WriteElementString("assets_included", SaveAssets.ToString()); - - if (MultiRegionFormat) - { - WriteRegionsManifest(scenesGroup, xtw); - } - else - { - xtw.WriteStartElement("region_info"); - WriteRegionInfo(m_rootScene, xtw); - xtw.WriteEndElement(); - } - - xtw.WriteEndElement(); - - xtw.Flush(); - } - - s = sw.ToString(); - } - - return s; - } - - /// - /// Writes the list of regions included in a multi-region OAR. - /// - private static void WriteRegionsManifest(ArchiveScenesGroup scenesGroup, XmlTextWriter xtw) - { - xtw.WriteStartElement("regions"); - - // Write the regions in order: rows from South to North, then regions from West to East. - // The list of regions can have "holes"; we write empty elements in their position. - - for (uint y = (uint)scenesGroup.Rect.Top; y < scenesGroup.Rect.Bottom; ++y) - { - SortedDictionary row; - if (scenesGroup.Regions.TryGetValue(y, out row)) - { - xtw.WriteStartElement("row"); - - for (uint x = (uint)scenesGroup.Rect.Left; x < scenesGroup.Rect.Right; ++x) - { - Scene scene; - if (row.TryGetValue(x, out scene)) - { - xtw.WriteStartElement("region"); - xtw.WriteElementString("id", scene.RegionInfo.RegionID.ToString()); - xtw.WriteElementString("dir", scenesGroup.GetRegionDir(scene.RegionInfo.RegionID)); - WriteRegionInfo(scene, xtw); - xtw.WriteEndElement(); - } - else - { - // Write a placeholder for a missing region - xtw.WriteElementString("region", ""); - } - } - - xtw.WriteEndElement(); - } - else - { - // Write a placeholder for a missing row - xtw.WriteElementString("row", ""); - } - } - - xtw.WriteEndElement(); // "regions" - } - - protected static void WriteRegionInfo(Scene scene, XmlTextWriter xtw) - { - bool isMegaregion; - Vector2 size; - - IRegionCombinerModule rcMod = scene.RequestModuleInterface(); - - if (rcMod != null) - isMegaregion = rcMod.IsRootForMegaregion(scene.RegionInfo.RegionID); - else - isMegaregion = false; - - if (isMegaregion) - size = rcMod.GetSizeOfMegaregion(scene.RegionInfo.RegionID); - else - size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); - - xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); - xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); - } - - - protected void Save(Scene scene, List sceneObjects, string regionDir) - { - if (regionDir != string.Empty) - regionDir = ArchiveConstants.REGIONS_PATH + regionDir + "/"; - - m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); - - // Write out region settings - string settingsPath = String.Format("{0}{1}{2}.xml", - regionDir, ArchiveConstants.SETTINGS_PATH, scene.RegionInfo.RegionName); - m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(scene.RegionInfo.RegionSettings)); - - m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); - - // Write out land data (aka parcel) settings - List landObjects = scene.LandChannel.AllParcels(); - foreach (ILandObject lo in landObjects) - { - LandData landData = lo.LandData; - string landDataPath = String.Format("{0}{1}{2}.xml", - regionDir, ArchiveConstants.LANDDATA_PATH, landData.GlobalID.ToString()); - m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); - } - - m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); - - // Write out terrain - string terrainPath = String.Format("{0}{1}{2}.r32", - regionDir, ArchiveConstants.TERRAINS_PATH, scene.RegionInfo.RegionName); - - MemoryStream ms = new MemoryStream(); - scene.RequestModuleInterface().SaveToStream(terrainPath, ms); - m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); - ms.Close(); - - m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); - - // Write out scene object metadata - IRegionSerialiserModule serializer = scene.RequestModuleInterface(); - foreach (SceneObjectGroup sceneObject in sceneObjects) - { - //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); - - string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); - string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); - m_archiveWriter.WriteFile(objectPath, serializedObject); - } - } - - protected void ReceivedAllAssets( - ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) - { - foreach (UUID uuid in assetsNotFoundUuids) - { - m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); - } - - // m_log.InfoFormat( - // "[ARCHIVER]: Received {0} of {1} assets requested", - // assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); - - CloseArchive(String.Empty); - } - - - /// - /// Closes the archive and notifies that we're done. - /// - /// The error that occurred, or empty for success - protected void CloseArchive(string errorMessage) - { - try - { - if (m_archiveWriter != null) - m_archiveWriter.Close(); - m_saveStream.Close(); - } - catch (Exception e) - { - m_log.Error(string.Format("[ARCHIVER]: Error closing archive: {0} ", e.Message), e); - if (errorMessage == string.Empty) - errorMessage = e.Message; - } - - m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_rootScene.RegionInfo.RegionName); - - m_rootScene.EventManager.TriggerOarFileSaved(m_requestId, errorMessage); - } - - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs new file mode 100644 index 0000000000..0780d86ed5 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestExecution.cs @@ -0,0 +1,153 @@ +/* + * 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.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Framework.Serialization.External; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Method called when all the necessary assets for an archive request have been received. + /// + public delegate void AssetsRequestCallback( + ICollection assetsFoundUuids, ICollection assetsNotFoundUuids); + + /// + /// Execute the write of an archive once we have received all the necessary data + /// + public class ArchiveWriteRequestExecution + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected ITerrainModule m_terrainModule; + protected IRegionSerialiserModule m_serialiser; + protected List m_sceneObjects; + protected Scene m_scene; + protected TarArchiveWriter m_archiveWriter; + protected Guid m_requestId; + protected Dictionary m_options; + + public ArchiveWriteRequestExecution( + List sceneObjects, + ITerrainModule terrainModule, + IRegionSerialiserModule serialiser, + Scene scene, + TarArchiveWriter archiveWriter, + Guid requestId, + Dictionary options) + { + m_sceneObjects = sceneObjects; + m_terrainModule = terrainModule; + m_serialiser = serialiser; + m_scene = scene; + m_archiveWriter = archiveWriter; + m_requestId = requestId; + m_options = options; + } + + protected internal void ReceivedAllAssets( + ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) + { + try + { + Save(assetsFoundUuids, assetsNotFoundUuids); + } + finally + { + m_archiveWriter.Close(); + } + + m_log.InfoFormat("[ARCHIVER]: Finished writing out OAR for {0}", m_scene.RegionInfo.RegionName); + + m_scene.EventManager.TriggerOarFileSaved(m_requestId, String.Empty); + } + + protected internal void Save(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) + { + foreach (UUID uuid in assetsNotFoundUuids) + { + m_log.DebugFormat("[ARCHIVER]: Could not find asset {0}", uuid); + } + +// m_log.InfoFormat( +// "[ARCHIVER]: Received {0} of {1} assets requested", +// assetsFoundUuids.Count, assetsFoundUuids.Count + assetsNotFoundUuids.Count); + + m_log.InfoFormat("[ARCHIVER]: Adding region settings to archive."); + + // Write out region settings + string settingsPath + = String.Format("{0}{1}.xml", ArchiveConstants.SETTINGS_PATH, m_scene.RegionInfo.RegionName); + m_archiveWriter.WriteFile(settingsPath, RegionSettingsSerializer.Serialize(m_scene.RegionInfo.RegionSettings)); + + m_log.InfoFormat("[ARCHIVER]: Adding parcel settings to archive."); + + // Write out land data (aka parcel) settings + ListlandObjects = m_scene.LandChannel.AllParcels(); + foreach (ILandObject lo in landObjects) + { + LandData landData = lo.LandData; + string landDataPath = String.Format("{0}{1}.xml", ArchiveConstants.LANDDATA_PATH, + landData.GlobalID.ToString()); + m_archiveWriter.WriteFile(landDataPath, LandDataSerializer.Serialize(landData, m_options)); + } + + m_log.InfoFormat("[ARCHIVER]: Adding terrain information to archive."); + + // Write out terrain + string terrainPath + = String.Format("{0}{1}.r32", ArchiveConstants.TERRAINS_PATH, m_scene.RegionInfo.RegionName); + + MemoryStream ms = new MemoryStream(); + m_terrainModule.SaveToStream(terrainPath, ms); + m_archiveWriter.WriteFile(terrainPath, ms.ToArray()); + ms.Close(); + + m_log.InfoFormat("[ARCHIVER]: Adding scene objects to archive."); + + // Write out scene object metadata + foreach (SceneObjectGroup sceneObject in m_sceneObjects) + { + //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); + + string serializedObject = m_serialiser.SerializeGroupToXml2(sceneObject, m_options); + m_archiveWriter.WriteFile(ArchiveHelpers.CreateObjectPath(sceneObject), serializedObject); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs new file mode 100644 index 0000000000..4edaaca594 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs @@ -0,0 +1,438 @@ +/* + * 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.IO.Compression; +using System.Reflection; +using System.Text.RegularExpressions; +using System.Threading; +using System.Xml; +using log4net; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Serialization; +using OpenSim.Region.CoreModules.World.Terrain; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using Ionic.Zlib; +using GZipStream = Ionic.Zlib.GZipStream; +using CompressionMode = Ionic.Zlib.CompressionMode; + +namespace OpenSim.Region.CoreModules.World.Archiver +{ + /// + /// Prepare to write out an archive. + /// + public class ArchiveWriteRequestPreparation + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// The minimum major version of OAR that we can write. + /// + public static int MIN_MAJOR_VERSION = 0; + + /// + /// The maximum major version of OAR that we can write. + /// + public static int MAX_MAJOR_VERSION = 0; + + /// + /// Determine whether this archive will save assets. Default is true. + /// + public bool SaveAssets { get; set; } + + protected ArchiverModule m_module; + protected Scene m_scene; + protected Stream m_saveStream; + protected Guid m_requestId; + + /// + /// Constructor + /// + /// Calling module + /// The path to which to save data. + /// The id associated with this request + /// + /// If there was a problem opening a stream for the file specified by the savePath + /// + public ArchiveWriteRequestPreparation(ArchiverModule module, string savePath, Guid requestId) : this(module, requestId) + { + try + { + m_saveStream = new GZipStream(new FileStream(savePath, FileMode.Create), CompressionMode.Compress, CompressionLevel.BestCompression); + } + catch (EntryPointNotFoundException e) + { + m_log.ErrorFormat( + "[ARCHIVER]: Mismatch between Mono and zlib1g library version when trying to create compression stream." + + "If you've manually installed Mono, have you appropriately updated zlib1g as well?"); + m_log.ErrorFormat("{0} {1}", e.Message, e.StackTrace); + } + } + + /// + /// Constructor. + /// + /// Calling module + /// The stream to which to save data. + /// The id associated with this request + public ArchiveWriteRequestPreparation(ArchiverModule module, Stream saveStream, Guid requestId) : this(module, requestId) + { + m_saveStream = saveStream; + } + + protected ArchiveWriteRequestPreparation(ArchiverModule module, Guid requestId) + { + m_module = module; + + // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix + // this. + if (m_module != null) + m_scene = m_module.Scene; + + m_requestId = requestId; + + SaveAssets = true; + } + + /// + /// Archive the region requested. + /// + /// if there was an io problem with creating the file + public void ArchiveRegion(Dictionary options) + { + if (options.ContainsKey("noassets") && (bool)options["noassets"]) + SaveAssets = false; + + try + { + Dictionary assetUuids = new Dictionary(); + + EntityBase[] entities = m_scene.GetEntities(); + List sceneObjects = new List(); + + string checkPermissions = null; + int numObjectsSkippedPermissions = 0; + Object temp; + if (options.TryGetValue("checkPermissions", out temp)) + checkPermissions = (string)temp; + + // Filter entities so that we only have scene objects. + // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods + // end up having to do this + foreach (EntityBase entity in entities) + { + if (entity is SceneObjectGroup) + { + SceneObjectGroup sceneObject = (SceneObjectGroup)entity; + + if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) + { + if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions)) + { + // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. + ++numObjectsSkippedPermissions; + } + else + { + sceneObjects.Add(sceneObject); + } + } + } + } + + if (SaveAssets) + { + UuidGatherer assetGatherer = new UuidGatherer(m_scene.AssetService); + + foreach (SceneObjectGroup sceneObject in sceneObjects) + { + assetGatherer.GatherAssetUuids(sceneObject, assetUuids); + } + + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", + sceneObjects.Count, assetUuids.Count); + } + else + { + m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); + } + + if (numObjectsSkippedPermissions > 0) + { + m_log.DebugFormat( + "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", + numObjectsSkippedPermissions); + } + + // Make sure that we also request terrain texture assets + RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; + + if (regionSettings.TerrainTexture1 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_1) + assetUuids[regionSettings.TerrainTexture1] = AssetType.Texture; + + if (regionSettings.TerrainTexture2 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_2) + assetUuids[regionSettings.TerrainTexture2] = AssetType.Texture; + + if (regionSettings.TerrainTexture3 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_3) + assetUuids[regionSettings.TerrainTexture3] = AssetType.Texture; + + if (regionSettings.TerrainTexture4 != RegionSettings.DEFAULT_TERRAIN_TEXTURE_4) + assetUuids[regionSettings.TerrainTexture4] = AssetType.Texture; + + TarArchiveWriter archiveWriter = new TarArchiveWriter(m_saveStream); + + // Asynchronously request all the assets required to perform this archive operation + ArchiveWriteRequestExecution awre + = new ArchiveWriteRequestExecution( + sceneObjects, + m_scene.RequestModuleInterface(), + m_scene.RequestModuleInterface(), + m_scene, + archiveWriter, + m_requestId, + options); + + m_log.InfoFormat("[ARCHIVER]: Creating archive file. This may take some time."); + + // Write out control file. This has to be done first so that subsequent loaders will see this file first + // XXX: I know this is a weak way of doing it since external non-OAR aware tar executables will not do this + archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, CreateControlFile(options)); + m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); + + if (SaveAssets) + { + AssetsRequest ar + = new AssetsRequest( + new AssetsArchiver(archiveWriter), assetUuids, + m_scene.AssetService, m_scene.UserAccountService, + m_scene.RegionInfo.ScopeID, options, awre.ReceivedAllAssets); + + Util.FireAndForget(o => ar.Execute()); + } + else + { + awre.ReceivedAllAssets(new List(), new List()); + } + } + catch (Exception) + { + m_saveStream.Close(); + throw; + } + } + + /// + /// Checks whether the user has permission to export an object group to an OAR. + /// + /// The user + /// The object group + /// Which permissions to check: "C" = Copy, "T" = Transfer + /// Whether the user is allowed to export the object to an OAR + private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions) + { + if (checkPermissions == null) + return true; + + IPermissionsModule module = m_scene.RequestModuleInterface(); + if (module == null) + return true; // this shouldn't happen + + // Check whether the user is permitted to export all of the parts in the SOG. If any + // part can't be exported then the entire SOG can't be exported. + + bool permitted = true; + //int primNumber = 1; + + foreach (SceneObjectPart obj in objGroup.Parts) + { + uint perm; + PermissionClass permissionClass = module.GetPermissionClass(user, obj); + switch (permissionClass) + { + case PermissionClass.Owner: + perm = obj.BaseMask; + break; + case PermissionClass.Group: + perm = obj.GroupMask | obj.EveryoneMask; + break; + case PermissionClass.Everyone: + default: + perm = obj.EveryoneMask; + break; + } + + bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; + bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; + + // Special case: if Everyone can copy the object then this implies it can also be + // Transferred. + // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask + // 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) + partPermitted = false; + if (checkPermissions.Contains("T") && !canTransfer) + partPermitted = false; + + // If the user is the Creator of the object then it can always be included in the OAR + bool creator = (obj.CreatorID.Guid == user.Guid); + if (creator) + partPermitted = true; + + //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); + //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, creator={8}, permitted={9}", + // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, + // permissionClass, checkPermissions, canCopy, canTransfer, creator, partPermitted); + + if (!partPermitted) + { + permitted = false; + break; + } + + //++primNumber; + } + + return permitted; + } + + /// + /// Create the control file for the most up to date archive + /// + /// + public string CreateControlFile(Dictionary options) + { + int majorVersion = MAX_MAJOR_VERSION, minorVersion = 8; +// +// if (options.ContainsKey("version")) +// { +// string[] parts = options["version"].ToString().Split('.'); +// if (parts.Length >= 1) +// { +// majorVersion = Int32.Parse(parts[0]); +// +// if (parts.Length >= 2) +// minorVersion = Int32.Parse(parts[1]); +// } +// } +// +// if (majorVersion < MIN_MAJOR_VERSION || majorVersion > MAX_MAJOR_VERSION) +// { +// throw new Exception( +// string.Format( +// "OAR version number for save must be between {0} and {1}", +// MIN_MAJOR_VERSION, MAX_MAJOR_VERSION)); +// } +// else if (majorVersion == MAX_MAJOR_VERSION) +// { +// // Force 1.0 +// minorVersion = 0; +// } +// else if (majorVersion == MIN_MAJOR_VERSION) +// { +// // Force 0.4 +// minorVersion = 4; +// } + + m_log.InfoFormat("[ARCHIVER]: Creating version {0}.{1} OAR", majorVersion, minorVersion); + //if (majorVersion == 1) + //{ + // m_log.WarnFormat("[ARCHIVER]: Please be aware that version 1.0 OARs are not compatible with OpenSim 0.7.0.2 and earlier. Please use the --version=0 option if you want to produce a compatible OAR"); + //} + + String s; + + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter xtw = new XmlTextWriter(sw)) + { + xtw.Formatting = Formatting.Indented; + xtw.WriteStartDocument(); + xtw.WriteStartElement("archive"); + xtw.WriteAttributeString("major_version", majorVersion.ToString()); + xtw.WriteAttributeString("minor_version", minorVersion.ToString()); + + xtw.WriteStartElement("creation_info"); + DateTime now = DateTime.UtcNow; + TimeSpan t = now - new DateTime(1970, 1, 1); + xtw.WriteElementString("datetime", ((int)t.TotalSeconds).ToString()); + xtw.WriteElementString("id", UUID.Random().ToString()); + xtw.WriteEndElement(); + + xtw.WriteStartElement("region_info"); + + bool isMegaregion; + Vector2 size; + IRegionCombinerModule rcMod = null; + + // FIXME: This is only here for regression test purposes since they do not supply a module. Need to fix + // this, possibly by doing control file creation somewhere else. + if (m_module != null) + rcMod = m_module.RegionCombinerModule; + + if (rcMod != null) + isMegaregion = rcMod.IsRootForMegaregion(m_scene.RegionInfo.RegionID); + else + isMegaregion = false; + + if (isMegaregion) + size = rcMod.GetSizeOfMegaregion(m_scene.RegionInfo.RegionID); + else + size = new Vector2((float)Constants.RegionSize, (float)Constants.RegionSize); + + xtw.WriteElementString("is_megaregion", isMegaregion.ToString()); + xtw.WriteElementString("size_in_meters", string.Format("{0},{1}", size.X, size.Y)); + + xtw.WriteEndElement(); + + xtw.WriteElementString("assets_included", SaveAssets.ToString()); + + xtw.WriteEndElement(); + + xtw.Flush(); + } + + s = sw.ToString(); + } + +// if (m_scene != null) +// Console.WriteLine( +// "[ARCHIVE WRITE REQUEST PREPARATION]: Control file for {0} is: {1}", m_scene.RegionInfo.RegionName, s); + + return s; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index abf3713671..bf3b1240a4 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -32,8 +32,6 @@ using System.Reflection; using log4net; using NDesk.Options; using Nini.Config; -using OpenSim.Framework; -using OpenSim.Framework.Console; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -119,7 +117,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver // // foreach (string param in mainParams) // m_log.DebugFormat("GOT PARAM [{0}]", param); - + if (mainParams.Count > 2) { DearchiveRegion(mainParams[2], mergeOar, skipAssets, Guid.Empty); @@ -148,22 +146,17 @@ namespace OpenSim.Region.CoreModules.World.Archiver 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; }); - ops.Add("all", delegate(string v) { options["all"] = v != null; }); List mainParams = ops.Parse(cmdparams); - string path; if (mainParams.Count > 2) - path = mainParams[2]; + { + ArchiveRegion(mainParams[2], options); + } else - path = DEFAULT_OAR_BACKUP_FILENAME; - - // Not doing this right now as this causes some problems with auto-backup systems. Maybe a force flag is - // needed -// if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, path)) -// return; - - ArchiveRegion(path, options); + { + ArchiveRegion(DEFAULT_OAR_BACKUP_FILENAME, options); + } } public void ArchiveRegion(string savePath, Dictionary options) @@ -176,7 +169,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_log.InfoFormat( "[ARCHIVER]: Writing archive for region {0} to {1}", Scene.RegionInfo.RegionName, savePath); - new ArchiveWriteRequest(Scene, savePath, requestId).ArchiveRegion(options); + new ArchiveWriteRequestPreparation(this, savePath, requestId).ArchiveRegion(options); } public void ArchiveRegion(Stream saveStream) @@ -191,7 +184,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver public void ArchiveRegion(Stream saveStream, Guid requestId, Dictionary options) { - new ArchiveWriteRequest(Scene, saveStream, requestId).ArchiveRegion(options); + new ArchiveWriteRequestPreparation(this, saveStream, requestId).ArchiveRegion(options); } public void DearchiveRegion(string loadPath) diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index e2f88331c9..89e9593ba3 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -46,12 +46,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - /// - /// Method called when all the necessary assets for an archive request have been received. - /// - public delegate void AssetsRequestCallback( - ICollection assetsFoundUuids, ICollection assetsNotFoundUuids); - enum RequestState { Initial, @@ -129,10 +123,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_options = options; m_repliesRequired = uuids.Count; - // FIXME: This is a really poor way of handling the timeout since it will always leave the original requesting thread - // hanging. Need to restructure so an original request thread waits for a ManualResetEvent on asset received - // so we can properly abort that thread. Or request all assets synchronously, though that would be a more - // radical change m_requestCallbackTimer = new System.Timers.Timer(TIMEOUT); m_requestCallbackTimer.AutoReset = false; m_requestCallbackTimer.Elapsed += new ElapsedEventHandler(OnRequestCallbackTimeout); diff --git a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs b/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs deleted file mode 100644 index 3dcc020188..0000000000 --- a/OpenSim/Region/CoreModules/World/Archiver/DearchiveScenesGroup.cs +++ /dev/null @@ -1,232 +0,0 @@ -/* - * 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.Linq; -using System.Text; -using OpenSim.Region.Framework.Scenes; -using OpenMetaverse; -using System.Drawing; -using log4net; -using System.Reflection; -using OpenSim.Framework.Serialization; - -namespace OpenSim.Region.CoreModules.World.Archiver -{ - /// - /// The regions included in an OAR file. - /// - public class DearchiveScenesInfo - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - /// - /// One region in the archive. - /// - public class RegionInfo - { - /// - /// The subdirectory in which the region is stored. - /// - public string Directory { get; set; } - - /// - /// The region's coordinates (relative to the South-West corner of the block). - /// - public Point Location { get; set; } - - /// - /// The UUID of the original scene from which this archived region was saved. - /// - public string OriginalID { get; set; } - - /// - /// The scene in the current simulator into which this region is loaded. - /// If null then the region doesn't have a corresponding scene, and it won't be loaded. - /// - public Scene Scene { get; set; } - } - - /// - /// Whether this archive uses the multi-region format. - /// - public Boolean MultiRegionFormat { get; set; } - - /// - /// Maps (Region directory -> region) - /// - protected Dictionary m_directory2region = new Dictionary(); - - /// - /// Maps (UUID of the scene in the simulator where the region will be loaded -> region) - /// - protected Dictionary m_newId2region = new Dictionary(); - - public int LoadedCreationDateTime { get; set; } - public string DefaultOriginalID { get; set; } - - // These variables are used while reading the archive control file - protected int? m_curY = null; - protected int? m_curX = null; - protected RegionInfo m_curRegion; - - - public DearchiveScenesInfo() - { - MultiRegionFormat = false; - } - - - // The following methods are used while reading the archive control file - - public void StartRow() - { - m_curY = (m_curY == null) ? 0 : m_curY + 1; - m_curX = null; - } - - public void StartRegion() - { - m_curX = (m_curX == null) ? 0 : m_curX + 1; - // Note: this doesn't mean we have a real region in this location; this could just be a "hole" - } - - public void SetRegionOriginalID(string id) - { - m_curRegion = new RegionInfo(); - m_curRegion.Location = new Point((int)m_curX, (int)m_curY); - m_curRegion.OriginalID = id; - // 'curRegion' will be saved in 'm_directory2region' when SetRegionDir() is called - } - - public void SetRegionDirectory(string directory) - { - m_curRegion.Directory = directory; - m_directory2region[directory] = m_curRegion; - } - - - /// - /// Sets all the scenes present in the simulator. - /// - /// - /// This method matches regions in the archive to scenes in the simulator according to - /// their relative position. We only load regions if there's an existing Scene in the - /// grid location where the region should be loaded. - /// - /// The scene where the Load OAR operation was run - /// All the scenes in the simulator - public void SetSimulatorScenes(Scene rootScene, ArchiveScenesGroup simulatorScenes) - { - foreach (RegionInfo archivedRegion in m_directory2region.Values) - { - Point location = new Point((int)rootScene.RegionInfo.RegionLocX, (int)rootScene.RegionInfo.RegionLocY); - location.Offset(archivedRegion.Location); - - Scene scene; - if (simulatorScenes.TryGetScene(location, out scene)) - { - archivedRegion.Scene = scene; - m_newId2region[scene.RegionInfo.RegionID] = archivedRegion; - } - else - { - m_log.WarnFormat("[ARCHIVER]: Not loading archived region {0} because there's no existing region at location {1},{2}", - archivedRegion.Directory, location.X, location.Y); - } - } - } - - /// - /// Returns the archived region according to the path of a file in the archive. - /// Also, converts the full path into a path that is relative to the region's directory. - /// - /// The path of a file in the archive - /// The corresponding Scene, or null if none - /// The path relative to the region's directory. (Or the original - /// path, if this file doesn't belong to a region.) - /// True: use this file; False: skip it - public bool GetRegionFromPath(string fullPath, out Scene scene, out string relativePath) - { - scene = null; - relativePath = fullPath; - - if (!MultiRegionFormat) - { - if (m_newId2region.Count > 0) - scene = m_newId2region.First().Value.Scene; - return true; - } - - if (!fullPath.StartsWith(ArchiveConstants.REGIONS_PATH)) - return true; // this file doesn't belong to a region - - string[] parts = fullPath.Split(new Char[] { '/' }, 3); - if (parts.Length != 3) - return false; - string regionDirectory = parts[1]; - relativePath = parts[2]; - - RegionInfo region; - if (m_directory2region.TryGetValue(regionDirectory, out region)) - { - scene = region.Scene; - return (scene != null); - } - else - { - return false; - } - } - - /// - /// Returns the original UUID of a region (from the simulator where the OAR was saved), - /// given the UUID of the scene it was loaded into in the current simulator. - /// - /// - /// - public string GetOriginalRegionID(UUID newID) - { - RegionInfo region; - if (m_newId2region.TryGetValue(newID, out region)) - return region.OriginalID; - else - return DefaultOriginalID; - } - - /// - /// Returns the scenes that have been (or will be) loaded. - /// - /// - public List GetLoadedScenes() - { - return m_newId2region.Keys.ToList(); - } - - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 82f49b0dfa..5deaf5264b 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -47,41 +47,32 @@ using ArchiveConstants = OpenSim.Framework.Serialization.ArchiveConstants; using TarArchiveReader = OpenSim.Framework.Serialization.TarArchiveReader; using TarArchiveWriter = OpenSim.Framework.Serialization.TarArchiveWriter; using RegionSettings = OpenSim.Framework.RegionSettings; -using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.CoreModules.World.Archiver.Tests { [TestFixture] - public class ArchiverTests : OpenSimTestCase + public class ArchiverTests { private Guid m_lastRequestId; private string m_lastErrorMessage; - protected SceneHelpers m_sceneHelpers; protected TestScene m_scene; protected ArchiverModule m_archiverModule; - protected SerialiserModule m_serialiserModule; protected TaskInventoryItem m_soundItem; [SetUp] - public override void SetUp() + public void SetUp() { - base.SetUp(); - - // FIXME: Do something about this - relying on statics in unit tests causes trouble sooner or later - new SceneManager(); - m_archiverModule = new ArchiverModule(); - m_serialiserModule = new SerialiserModule(); + SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - m_sceneHelpers = new SceneHelpers(); - m_scene = m_sceneHelpers.SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, m_serialiserModule, terrainModule); + m_scene = new SceneHelpers().SetupScene(); + SceneHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); } - - private void LoadCompleted(Guid requestId, List loadedScenes, string errorMessage) + + private void LoadCompleted(Guid requestId, string errorMessage) { lock (this) { @@ -137,10 +128,26 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); - SceneObjectGroup sog1; - SceneObjectGroup sog2; - UUID ncAssetUuid; - CreateTestObjects(m_scene, out sog1, out sog2, out ncAssetUuid); + 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; @@ -179,7 +186,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); + arr.LoadControlFile(filePath, data); Assert.That(arr.ControlFileLoaded, Is.True); @@ -204,30 +211,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // TODO: Test presence of more files and contents of files. } - private void CreateTestObjects(Scene scene, out SceneObjectGroup sog1, out SceneObjectGroup sog2, out UUID ncAssetUuid) - { - SceneObjectPart part1 = CreateSceneObjectPart1(); - sog1 = new SceneObjectGroup(part1); - scene.AddNewSceneObject(sog1, false); - - AssetNotecard nc = new AssetNotecard(); - nc.BodyText = "Hello World!"; - nc.Encode(); - ncAssetUuid = UUID.Random(); - UUID ncItemUuid = UUID.Random(); - AssetBase ncAsset - = AssetHelpers.CreateAsset(ncAssetUuid, AssetType.Notecard, nc.AssetData, UUID.Zero); - m_scene.AssetService.Store(ncAsset); - - TaskInventoryItem ncItem - = new TaskInventoryItem { Name = "ncItem", AssetID = ncAssetUuid, ItemID = ncItemUuid }; - SceneObjectPart part2 = CreateSceneObjectPart2(); - sog2 = new SceneObjectGroup(part2); - part2.Inventory.AddInventoryItem(ncItem, true); - - scene.AddNewSceneObject(sog2, false); - } - /// /// Test saving an OpenSim Region Archive with the no assets option /// @@ -287,7 +270,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); + arr.LoadControlFile(filePath, data); Assert.That(arr.ControlFileLoaded, Is.True); @@ -324,7 +307,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); SceneObjectGroup sog1 = SceneHelpers.CreateSceneObject(1, ownerId, "obj1-", 0x11); SceneObjectPart sop2 @@ -379,10 +362,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests // Also check that direct entries which will also have a file entry containing that directory doesn't // upset load tar.WriteDir(ArchiveConstants.TERRAINS_PATH); - + tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); + SceneObjectPart part1 = CreateSceneObjectPart1(); part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); @@ -405,12 +389,31 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(soundDataResourceName, Is.Not.Null); byte[] soundData; - UUID soundUuid; - CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); - - TaskInventoryItem item1 - = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; - part1.Inventory.AddInventoryItem(item1, true); + Console.WriteLine("Loading " + soundDataResourceName); + using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) + { + using (BinaryReader br = new BinaryReader(resource)) + { + // FIXME: Use the inspector instead + soundData = br.ReadBytes(99999999); + UUID soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); + string soundAssetFileName + = ArchiveConstants.ASSETS_PATH + soundUuid + + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; + tar.WriteFile(soundAssetFileName, soundData); + + /* + AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); + scene.AssetService.Store(soundAsset); + asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; + */ + + TaskInventoryItem item1 + = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; + part1.Inventory.AddInventoryItem(item1, true); + } + } + m_scene.AddNewSceneObject(object1, false); string object1FileName = string.Format( @@ -432,34 +435,6 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(m_lastErrorMessage, Is.Null); - TestLoadedRegion(part1, soundItemName, soundData); - } - - private static void CreateSoundAsset(TarArchiveWriter tar, Assembly assembly, string soundDataResourceName, out byte[] soundData, out UUID soundUuid) - { - using (Stream resource = assembly.GetManifestResourceStream(soundDataResourceName)) - { - using (BinaryReader br = new BinaryReader(resource)) - { - // FIXME: Use the inspector instead - soundData = br.ReadBytes(99999999); - soundUuid = UUID.Parse("00000000-0000-0000-0000-000000000001"); - string soundAssetFileName - = ArchiveConstants.ASSETS_PATH + soundUuid - + ArchiveConstants.ASSET_TYPE_TO_EXTENSION[(sbyte)AssetType.SoundWAV]; - tar.WriteFile(soundAssetFileName, soundData); - - /* - AssetBase soundAsset = AssetHelpers.CreateAsset(soundUuid, soundData); - scene.AssetService.Store(soundAsset); - asset1FileName = ArchiveConstants.ASSETS_PATH + soundUuid + ".wav"; - */ - } - } - } - - private void TestLoadedRegion(SceneObjectPart part1, string soundItemName, byte[] soundData) - { SceneObjectPart object1PartLoaded = m_scene.GetSceneObjectPart(part1.Name); Assert.That(object1PartLoaded, Is.Not.Null, "object1 was not loaded"); @@ -479,6 +454,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(loadedSoundAsset.Data, Is.EqualTo(soundData), "saved and loaded sound data do not match"); Assert.Greater(m_scene.LandChannel.AllParcels().Count, 0, "incorrect number of parcels"); + + // Temporary + Console.WriteLine("Successfully completed {0}", MethodBase.GetCurrentMethod()); } /// @@ -538,8 +516,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - m_sceneHelpers = new SceneHelpers(); - TestScene scene2 = m_sceneHelpers.SetupScene(); + TestScene scene2 = new 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 @@ -577,7 +554,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests tar.WriteDir(ArchiveConstants.TERRAINS_PATH); tar.WriteFile( ArchiveConstants.CONTROL_FILE_PATH, - new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty).CreateControlFile(new ArchiveScenesGroup())); + new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary())); RegionSettings rs = new RegionSettings(); rs.AgentLimit = 17; @@ -687,7 +664,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - Scene scene = m_sceneHelpers.SetupScene(); + Scene scene = new SceneHelpers().SetupScene(); SceneHelpers.SetupSceneModules(scene, archiverModule, serialiserModule, terrainModule); m_scene.AddNewSceneObject(new SceneObjectGroup(part2), false); @@ -723,258 +700,5 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests Assert.That(object2PartMerged.GroupPosition, Is.EqualTo(part2.GroupPosition), "object2 group position not equal after merge"); } } - - /// - /// Test saving a multi-region OAR. - /// - [Test] - public void TestSaveMultiRegionOar() - { - TestHelpers.InMethod(); - - // Create test regions - - int WIDTH = 2; - int HEIGHT = 2; - - List scenes = new List(); - - // Maps (Directory in OAR file -> scene) - Dictionary regionPaths = new Dictionary(); - - // Maps (Scene -> expected object paths) - Dictionary> expectedPaths = new Dictionary>(); - - // List of expected assets - List expectedAssets = new List(); - - for (uint y = 0; y < HEIGHT; y++) - { - for (uint x = 0; x < WIDTH; x++) - { - Scene scene; - if (x == 0 && y == 0) - { - scene = m_scene; // this scene was already created in SetUp() - } - else - { - scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); - SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); - } - scenes.Add(scene); - - string dir = String.Format("{0}_{1}_{2}", x + 1, y + 1, scene.RegionInfo.RegionName.Replace(" ", "_")); - regionPaths[dir] = scene; - - SceneObjectGroup sog1; - SceneObjectGroup sog2; - UUID ncAssetUuid; - - CreateTestObjects(scene, out sog1, out sog2, out ncAssetUuid); - - expectedPaths[scene.RegionInfo.RegionID] = new List(); - expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog1)); - expectedPaths[scene.RegionInfo.RegionID].Add(ArchiveHelpers.CreateObjectPath(sog2)); - - expectedAssets.Add(ncAssetUuid); - } - } - - - // Save OAR - - MemoryStream archiveWriteStream = new MemoryStream(); - m_scene.EventManager.OnOarFileSaved += SaveCompleted; - - Guid requestId = new Guid("00000000-0000-0000-0000-808080808080"); - - Dictionary options = new Dictionary(); - options.Add("all", true); - - lock (this) - { - m_archiverModule.ArchiveRegion(archiveWriteStream, requestId, options); - Monitor.Wait(this, 60000); - } - - - // Check that the OAR contains the expected data - - Assert.That(m_lastRequestId, Is.EqualTo(requestId)); - - byte[] archive = archiveWriteStream.ToArray(); - MemoryStream archiveReadStream = new MemoryStream(archive); - TarArchiveReader tar = new TarArchiveReader(archiveReadStream); - - Dictionary> foundPaths = new Dictionary>(); - List foundAssets = new List(); - - foreach (Scene scene in scenes) - { - foundPaths[scene.RegionInfo.RegionID] = new List(); - } - - string filePath; - TarArchiveReader.TarEntryType tarEntryType; - - byte[] data = tar.ReadEntry(out filePath, out tarEntryType); - Assert.That(filePath, Is.EqualTo(ArchiveConstants.CONTROL_FILE_PATH)); - - ArchiveReadRequest arr = new ArchiveReadRequest(m_scene, (Stream)null, false, false, Guid.Empty); - arr.LoadControlFile(filePath, data, new DearchiveScenesInfo()); - - Assert.That(arr.ControlFileLoaded, Is.True); - - while (tar.ReadEntry(out filePath, out tarEntryType) != null) - { - if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) - { - // Assets are shared, so this file doesn't belong to any specific region. - string fileName = filePath.Remove(0, ArchiveConstants.ASSETS_PATH.Length); - if (fileName.EndsWith("_notecard.txt")) - foundAssets.Add(UUID.Parse(fileName.Substring(0, fileName.Length - "_notecard.txt".Length))); - } - else - { - // This file belongs to one of the regions. Find out which one. - Assert.IsTrue(filePath.StartsWith(ArchiveConstants.REGIONS_PATH)); - string[] parts = filePath.Split(new Char[] { '/' }, 3); - Assert.AreEqual(3, parts.Length); - string regionDirectory = parts[1]; - string relativePath = parts[2]; - Scene scene = regionPaths[regionDirectory]; - - if (relativePath.StartsWith(ArchiveConstants.OBJECTS_PATH)) - { - foundPaths[scene.RegionInfo.RegionID].Add(relativePath); - } - } - } - - Assert.AreEqual(scenes.Count, foundPaths.Count); - foreach (Scene scene in scenes) - { - Assert.That(foundPaths[scene.RegionInfo.RegionID], Is.EquivalentTo(expectedPaths[scene.RegionInfo.RegionID])); - } - - Assert.That(foundAssets, Is.EquivalentTo(expectedAssets)); - } - - /// - /// Test loading a multi-region OAR. - /// - [Test] - public void TestLoadMultiRegionOar() - { - TestHelpers.InMethod(); - - // Create an ArchiveScenesGroup with the regions in the OAR. This is needed to generate the control file. - - int WIDTH = 2; - int HEIGHT = 2; - - for (uint y = 0; y < HEIGHT; y++) - { - for (uint x = 0; x < WIDTH; x++) - { - Scene scene; - if (x == 0 && y == 0) - { - scene = m_scene; // this scene was already created in SetUp() - } - else - { - scene = m_sceneHelpers.SetupScene(string.Format("Unit test region {0}", (y * WIDTH) + x + 1), UUID.Random(), 1000 + x, 1000 + y); - SceneHelpers.SetupSceneModules(scene, new ArchiverModule(), m_serialiserModule, new TerrainModule()); - } - } - } - - ArchiveScenesGroup scenesGroup = new ArchiveScenesGroup(); - SceneManager.Instance.ForEachScene(delegate(Scene scene) - { - scenesGroup.AddScene(scene); - }); - scenesGroup.CalcSceneLocations(); - - // Generate the OAR file - - MemoryStream archiveWriteStream = new MemoryStream(); - TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); - - ArchiveWriteRequest writeRequest = new ArchiveWriteRequest(m_scene, (Stream)null, Guid.Empty); - writeRequest.MultiRegionFormat = true; - tar.WriteFile( - ArchiveConstants.CONTROL_FILE_PATH, writeRequest.CreateControlFile(scenesGroup)); - - SceneObjectPart part1 = CreateSceneObjectPart1(); - part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); - part1.SitTargetPosition = new Vector3(1, 2, 3); - - SceneObjectGroup object1 = new SceneObjectGroup(part1); - - // Let's put some inventory items into our object - string soundItemName = "sound-item1"; - UUID soundItemUuid = UUID.Parse("00000000-0000-0000-0000-000000000002"); - Type type = GetType(); - Assembly assembly = type.Assembly; - string soundDataResourceName = null; - string[] names = assembly.GetManifestResourceNames(); - foreach (string name in names) - { - if (name.EndsWith(".Resources.test-sound.wav")) - soundDataResourceName = name; - } - Assert.That(soundDataResourceName, Is.Not.Null); - - byte[] soundData; - UUID soundUuid; - CreateSoundAsset(tar, assembly, soundDataResourceName, out soundData, out soundUuid); - - TaskInventoryItem item1 - = new TaskInventoryItem { AssetID = soundUuid, ItemID = soundItemUuid, Name = soundItemName }; - part1.Inventory.AddInventoryItem(item1, true); - m_scene.AddNewSceneObject(object1, false); - - string object1FileName = string.Format( - "{0}_{1:000}-{2:000}-{3:000}__{4}.xml", - part1.Name, - Math.Round(part1.GroupPosition.X), Math.Round(part1.GroupPosition.Y), Math.Round(part1.GroupPosition.Z), - part1.UUID); - string path = "regions/1_1_Unit_test_region/" + ArchiveConstants.OBJECTS_PATH + object1FileName; - tar.WriteFile(path, SceneObjectSerializer.ToXml2Format(object1)); - - tar.Close(); - - - // Delete the current objects, to test that they're loaded from the OAR and didn't - // just remain in the scene. - SceneManager.Instance.ForEachScene(delegate(Scene scene) - { - scene.DeleteAllSceneObjects(); - }); - - // Create a "hole", to test that that the corresponding region isn't loaded from the OAR - SceneManager.Instance.CloseScene(SceneManager.Instance.Scenes[1]); - - - // Check thay the OAR file contains the expected data - - MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - - lock (this) - { - m_scene.EventManager.OnOarFileLoaded += LoadCompleted; - m_archiverModule.DearchiveRegion(archiveReadStream); - } - - Assert.That(m_lastErrorMessage, Is.Null); - - Assert.AreEqual(3, SceneManager.Instance.Scenes.Count); - - TestLoadedRegion(part1, soundItemName, soundData); - } - } } diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 5fd1bcef20..fdef9d842f 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -40,7 +40,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using RegionFlags = OpenMetaverse.RegionFlags; namespace OpenSim.Region.CoreModules.World.Estate { diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs deleted file mode 100644 index d1f05a714a..0000000000 --- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs +++ /dev/null @@ -1,110 +0,0 @@ -/* - * 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.Diagnostics; -using System.Reflection; -using System.Text; -using log4net; -using Nini.Config; -using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenMetaverse.Messages.Linden; -using OpenSim.Framework; -using OpenSim.Framework.Capabilities; -using OpenSim.Framework.Console; -using OpenSim.Framework.Servers; -using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.CoreModules.Framework.InterfaceCommander; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Physics.Manager; -using OpenSim.Services.Interfaces; -using Caps = OpenSim.Framework.Capabilities.Caps; -using GridRegion = OpenSim.Services.Interfaces.GridRegion; - -namespace OpenSim.Region.CoreModules.World.Land -{ - public class DwellModule : IDwellModule, INonSharedRegionModule - { - private Scene m_scene; - - public Type ReplaceableInterface - { - get { return typeof(IDwellModule); } - } - - public string Name - { - get { return "DwellModule"; } - } - - public void Initialise(IConfigSource source) - { - } - - public void AddRegion(Scene scene) - { - m_scene = scene; - - m_scene.EventManager.OnNewClient += OnNewClient; - } - - public void RegionLoaded(Scene scene) - { - } - - public void RemoveRegion(Scene scene) - { - } - - public void Close() - { - } - - public void OnNewClient(IClientAPI client) - { - client.OnParcelDwellRequest += ClientOnParcelDwellRequest; - } - - private void ClientOnParcelDwellRequest(int localID, IClientAPI client) - { - ILandObject parcel = m_scene.LandChannel.GetLandObject(localID); - if (parcel == null) - return; - - client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); - } - - public int GetDwell(UUID parcelID) - { - return 0; - } - } -} diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index b5e2bc3085..aae6603d57 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -927,7 +927,6 @@ namespace OpenSim.Region.CoreModules.World.Land ILandObject newLand = startLandObject.Copy(); newLand.LandData.Name = newLand.LandData.Name; newLand.LandData.GlobalID = UUID.Random(); - newLand.LandData.Dwell = 0; newLand.SetLandBitmap(newLand.GetSquareLandBitmap(start_x, start_y, end_x, end_y)); diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index d5b2adb00d..4f067374d2 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -33,7 +33,6 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using RegionFlags = OpenMetaverse.RegionFlags; namespace OpenSim.Region.CoreModules.World.Land { diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index cbb3abe460..102b4d7550 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Land /// without recounting the whole sim. /// /// We start out tainted so that the first get call resets the various prim counts. - /// + /// private bool m_Tainted = true; private Object m_TaintLock = new Object(); diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index ab8f14344b..09f6758ba4 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -27,12 +27,9 @@ using System; using System.Collections.Generic; -using System.IO; -using System.Linq; using System.Reflection; using System.Text; using System.Text.RegularExpressions; -using System.Xml; using log4net; using Mono.Addins; using NDesk.Options; @@ -43,7 +40,6 @@ using OpenSim.Framework.Console; using OpenSim.Framework.Monitoring; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Region.Framework.Scenes.Serialization; namespace OpenSim.Region.CoreModules.World.Objects.Commands { @@ -87,85 +83,52 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands m_console.Commands.AddCommand( "Objects", false, "delete object owner", "delete object owner ", - "Delete scene objects by owner", - "Command will ask for confirmation before proceeding.", - HandleDeleteObject); + "Delete a scene object by owner", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object creator", "delete object creator ", - "Delete scene objects by creator", - "Command will ask for confirmation before proceeding.", - HandleDeleteObject); + "Delete a scene object by creator", HandleDeleteObject); m_console.Commands.AddCommand( - "Objects", false, "delete object id", - "delete object id ", - "Delete a scene object by uuid or localID", - HandleDeleteObject); + "Objects", false, "delete object uuid", + "delete object uuid ", + "Delete a scene object by uuid", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object name", "delete object name [--regex] ", "Delete a scene object by name.", - "Command will ask for confirmation before proceeding.\n" - + "If --regex is specified then the name is treatead as a regular expression", + "If --regex is specified then the name is treatead as a regular expression", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, "delete object outside", "delete object outside", - "Delete all scene objects outside region boundaries", - "Command will ask for confirmation before proceeding.", - HandleDeleteObject); + "Delete all scene objects outside region boundaries", HandleDeleteObject); m_console.Commands.AddCommand( "Objects", false, - "delete object pos", - "delete object pos to ", - "Delete scene objects within the given area.", - ConsoleUtil.CoordHelp, - HandleDeleteObject); - - m_console.Commands.AddCommand( - "Objects", - false, - "show object id", - "show object id [--full] ", - "Show details of a scene object with the given UUID or localID", - "The --full option will print out information on all the parts of the object.\n" - + "For yet more detailed part information, use the \"show part\" commands.", - HandleShowObjectById); + "show object uuid", + "show object uuid ", + "Show details of a scene object with the given UUID", HandleShowObjectByUuid); m_console.Commands.AddCommand( "Objects", false, "show object name", - "show object name [--full] [--regex] ", + "show object name [--regex] ", "Show details of scene objects with the given name.", - "The --full option will print out information on all the parts of the object.\n" - + "For yet more detailed part information, use the \"show part\" commands.\n" - + "If --regex is specified then the name is treatead as a regular expression.", + "If --regex is specified then the name is treatead as a regular expression", HandleShowObjectByName); m_console.Commands.AddCommand( "Objects", false, - "show object pos", - "show object pos [--full] to ", - "Show details of scene objects within the given area.", - "The --full option will print out information on all the parts of the object.\n" - + "For yet more detailed part information, use the \"show part\" commands.\n" - + ConsoleUtil.CoordHelp, - HandleShowObjectByPos); - - m_console.Commands.AddCommand( - "Objects", - false, - "show part id", - "show part id ", - "Show details of a scene object part with the given UUID or localID", HandleShowPartById); + "show part uuid", + "show part uuid ", + "Show details of a scene object parts with the given UUID", HandleShowPartByUuid); m_console.Commands.AddCommand( "Objects", @@ -173,28 +136,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "show part name", "show part name [--regex] ", "Show details of scene object parts with the given name.", - "If --regex is specified then the name is treated as a regular expression", + "If --regex is specified then the name is treatead as a regular expression", HandleShowPartByName); - - m_console.Commands.AddCommand( - "Objects", - false, - "show part pos", - "show part pos to ", - "Show details of scene object parts within the given area.", - ConsoleUtil.CoordHelp, - HandleShowPartByPos); - - m_console.Commands.AddCommand( - "Objects", - false, - "dump object id", - "dump object id ", - "Dump the formatted serialization of the given object to the file .xml", - "e.g. dump object uuid c1ed6809-cc24-4061-a4c2-93082a2d1f1d will dump serialization to c1ed6809-cc24-4061-a4c2-93082a2d1f1d.xml\n" - + "To locate the UUID or localID in the first place, you need to use the other show object commands.\n" - + "If a local ID is given then the filename used is still that for the UUID", - HandleDumpObjectById); } public void RemoveRegion(Scene scene) @@ -207,75 +150,25 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands // m_log.DebugFormat("[OBJECTS COMMANDS MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); } - /// - /// Outputs the sogs to console. - /// - /// - /// If true then output all part details. If false then output summary. - private void OutputSogsToConsole(Predicate searchPredicate, bool showFull) - { - List sceneObjects = m_scene.GetSceneObjectGroups().FindAll(searchPredicate); - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectGroup so in sceneObjects) - { - AddSceneObjectReport(sb, so, showFull); - sb.Append("\n"); - } - - sb.AppendFormat("{0} object(s) found in {1}\n", sceneObjects.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); - } - - private void OutputSopsToConsole(Predicate searchPredicate, bool showFull) - { - List sceneObjects = m_scene.GetSceneObjectGroups(); - List parts = new List(); - - sceneObjects.ForEach(so => parts.AddRange(Array.FindAll(so.Parts, searchPredicate))); - - StringBuilder sb = new StringBuilder(); - - foreach (SceneObjectPart part in parts) - { - AddScenePartReport(sb, part, showFull); - sb.Append("\n"); - } - - sb.AppendFormat("{0} parts found in {1}\n", parts.Count, m_scene.Name); - - m_console.OutputFormat(sb.ToString()); - } - - private void HandleShowObjectById(string module, string[] cmdparams) + private void HandleShowObjectByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - bool showFull = false; - OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 4) + if (cmd.Length < 4) { m_console.OutputFormat("Usage: show object uuid "); return; } - UUID uuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out uuid, out localId)) + UUID objectUuid; + if (!UUID.TryParse(cmd[3], out objectUuid)) + { + m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); return; + } - SceneObjectGroup so; - - if (localId != ConsoleUtil.LocalIdNotFound) - so = m_scene.GetSceneObjectGroup(localId); - else - so = m_scene.GetSceneObjectGroup(uuid); + SceneObjectGroup so = m_scene.GetSceneObjectGroup(objectUuid); if (so == null) { @@ -284,7 +177,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddSceneObjectReport(sb, so, showFull); + AddSceneObjectReport(sb, so); m_console.OutputFormat(sb.ToString()); } @@ -294,91 +187,70 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet(); - options.Add("full", v => showFull = v != null ); - options.Add("regex", v => useRegex = v != null ); + OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show object name [--full] [--regex] "); + m_console.OutputFormat("Usage: show object name [--regex] "); return; } string name = mainParams[3]; - Predicate searchPredicate; + List sceneObjects = new List(); + Action searchAction; if (useRegex) { Regex nameRegex = new Regex(name); - searchPredicate = so => nameRegex.IsMatch(so.Name); + searchAction = so => { if (nameRegex.IsMatch(so.Name)) { sceneObjects.Add(so); }}; } else { - searchPredicate = so => so.Name == name; + searchAction = so => { if (so.Name == name) { sceneObjects.Add(so); }}; } - OutputSogsToConsole(searchPredicate, showFull); + m_scene.ForEachSOG(searchAction); + + 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 HandleShowObjectByPos(string module, string[] cmdparams) + private void HandleShowPartByUuid(string module, string[] cmd) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; - bool showFull = false; - OptionSet options = new OptionSet().Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 5) + if (cmd.Length < 4) { - m_console.OutputFormat("Usage: show object pos [--full] to "); - return; - } - - Vector3 startVector, endVector; - - if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) - return; - - Predicate searchPredicate - = so => Util.IsInsideBox(so.AbsolutePosition, startVector, endVector); - - OutputSogsToConsole(searchPredicate, showFull); - } - - private void HandleShowPartById(string module, string[] cmdparams) - { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return; - -// bool showFull = false; - OptionSet options = new OptionSet(); -// options.Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 4) - { - m_console.OutputFormat("Usage: show part id [--full] "); + m_console.OutputFormat("Usage: show part uuid "); return; } UUID objectUuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, mainParams[3], out objectUuid, out localId)) + if (!UUID.TryParse(cmd[3], out objectUuid)) + { + m_console.OutputFormat("{0} is not a valid uuid", cmd[3]); return; + } - SceneObjectPart sop; - if (localId == ConsoleUtil.LocalIdNotFound) - sop = m_scene.GetSceneObjectPart(objectUuid); - else - sop = m_scene.GetSceneObjectPart(localId); + SceneObjectPart sop = m_scene.GetSceneObjectPart(objectUuid); if (sop == null) { @@ -387,239 +259,84 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands } StringBuilder sb = new StringBuilder(); - AddScenePartReport(sb, sop, true); + AddScenePartReport(sb, sop); m_console.OutputFormat(sb.ToString()); } - private void HandleShowPartByPos(string module, string[] cmdparams) - { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return; - -// bool showFull = false; - OptionSet options = new OptionSet(); -// options.Add("full", v => showFull = v != null ); - - List mainParams = options.Parse(cmdparams); - - if (mainParams.Count < 5) - { - m_console.OutputFormat("Usage: show part pos [--full] to "); - return; - } - - string rawConsoleStartVector = mainParams[3]; - Vector3 startVector; - - if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) - { - m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); - return; - } - - string rawConsoleEndVector = mainParams[5]; - Vector3 endVector; - - if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) - { - m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); - return; - } - - OutputSopsToConsole(sop => Util.IsInsideBox(sop.AbsolutePosition, startVector, endVector), true); - } - private void HandleShowPartByName(string module, string[] cmdparams) { if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) return; -// bool showFull = false; bool useRegex = false; - OptionSet options = new OptionSet(); -// options.Add("full", v => showFull = v != null ); - options.Add("regex", v => useRegex = v != null ); + OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); List mainParams = options.Parse(cmdparams); if (mainParams.Count < 4) { - m_console.OutputFormat("Usage: show part name [--full] [--regex] "); + m_console.OutputFormat("Usage: show part name [--regex] "); return; } string name = mainParams[3]; - Predicate searchPredicate; + List parts = new List(); + + Action searchAction; if (useRegex) { Regex nameRegex = new Regex(name); - searchPredicate = sop => nameRegex.IsMatch(sop.Name); + searchAction = so => so.ForEachPart(sop => { if (nameRegex.IsMatch(sop.Name)) { parts.Add(sop); } }); } else { - searchPredicate = sop => sop.Name == name; + searchAction = so => so.ForEachPart(sop => { if (sop.Name == name) { parts.Add(sop); } }); } - OutputSopsToConsole(searchPredicate, true); + m_scene.ForEachSOG(searchAction); + + 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 void HandleDumpObjectById(string module, string[] cmdparams) + private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so) { - if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) - return; - - if (cmdparams.Length < 4) - { - m_console.OutputFormat("Usage: dump object id "); - return; - } - - UUID objectUuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, cmdparams[3], out objectUuid, out localId)) - return; - - SceneObjectGroup so; - if (localId == ConsoleUtil.LocalIdNotFound) - so = m_scene.GetSceneObjectGroup(objectUuid); - else - so = m_scene.GetSceneObjectGroup(localId); - - if (so == null) - { -// m_console.OutputFormat("No part found with uuid {0}", objectUuid); - return; - } - - // In case we found it via local ID. - objectUuid = so.UUID; - - string fileName = string.Format("{0}.xml", objectUuid); - - if (!ConsoleUtil.CheckFileDoesNotExist(m_console, fileName)) - return; - - using (XmlTextWriter xtw = new XmlTextWriter(fileName, Encoding.UTF8)) - { - xtw.Formatting = Formatting.Indented; - SceneObjectSerializer.ToOriginalXmlFormat(so, xtw, true); - } - - m_console.OutputFormat("Object dumped to file {0}", fileName); - } - - /// - /// Append a scene object report to an input StringBuilder - /// - /// - /// - /// - /// - /// If true then information on all parts of an object is appended. - /// If false then only summary information about an object is appended. - /// - private StringBuilder AddSceneObjectReport(StringBuilder sb, SceneObjectGroup so, bool showFull) - { - if (showFull) - { - foreach (SceneObjectPart sop in so.Parts) - { - AddScenePartReport(sb, sop, false); - sb.Append("\n"); - } - } - else - { - AddSummarySceneObjectReport(sb, 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); + sb.AppendFormat("Flags: {0}\n", so.RootPart.Flags); return sb; } - private StringBuilder AddSummarySceneObjectReport(StringBuilder sb, SceneObjectGroup so) + private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop) { - ConsoleDisplayList cdl = new ConsoleDisplayList(); - cdl.AddRow("Name", so.Name); - cdl.AddRow("Descrition", so.Description); - cdl.AddRow("Local ID", so.LocalId); - cdl.AddRow("UUID", so.UUID); - cdl.AddRow("Location", string.Format("{0} @ {1}", so.AbsolutePosition, so.Scene.Name)); - cdl.AddRow("Parts", so.PrimCount); - cdl.AddRow("Flags", so.RootPart.Flags); + 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("Link number: {0}\n", sop.LinkNum); + sb.AppendFormat("Flags: {0}\n", sop.Flags); - return sb.Append(cdl.ToString()); - } - - /// - /// Append a scene object part report to an input StringBuilder - /// - /// - /// - /// - /// - /// If true then information on each inventory item will be shown. - /// If false then only summary inventory information is shown. - /// - private StringBuilder AddScenePartReport(StringBuilder sb, SceneObjectPart sop, bool showFull) - { - ConsoleDisplayList cdl = new ConsoleDisplayList(); - cdl.AddRow("Name", sop.Name); - cdl.AddRow("Description", sop.Description); - cdl.AddRow("Local ID", sop.LocalId); - cdl.AddRow("UUID", sop.UUID); - cdl.AddRow("Location", string.Format("{0} @ {1}", sop.AbsolutePosition, sop.ParentGroup.Scene.Name)); - cdl.AddRow( - "Parent", - sop.IsRoot ? "Is Root" : string.Format("{0} {1}", sop.ParentGroup.Name, sop.ParentGroup.UUID)); - cdl.AddRow("Link number", sop.LinkNum); - cdl.AddRow("Flags", sop.Flags); - - object itemsOutput; - if (showFull) - { - StringBuilder itemsSb = new StringBuilder("\n"); - itemsOutput = AddScenePartItemsReport(itemsSb, sop.Inventory).ToString(); - } - else - { - itemsOutput = sop.Inventory.Count; - } - - - cdl.AddRow("Items", itemsOutput); - - return sb.Append(cdl.ToString()); - } - - private StringBuilder AddScenePartItemsReport(StringBuilder sb, IEntityInventory inv) - { - ConsoleDisplayTable cdt = new ConsoleDisplayTable(); - cdt.Indent = 2; - - cdt.AddColumn("Name", 50); - cdt.AddColumn("Type", 12); - cdt.AddColumn("Running", 7); - cdt.AddColumn("Item UUID", 36); - cdt.AddColumn("Asset UUID", 36); - - foreach (TaskInventoryItem item in inv.GetInventoryItems()) - { - bool foundScriptInstance, scriptRunning; - foundScriptInstance - = SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, item, out scriptRunning); - - cdt.AddRow( - item.Name, - ((InventoryType)item.InvType).ToString(), - foundScriptInstance ? scriptRunning.ToString() : "n/a", - item.ItemID.ToString(), - item.AssetID.ToString()); - } - - return sb.Append(cdt.ToString()); + return sb; } private void HandleDeleteObject(string module, string[] cmd) @@ -681,24 +398,19 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; - case "id": - UUID uuid; - uint localId; - if (!ConsoleUtil.TryParseConsoleId(m_console, o, out uuid, out localId)) + case "uuid": + if (!UUID.TryParse(o, out match)) return; requireConfirmation = false; deletes = new List(); - - SceneObjectGroup so; - if (localId == ConsoleUtil.LocalIdNotFound) - so = m_scene.GetSceneObjectGroup(uuid); - else - so = m_scene.GetSceneObjectGroup(localId); - - if (!so.IsAttachment) - deletes.Add(so); - + + 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); @@ -738,10 +450,6 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands break; - case "pos": - deletes = GetDeleteCandidatesByPos(module, cmd); - break; - default: m_console.OutputFormat("Unrecognized mode {0}", mode); return; @@ -756,7 +464,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands string.Format( "Are you sure that you want to delete {0} objects from {1}", deletes.Count, m_scene.RegionInfo.RegionName), - "y/N"); + "n"); if (response.ToLower() != "y") { @@ -778,6 +486,9 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands private List GetDeleteCandidatesByName(string module, string[] cmdparams) { + if (!(m_console.ConsoleScene == null || m_console.ConsoleScene == m_scene)) + return null; + bool useRegex = false; OptionSet options = new OptionSet().Add("regex", v=> useRegex = v != null ); @@ -811,52 +522,5 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands return sceneObjects; } - - /// - /// Get scene object delete candidates by position - /// - /// - /// - /// null if parsing failed on one of the arguments, otherwise a list of objects to delete. If there - /// are no objects to delete then the list will be empty./returns> - private List GetDeleteCandidatesByPos(string module, string[] cmdparams) - { - if (cmdparams.Length < 5) - { - m_console.OutputFormat("Usage: delete object pos to "); - return null; - } - - Vector3 startVector, endVector; - - if (!TryParseVectorRange(cmdparams.Skip(3).Take(3), out startVector, out endVector)) - return null; - - return m_scene.GetSceneObjectGroups().FindAll( - so => !so.IsAttachment && Util.IsInsideBox(so.AbsolutePosition, startVector, endVector)); - } - - private bool TryParseVectorRange(IEnumerable rawComponents, out Vector3 startVector, out Vector3 endVector) - { - string rawConsoleStartVector = rawComponents.Take(1).Single(); - - if (!ConsoleUtil.TryParseConsoleMinVector(rawConsoleStartVector, out startVector)) - { - m_console.OutputFormat("Error: Start vector {0} does not have a valid format", rawConsoleStartVector); - endVector = Vector3.Zero; - - return false; - } - - string rawConsoleEndVector = rawComponents.Skip(1).Take(1).Single(); - - if (!ConsoleUtil.TryParseConsoleMaxVector(rawConsoleEndVector, out endVector)) - { - m_console.OutputFormat("Error: End vector {0} does not have a valid format", rawConsoleEndVector); - return false; - } - - return true; - } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs index 513a8f5385..14c1a3947e 100644 --- a/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs +++ b/OpenSim/Region/CoreModules/World/Sound/SoundModule.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -24,110 +24,56 @@ * (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.Collections.Generic; -using System.Reflection; +using System; using Nini.Config; using OpenMetaverse; -using log4net; -using Mono.Addins; - using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; +using System.Reflection; +using log4net; namespace OpenSim.Region.CoreModules.World.Sound { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "SoundModule")] - public class SoundModule : INonSharedRegionModule, ISoundModule + public class SoundModule : IRegionModule, ISoundModule { - private static readonly ILog m_log = LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private Scene m_scene; - - public bool Enabled { get; private set; } - - public float MaxDistance { get; private set; } - - #region INonSharedRegionModule - - public void Initialise(IConfigSource configSource) +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + + public void Initialise(Scene scene, IConfigSource source) { - IConfig config = configSource.Configs["Sounds"]; - - if (config == null) - { - Enabled = true; - MaxDistance = 100.0f; - } - else - { - Enabled = config.GetString("Module", "OpenSim.Region.CoreModules.dll:SoundModule") == - Path.GetFileName(Assembly.GetExecutingAssembly().Location) - + ":" + MethodBase.GetCurrentMethod().DeclaringType.Name; - MaxDistance = config.GetFloat("MaxDistance", 100.0f); - } - } - - public void AddRegion(Scene scene) { } - - public void RemoveRegion(Scene scene) - { - m_scene.EventManager.OnClientLogin -= OnNewClient; - } - - public void RegionLoaded(Scene scene) - { - if (!Enabled) - return; - m_scene = scene; - m_scene.EventManager.OnClientLogin += OnNewClient; - + + m_scene.EventManager.OnNewClient += OnNewClient; + m_scene.RegisterModuleInterface(this); } - - public void Close() { } - - public Type ReplaceableInterface - { - get { return typeof(ISoundModule); } - } - + + public void PostInitialise() {} + public void Close() {} public string Name { get { return "Sound Module"; } } - - #endregion - - #region Event Handlers - + public bool IsSharedModule { get { return false; } } + private void OnNewClient(IClientAPI client) { client.OnSoundTrigger += TriggerSound; } - - #endregion - - #region ISoundModule - + public virtual void PlayAttachedSound( UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius) { - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) return; SceneObjectGroup grp = part.ParentGroup; - if (radius == 0) - radius = MaxDistance; - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > MaxDistance) // Max audio distance + if (dis > 100.0) // Max audio distance return; if (grp.IsAttachment) @@ -140,21 +86,23 @@ namespace OpenSim.Region.CoreModules.World.Sound } // Scale by distance - double thisSpGain = gain * ((radius - dis) / radius); + if (radius == 0) + gain = (float)((double)gain * ((100.0 - dis) / 100.0)); + else + gain = (float)((double)gain * ((radius - dis) / radius)); - sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, - ownerID, (float)thisSpGain, flags); + sp.ControllingClient.SendPlayAttachedSound(soundID, objectID, ownerID, (float)gain, flags); }); } - + public virtual void TriggerSound( UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius) { - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) { ScenePresence sp; - if (!m_scene.TryGetScenePresence(ownerID, out sp)) + if (!m_scene.TryGetScenePresence(objectID, out sp)) return; } else @@ -168,207 +116,24 @@ namespace OpenSim.Region.CoreModules.World.Sound } } - if (radius == 0) - radius = MaxDistance; - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) { double dis = Util.GetDistanceTo(sp.AbsolutePosition, position); - if (dis > MaxDistance) // Max audio distance + if (dis > 100.0) // Max audio distance return; + float thisSpGain; + // Scale by distance - double thisSpGain = gain * ((radius - dis) / radius); + if (radius == 0) + thisSpGain = (float)((double)gain * ((100.0 - dis) / 100.0)); + else + thisSpGain = (float)((double)gain * ((radius - dis) / radius)); - sp.ControllingClient.SendTriggeredSound(soundId, ownerID, - objectID, parentID, handle, position, - (float)thisSpGain); + sp.ControllingClient.SendTriggeredSound( + soundId, ownerID, objectID, parentID, handle, position, thisSpGain); }); } - - public virtual void StopSound(UUID objectID) - { - SceneObjectPart m_host; - if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) - return; - - StopSound(m_host); - } - - private static void StopSound(SceneObjectPart m_host) - { - m_host.AdjustSoundGain(0); - // Xantor 20080528: Clear prim data of sound instead - if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) - { - if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) - { - foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) - { - part.Sound = UUID.Zero; - part.SoundFlags = 1 << 5; - part.SoundRadius = 0; - part.ScheduleFullUpdate(); - part.SendFullUpdateToAllClients(); - } - m_host.ParentGroup.LoopSoundMasterPrim = null; - m_host.ParentGroup.LoopSoundSlavePrims.Clear(); - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundFlags = 1 << 5; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - } - else - { - m_host.Sound = UUID.Zero; - m_host.SoundFlags = 1 << 5; - m_host.SoundRadius = 0; - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - } - - public virtual void PreloadSound(UUID objectID, UUID soundID, float radius) - { - SceneObjectPart part; - if (soundID == UUID.Zero - || !m_scene.TryGetSceneObjectPart(objectID, out part)) - { - return; - } - - if (radius == 0) - radius = MaxDistance; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - if (!(Util.GetDistanceTo(sp.AbsolutePosition, part.AbsolutePosition) >= MaxDistance)) - sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); - }); - } - - // Xantor 20080528 we should do this differently. - // 1) apply the sound to the object - // 2) schedule full update - // just sending the sound out once doesn't work so well when other avatars come in view later on - // or when the prim gets moved, changed, sat on, whatever - // see large number of mantises (mantes?) - // 20080530 Updated to remove code duplication - // 20080530 Stop sound if there is one, otherwise volume only changes don't work - public void LoopSound(UUID objectID, UUID soundID, - double volume, double radius, bool isMaster) - { - SceneObjectPart m_host; - if (!m_scene.TryGetSceneObjectPart(objectID, out m_host)) - return; - - if (isMaster) - m_host.ParentGroup.LoopSoundMasterPrim = m_host; - - if (m_host.Sound != UUID.Zero) - StopSound(m_host); - - m_host.Sound = soundID; - m_host.SoundGain = volume; - m_host.SoundFlags = 1; // looping - m_host.SoundRadius = radius; - - m_host.ScheduleFullUpdate(); - m_host.SendFullUpdateToAllClients(); - } - - public void SendSound(UUID objectID, UUID soundID, double volume, - bool triggered, byte flags, float radius, bool useMaster, - bool isMaster) - { - if (soundID == UUID.Zero) - return; - - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - return; - - volume = Util.Clip((float)volume, 0, 1); - - UUID parentID = part.ParentGroup.UUID; - - Vector3 position = part.AbsolutePosition; // region local - ulong regionHandle = m_scene.RegionInfo.RegionHandle; - - if (useMaster) - { - if (isMaster) - { - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - part.ParentGroup.PlaySoundMasterPrim = part; - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - foreach (SceneObjectPart prim in part.ParentGroup.PlaySoundSlavePrims) - { - position = prim.AbsolutePosition; // region local - if (triggered) - TriggerSound(soundID, part.OwnerID, prim.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, prim.UUID, volume, position, flags, radius); - } - part.ParentGroup.PlaySoundSlavePrims.Clear(); - part.ParentGroup.PlaySoundMasterPrim = null; - } - else - { - part.ParentGroup.PlaySoundSlavePrims.Add(part); - } - } - else - { - if (triggered) - TriggerSound(soundID, part.OwnerID, part.UUID, parentID, volume, position, regionHandle, radius); - else - PlayAttachedSound(soundID, part.OwnerID, part.UUID, volume, position, flags, radius); - } - } - - public void TriggerSoundLimited(UUID objectID, UUID sound, - double volume, Vector3 min, Vector3 max) - { - if (sound == UUID.Zero) - return; - - SceneObjectPart part; - if (!m_scene.TryGetSceneObjectPart(objectID, out part)) - return; - - m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) - { - double dis = Util.GetDistanceTo(sp.AbsolutePosition, - part.AbsolutePosition); - - if (dis > MaxDistance) // Max audio distance - return; - else if (!Util.IsInsideBox(sp.AbsolutePosition, min, max)) - return; - - // Scale by distance - double thisSpGain = volume * ((MaxDistance - dis) / MaxDistance); - - sp.ControllingClient.SendTriggeredSound(sound, part.OwnerID, - part.UUID, part.ParentGroup.UUID, - m_scene.RegionInfo.RegionHandle, - part.AbsolutePosition, (float)thisSpGain); - }); - } - - #endregion } } diff --git a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs index d99567cd4b..402b9fb0fe 100644 --- a/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs +++ b/OpenSim/Region/CoreModules/World/Terrain/TerrainModule.cs @@ -414,7 +414,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void LoadPlugins() { m_plugineffects = new Dictionary(); - LoadPlugins(Assembly.GetCallingAssembly()); string plugineffectsPath = "Terrain"; // Load the files in the Terrain/ dir @@ -428,7 +427,32 @@ namespace OpenSim.Region.CoreModules.World.Terrain try { Assembly library = Assembly.LoadFrom(file); - LoadPlugins(library); + foreach (Type pluginType in library.GetTypes()) + { + try + { + if (pluginType.IsAbstract || pluginType.IsNotPublic) + continue; + + string typeName = pluginType.Name; + + if (pluginType.GetInterface("ITerrainEffect", false) != null) + { + ITerrainEffect terEffect = (ITerrainEffect) Activator.CreateInstance(library.GetType(pluginType.ToString())); + + InstallPlugin(typeName, terEffect); + } + else if (pluginType.GetInterface("ITerrainLoader", false) != null) + { + ITerrainLoader terLoader = (ITerrainLoader) Activator.CreateInstance(library.GetType(pluginType.ToString())); + m_loaders[terLoader.FileExtension] = terLoader; + m_log.Info("L ... " + typeName); + } + } + catch (AmbiguousMatchException) + { + } + } } catch (BadImageFormatException) { @@ -436,36 +460,6 @@ namespace OpenSim.Region.CoreModules.World.Terrain } } - private void LoadPlugins(Assembly library) - { - foreach (Type pluginType in library.GetTypes()) - { - try - { - if (pluginType.IsAbstract || pluginType.IsNotPublic) - continue; - - string typeName = pluginType.Name; - - if (pluginType.GetInterface("ITerrainEffect", false) != null) - { - ITerrainEffect terEffect = (ITerrainEffect)Activator.CreateInstance(library.GetType(pluginType.ToString())); - - InstallPlugin(typeName, terEffect); - } - else if (pluginType.GetInterface("ITerrainLoader", false) != null) - { - ITerrainLoader terLoader = (ITerrainLoader)Activator.CreateInstance(library.GetType(pluginType.ToString())); - m_loaders[terLoader.FileExtension] = terLoader; - m_log.Info("L ... " + typeName); - } - } - catch (AmbiguousMatchException) - { - } - } - } - public void InstallPlugin(string pluginName, ITerrainEffect effect) { lock (m_plugineffects) @@ -1184,8 +1178,7 @@ namespace OpenSim.Region.CoreModules.World.Terrain private void InterfaceRunPluginEffect(Object[] args) { - string firstArg = (string)args[0]; - if (firstArg == "list") + if ((string) args[0] == "list") { m_log.Info("List of loaded plugins"); foreach (KeyValuePair kvp in m_plugineffects) @@ -1194,14 +1187,14 @@ namespace OpenSim.Region.CoreModules.World.Terrain } return; } - if (firstArg == "reload") + if ((string) args[0] == "reload") { LoadPlugins(); return; } - if (m_plugineffects.ContainsKey(firstArg)) + if (m_plugineffects.ContainsKey((string) args[0])) { - m_plugineffects[firstArg].RunEffect(m_channel); + m_plugineffects[(string) args[0]].RunEffect(m_channel); CheckForTerrainUpdates(); } else diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs index 33f6c3fbe0..3c48d07bb6 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/Warp3DImageModule.cs @@ -222,13 +222,6 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap bitmap = ImageUtils.ResizeImage(origBitmap, viewport.Width, viewport.Height); } - // XXX: It shouldn't really be necesary to force a GC here as one should occur anyway pretty shortly - // afterwards. It's generally regarded as a bad idea to manually GC. If Warp3D is using lots of memory - // then this may be some issue with the Warp3D code itself, though it's also quite possible that generating - // this map tile simply takes a lot of memory. - GC.Collect(); - m_log.Debug("[WARP 3D IMAGE MODULE]: GC.Collect()"); - return bitmap; } diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index d781eae887..90a13a73b5 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -113,15 +113,6 @@ namespace OpenSim.Region.Framework.Interfaces /// void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID); - /// - /// Detach the given item to the ground at the specified coordinates & rotation - /// - /// - /// - /// - /// - void DetachSingleAttachmentToGround(IScenePresence sp, uint objectLocalID, Vector3 absolutePos, Quaternion absoluteRot); - /// /// Detach the given attachment so that it remains in the user's inventory. /// diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 6df5cc2ac5..8954513c06 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -25,8 +25,6 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; -using System.Drawing; using System.IO; using OpenMetaverse; @@ -35,14 +33,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IDynamicTextureManager { void RegisterRender(string handleType, IDynamicTextureRender render); - - /// - /// Used by IDynamicTextureRender implementations to return renders - /// - /// - /// - /// - void ReturnData(UUID id, IDynamicTexture texture); + void ReturnData(UUID id, byte[] data); UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, int updateTimer); @@ -122,65 +113,11 @@ namespace OpenSim.Region.Framework.Interfaces string GetName(); string GetContentType(); bool SupportsAsynchronous(); - -// /// -// /// Return true if converting the input body and extra params data will always result in the same byte[] array -// /// -// /// -// /// This method allows the caller to use a previously generated asset if it has one. -// /// -// /// -// /// -// /// -// bool AlwaysIdenticalConversion(string bodyData, string extraParams); - - IDynamicTexture ConvertUrl(string url, string extraParams); - IDynamicTexture ConvertData(string bodyData, string extraParams); - + byte[] ConvertUrl(string url, string extraParams); + byte[] ConvertStream(Stream data, string extraParams); bool AsyncConvertUrl(UUID id, string url, string extraParams); bool AsyncConvertData(UUID id, string bodyData, string extraParams); - void GetDrawStringSize(string text, string fontName, int fontSize, out double xSize, out double ySize); } - - public interface IDynamicTexture - { - /// - /// Input commands used to generate this data. - /// - /// - /// Null if input commands were not used. - /// - string InputCommands { get; } - - /// - /// Uri used to generate this data. - /// - /// - /// Null if a uri was not used. - /// - Uri InputUri { get; } - - /// - /// Extra input params used to generate this data. - /// - string InputParams { get; } - - /// - /// Texture data. - /// - byte[] Data { get; } - - /// - /// Size of texture. - /// - Size Size { get; } - - /// - /// Signal whether the texture is reuseable (i.e. whether the same input data will always generate the same - /// texture). - /// - bool IsReuseable { get; } - } } diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 8028d87099..4274cbe8bd 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -151,19 +151,6 @@ namespace OpenSim.Region.Framework.Interfaces /// void StopScriptInstance(UUID itemId); - /// - /// Try to get the script running status. - /// - /// - /// Returns true if a script for the item was found in one of the simulator's script engines. In this case, - /// the running parameter will reflect the running status. - /// Returns false if the item could not be found, if the item is not a script or if a script instance for the - /// item was not found in any of the script engines. In this case, running status is irrelevant. - /// - /// - /// - bool TryGetScriptInstanceRunning(UUID itemId, out bool running); - /// /// Add an item to this entity's inventory. If an item with the same name already exists, then an alternative /// name is chosen. @@ -282,26 +269,18 @@ namespace OpenSim.Region.Framework.Interfaces void ApplyGodPermissions(uint perms); - /// - /// Number of items in this inventory. - /// - int Count { get; } - /// /// Returns true if this inventory contains any scripts /// bool ContainsScripts(); /// - /// Number of scripts in this inventory. - /// - /// - /// Includes both running and non running scripts. - /// + /// Returns the count of scripts contained + /// int ScriptCount(); /// - /// Number of running scripts in this inventory. + /// Returns the count of running scripts contained /// int RunningScriptCount(); diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 292efa4b7e..ca2ad94592 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -46,10 +46,6 @@ namespace OpenSim.Region.Framework.Interfaces /// void sendRegionHandshakeToAll(); void TriggerEstateInfoChange(); - - /// - /// Fires the OnRegionInfoChange event. - /// void TriggerRegionInfoChange(); void setEstateTerrainBaseTexture(int level, UUID texture); diff --git a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs index da39e95638..baac6e827f 100644 --- a/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IJsonStoreModule.cs @@ -35,7 +35,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IJsonStoreModule { - bool CreateStore(string value, ref UUID result); + bool CreateStore(string value, out UUID result); bool DestroyStore(UUID storeID); bool TestPath(UUID storeID, string path, bool useJson); bool SetValue(UUID storeID, string path, string value, bool useJson); diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs index 70ff9549e8..a76ffdebd2 100644 --- a/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs +++ b/OpenSim/Region/Framework/Interfaces/IScriptModuleComms.cs @@ -47,46 +47,9 @@ namespace OpenSim.Region.Framework.Interfaces /// event ScriptCommand OnScriptCommand; - /// - /// Register an instance method as a script call by method name - /// - /// - /// void RegisterScriptInvocation(object target, string method); - - /// - /// Register a static or instance method as a script call by method info - /// - /// If target is a Type object, will assume method is static. - /// void RegisterScriptInvocation(object target, MethodInfo method); - - /// - /// Register one or more instance methods as script calls by method name - /// - /// - /// void RegisterScriptInvocation(object target, string[] methods); - - /// - /// Register one or more static methods as script calls by method name - /// - /// - /// - void RegisterScriptInvocation(Type target, string[] methods); - - /// - /// Automatically register script invocations by checking for methods - /// with . Should only check - /// public methods. - /// - /// - void RegisterScriptInvocations(IRegionModuleBase target); - - /// - /// Returns an array of all registered script calls - /// - /// Delegate[] GetScriptInvocationList(); Delegate LookupScriptInvocation(string fname); @@ -105,44 +68,12 @@ namespace OpenSim.Region.Framework.Interfaces /// void DispatchReply(UUID scriptId, int code, string text, string key); - /// - /// Operation to for a region module to register a constant to be used - /// by the script engine - /// - /// - /// The name of the constant. LSL convention is for constant names to - /// be uppercase. - /// - /// - /// The value of the constant. Should be of a type that can be - /// converted to one of - /// + /// For constants void RegisterConstant(string cname, object value); - - /// - /// Automatically register all constants on a region module by - /// checking for fields with . - /// - /// - void RegisterConstants(IRegionModuleBase target); - - /// - /// Operation to check for a registered constant - /// - /// Name of constant - /// Value of constant or null if none found. object LookupModConstant(string cname); Dictionary GetConstants(); // For use ONLY by the script API void RaiseEvent(UUID script, string id, string module, string command, string key); } - - [AttributeUsage(AttributeTargets.Method)] - public class ScriptInvocationAttribute : Attribute - { } - - [AttributeUsage(AttributeTargets.Field)] - public class ScriptConstantAttribute : Attribute - { } } diff --git a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs index 68af4923d5..6117a80d9e 100644 --- a/OpenSim/Region/Framework/Interfaces/ISoundModule.cs +++ b/OpenSim/Region/Framework/Interfaces/ISoundModule.cs @@ -32,96 +32,9 @@ namespace OpenSim.Region.Framework.Interfaces { public interface ISoundModule { - /// - /// Maximum distance between a sound source and a recipient. - /// - float MaxDistance { get; } - - /// - /// Play a sound from an object. - /// - /// Sound asset ID - /// Sound source owner - /// Sound source ID - /// Sound volume - /// Sound source position - /// Sound flags - /// - /// Radius used to affect gain over distance. - /// - void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, - double gain, Vector3 position, byte flags, float radius); - - /// - /// Trigger a sound in the scene. - /// - /// Sound asset ID - /// Sound source owner - /// Sound source ID - /// Sound source parent. - /// Sound volume - /// Sound source position - /// - /// - /// Radius used to affect gain over distance. - /// + void PlayAttachedSound(UUID soundID, UUID ownerID, UUID objectID, double gain, Vector3 position, byte flags, float radius); + void TriggerSound( - UUID soundId, UUID ownerID, UUID objectID, UUID parentID, - double gain, Vector3 position, UInt64 handle, float radius); - - /// - /// Stop sounds eminating from an object. - /// - /// Sound source ID - void StopSound(UUID objectID); - - /// - /// Preload sound to viewers within range. - /// - /// Sound source ID - /// Sound asset ID - /// - /// Radius used to determine which viewers should preload the sound. - /// - void PreloadSound(UUID objectID, UUID soundID, float radius); - - /// - /// Loop specified sound at specified volume with specified radius, - /// optionally declaring object as new sync master. - /// - /// Sound source ID - /// Sound asset ID - /// Sound volume - /// Sound radius - /// Set object to sync master if true - void LoopSound(UUID objectID, UUID soundID, double gain, - double radius, bool isMaster); - - /// - /// Trigger or play an attached sound in this part's inventory. - /// - /// Sound source ID - /// Sound asset ID - /// Sound volume - /// Triggered or not. - /// - /// Sound radius - /// Play using sound master - /// Play as sound master - void SendSound(UUID objectID, UUID sound, double volume, - bool triggered, byte flags, float radius, bool useMaster, - bool isMaster); - - /// - /// Trigger a sound to be played to all agents within an axis-aligned - /// bounding box. - /// - /// Sound source ID - /// Sound asset ID - /// Sound volume - /// AABB bottom south-west corner - /// AABB top north-east corner - void TriggerSoundLimited(UUID objectID, UUID sound, double volume, - Vector3 min, Vector3 max); + UUID soundId, UUID ownerID, UUID objectID, UUID parentID, double gain, Vector3 position, UInt64 handle, float radius); } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs index 79e9f9d51e..457444cd83 100644 --- a/OpenSim/Region/Framework/Interfaces/IUrlModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IUrlModule.cs @@ -39,8 +39,6 @@ namespace OpenSim.Region.Framework.Interfaces UUID RequestSecureURL(IScriptModule engine, SceneObjectPart host, UUID itemID); void ReleaseURL(string url); void HttpResponse(UUID request, int status, string body); - void HttpContentType(UUID request, string type); - string GetHttpHeader(UUID request, string header); int GetFreeUrls(); diff --git a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs index f8088c3d3c..24cd06978e 100644 --- a/OpenSim/Region/Framework/Interfaces/IUserManagement.cs +++ b/OpenSim/Region/Framework/Interfaces/IUserManagement.cs @@ -1,31 +1,4 @@ -/* - * 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; using System.Collections.Generic; using OpenMetaverse; diff --git a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs index 20e0199d7b..e8e375e037 100644 --- a/OpenSim/Region/Framework/Interfaces/IWorldComm.cs +++ b/OpenSim/Region/Framework/Interfaces/IWorldComm.cs @@ -45,13 +45,6 @@ namespace OpenSim.Region.Framework.Interfaces void Deactivate(); void Activate(); UUID GetID(); - - /// - /// Bitfield indicating which strings should be processed as regex. - /// 1 corresponds to IWorldCommListenerInfo::GetName() - /// 2 corresponds to IWorldCommListenerInfo::GetMessage() - /// - int RegexBitfield { get; } } public interface IWorldComm @@ -67,7 +60,7 @@ namespace OpenSim.Region.Framework.Interfaces /// the script during 'peek' time. Parameter hostID is needed to /// determine the position of the script. /// - /// localID of the script engine + /// localID of the script engine /// UUID of the script engine /// UUID of the SceneObjectPart /// channel to listen on @@ -77,23 +70,6 @@ namespace OpenSim.Region.Framework.Interfaces /// number of the scripts handle int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg); - /// - /// Create a listen event callback with the specified filters. - /// The parameters localID,itemID are needed to uniquely identify - /// the script during 'peek' time. Parameter hostID is needed to - /// determine the position of the script. - /// - /// localID of the script engine - /// UUID of the script engine - /// UUID of the SceneObjectPart - /// channel to listen on - /// name to filter on - /// key to filter on (user given, could be totally faked) - /// msg to filter on - /// Bitfield indicating which strings should be processed as regex. - /// number of the scripts handle - int Listen(uint LocalID, UUID itemID, UUID hostID, int channel, string name, UUID id, string msg, int regexBitfield); - /// /// This method scans over the objects which registered an interest in listen callbacks. /// For everyone it finds, it checks if it fits the given filter. If it does, then diff --git a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs index 65ae445950..ad421eeedb 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/AnimationSet.cs @@ -41,7 +41,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation { // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private OpenSim.Framework.Animation m_implicitDefaultAnimation = new OpenSim.Framework.Animation(); private OpenSim.Framework.Animation m_defaultAnimation = new OpenSim.Framework.Animation(); private List m_animations = new List(); @@ -50,11 +49,6 @@ namespace OpenSim.Region.Framework.Scenes.Animation get { return m_defaultAnimation; } } - public OpenSim.Framework.Animation ImplicitDefaultAnimation - { - get { return m_implicitDefaultAnimation; } - } - public AnimationSet() { ResetDefaultAnimation(); @@ -125,18 +119,11 @@ namespace OpenSim.Region.Framework.Scenes.Animation if (m_defaultAnimation.AnimID != animID) { m_defaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); - m_implicitDefaultAnimation = m_defaultAnimation; return true; } return false; } - // Called from serialization only - public void SetImplicitDefaultAnimation(UUID animID, int sequenceNum, UUID objectID) - { - m_implicitDefaultAnimation = new OpenSim.Framework.Animation(animID, sequenceNum, objectID); - } - protected bool ResetDefaultAnimation() { return TrySetDefaultAnimation("STAND", 1, UUID.Zero); diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 5b1c9f4a1c..4a19c3bfdf 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -47,75 +47,30 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnFrameDelegate(); - /// - /// Triggered on each sim frame. - /// - /// - /// This gets triggered in - /// Core uses it for things like Sun, Wind & Clouds - /// The MRM module also uses it. - /// public event OnFrameDelegate OnFrame; public delegate void ClientMovement(ScenePresence client); - /// - /// Trigerred when an agent moves. - /// - /// - /// This gets triggered in - /// prior to - /// public event ClientMovement OnClientMovement; public delegate void OnTerrainTaintedDelegate(); - /// - /// Triggered if the terrain has been edited - /// - /// - /// This gets triggered in - /// after it determines that an update has been made. - /// public event OnTerrainTaintedDelegate OnTerrainTainted; public delegate void OnTerrainTickDelegate(); - /// - /// Triggered if the terrain has been edited - /// - /// - /// This gets triggered in - /// but is used by core solely to update the physics engine. - /// - public event OnTerrainTickDelegate OnTerrainTick; - public delegate void OnTerrainUpdateDelegate(); + public event OnTerrainTickDelegate OnTerrainTick; + public event OnTerrainUpdateDelegate OnTerrainUpdate; public delegate void OnBackupDelegate(ISimulationDataService datastore, bool forceBackup); - /// - /// Triggered when a region is backed up/persisted to storage - /// - /// - /// This gets triggered in - /// and is fired before the persistence occurs. - /// public event OnBackupDelegate OnBackup; public delegate void OnClientConnectCoreDelegate(IClientCore client); - /// - /// Triggered when a new client connects to the scene. - /// - /// - /// This gets triggered in , - /// which checks if an instance of - /// also implements and as such, - /// is not triggered by NPCs. - /// public event OnClientConnectCoreDelegate OnClientConnect; public delegate void OnNewClientDelegate(IClientAPI client); @@ -125,96 +80,33 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// This is triggered for both child and root agent client connections. - /// /// Triggered before OnClientLogin. - /// - /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. /// public event OnNewClientDelegate OnNewClient; /// /// Fired if the client entering this sim is doing so as a new login /// - /// - /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. - /// public event Action OnClientLogin; public delegate void OnNewPresenceDelegate(ScenePresence presence); - /// - /// Triggered when a new presence is added to the scene - /// - /// - /// Triggered in which is used by both - /// users and NPCs - /// public event OnNewPresenceDelegate OnNewPresence; public delegate void OnRemovePresenceDelegate(UUID agentId); - /// - /// Triggered when a presence is removed from the scene - /// - /// - /// Triggered in which is used by both - /// users and NPCs - /// - /// Triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. - /// public event OnRemovePresenceDelegate OnRemovePresence; public delegate void OnParcelPrimCountUpdateDelegate(); - /// - /// Triggered whenever the prim count may have been altered, or prior - /// to an action that requires the current prim count to be accurate. - /// - /// - /// Triggered by in - /// , - /// , - /// , - /// , - /// , - /// , - /// - /// public event OnParcelPrimCountUpdateDelegate OnParcelPrimCountUpdate; public delegate void OnParcelPrimCountAddDelegate(SceneObjectGroup obj); - /// - /// Triggered in response to for - /// objects that actually contribute to parcel prim count. - /// - /// - /// Triggered by in - /// - /// public event OnParcelPrimCountAddDelegate OnParcelPrimCountAdd; public delegate void OnPluginConsoleDelegate(string[] args); - /// - /// Triggered after - /// has been called for all - /// loaded via . - /// Handlers for this event are typically used to parse the arguments - /// from in order to process or - /// filter the arguments and pass them onto - /// - /// - /// Triggered by in - /// via - /// via - /// via - /// via - /// - /// public event OnPluginConsoleDelegate OnPluginConsole; /// @@ -229,28 +121,8 @@ namespace OpenSim.Region.Framework.Scenes public delegate void OnSetRootAgentSceneDelegate(UUID agentID, Scene scene); - /// - /// Triggered before the grunt work for adding a root agent to a - /// scene has been performed (resuming attachment scripts, physics, - /// animations etc.) - /// - /// - /// Triggered before - /// by - /// in - /// via - /// and - /// public event OnSetRootAgentSceneDelegate OnSetRootAgentScene; - /// - /// Triggered after parcel properties have been updated. - /// - /// - /// Triggered by in - /// , - /// - /// public event ParcelPropertiesUpdateRequest OnParcelPropertiesUpdateRequest; /// @@ -265,45 +137,13 @@ namespace OpenSim.Region.Framework.Scenes /// /// Fired when an object is touched/grabbed. /// - /// /// The originalID is the local ID of the part that was actually touched. The localID itself is always that of /// the root part. - /// Triggerd in response to - /// via - /// in - /// public event ObjectGrabDelegate OnObjectGrab; public delegate void ObjectGrabDelegate(uint localID, uint originalID, Vector3 offsetPos, IClientAPI remoteClient, SurfaceTouchEventArgs surfaceArgs); - /// - /// Triggered when an object is being touched/grabbed continuously. - /// - /// - /// Triggered in response to - /// via - /// in - /// public event ObjectGrabDelegate OnObjectGrabbing; - - /// - /// Triggered when an object stops being touched/grabbed. - /// - /// - /// Triggered in response to - /// via - /// in - /// public event ObjectDeGrabDelegate OnObjectDeGrab; - - /// - /// Triggered when a script resets. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// public event ScriptResetDelegate OnScriptReset; public event OnPermissionErrorDelegate OnPermissionError; @@ -313,105 +153,29 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Occurs after OnNewScript. - /// Triggered by - /// in /// public event NewRezScript OnRezScript; public delegate void NewRezScript(uint localID, UUID itemID, string script, int startParam, bool postOnRez, string engine, int stateSource); public delegate void RemoveScript(uint localID, UUID itemID); - - /// - /// Triggered when a script is removed from an object. - /// - /// - /// Triggered by - /// in , - /// , - /// , - /// - /// public event RemoveScript OnRemoveScript; public delegate void StartScript(uint localID, UUID itemID); - - /// - /// Triggered when a script starts. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event StartScript OnStartScript; public delegate void StopScript(uint localID, UUID itemID); - - /// - /// Triggered when a script stops. - /// - /// - /// Triggered by , - /// in , - /// , - /// - /// public event StopScript OnStopScript; public delegate bool SceneGroupMoved(UUID groupID, Vector3 delta); - - /// - /// Triggered when an object is moved. - /// - /// - /// Triggered by - /// in , - /// - /// public event SceneGroupMoved OnSceneGroupMove; public delegate void SceneGroupGrabed(UUID groupID, Vector3 offset, UUID userID); - - /// - /// Triggered when an object is grabbed. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// via - /// public event SceneGroupGrabed OnSceneGroupGrab; public delegate bool SceneGroupSpinStarted(UUID groupID); - - /// - /// Triggered when an object starts to spin. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event SceneGroupSpinStarted OnSceneGroupSpinStart; public delegate bool SceneGroupSpun(UUID groupID, Quaternion rotation); - - /// - /// Triggered when an object is being spun. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event SceneGroupSpun OnSceneGroupSpin; public delegate void LandObjectAdded(ILandObject newParcel); @@ -440,9 +204,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// At the point of firing, the scene still contains the client's scene presence. - /// - /// This is triggered under per-agent lock. So if you want to perform any long-running operations, please - /// do this on a separate thread. /// public event ClientClosed OnClientClosed; @@ -453,9 +214,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Occurs before OnRezScript - /// Triggered by - /// in , - /// /// public event NewScript OnNewScript; @@ -490,12 +248,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// Triggered after the scene receives a client's upload of an updated script and has stored it in an asset. - /// Triggered by - /// in - /// via - /// via - /// via - /// via /// public event UpdateScript OnUpdateScript; @@ -521,203 +273,48 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Triggered when some scene object properties change. - /// - /// /// ScriptChangedEvent is fired when a scene object property that a script might be interested /// in (such as color, scale or inventory) changes. Only enough information sent is for the LSL changed event. /// This is not an indication that the script has changed (see OnUpdateScript for that). /// This event is sent to a script to tell it that some property changed on /// the object the script is in. See http://lslwiki.net/lslwiki/wakka.php?wakka=changed . - /// Triggered by - /// in , - /// - /// + /// public event ScriptChangedEvent OnScriptChangedEvent; public delegate void ScriptChangedEvent(uint localID, uint change); public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); - - /// - /// Triggered when a script receives control input from an agent. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptControlEvent OnScriptControlEvent; public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); - - /// - /// Triggered when an object has arrived within a tolerance distance - /// of a motion target. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptAtTargetEvent OnScriptAtTargetEvent; public delegate void ScriptNotAtTargetEvent(uint localID); - - /// - /// Triggered when an object has a motion target but has not arrived - /// within a tolerance distance. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptNotAtTargetEvent OnScriptNotAtTargetEvent; public delegate void ScriptAtRotTargetEvent(uint localID, uint handle, Quaternion targetrot, Quaternion atrot); - - /// - /// Triggered when an object has arrived within a tolerance rotation - /// of a rotation target. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptAtRotTargetEvent OnScriptAtRotTargetEvent; public delegate void ScriptNotAtRotTargetEvent(uint localID); - - /// - /// Triggered when an object has a rotation target but has not arrived - /// within a tolerance rotation. - /// - /// - /// Triggered by - /// in - /// via , - /// via - /// public event ScriptNotAtRotTargetEvent OnScriptNotAtRotTargetEvent; public delegate void ScriptColliding(uint localID, ColliderArgs colliders); - - /// - /// Triggered when a physical collision has started between a prim - /// and something other than the region terrain. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptColliderStart; - - /// - /// Triggered when something that previously collided with a prim has - /// not stopped colliding with it. - /// - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptColliding; - - /// - /// Triggered when something that previously collided with a prim has - /// stopped colliding with it. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptCollidingEnd; - - /// - /// Triggered when a physical collision has started between an object - /// and the region terrain. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptLandColliderStart; - - /// - /// Triggered when an object that previously collided with the region - /// terrain has not yet stopped colliding with it. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptLandColliding; - - /// - /// Triggered when an object that previously collided with the region - /// terrain has stopped colliding with it. - /// - /// - /// Triggered by - /// in - /// via - /// via - /// via - /// public event ScriptColliding OnScriptLandColliderEnd; public delegate void OnMakeChildAgentDelegate(ScenePresence presence); - - /// - /// Triggered when an agent has been made a child agent of a scene. - /// - /// - /// Triggered by - /// in - /// via , - /// , - /// - /// public event OnMakeChildAgentDelegate OnMakeChildAgent; public delegate void OnSaveNewWindlightProfileDelegate(); public delegate void OnSendNewWindlightProfileTargetedDelegate(RegionLightShareData wl, UUID user); /// - /// Triggered after the grunt work for adding a root agent to a - /// scene has been performed (resuming attachment scripts, physics, - /// animations etc.) - /// - /// /// This event is on the critical path for transferring an avatar from one region to another. Try and do /// as little work on this event as possible, or do work asynchronously. - /// Triggered after - /// by - /// in - /// via - /// and - /// + /// public event Action OnMakeRootAgent; public event OnSendNewWindlightProfileTargetedDelegate OnSendNewWindlightProfileTargeted; @@ -743,17 +340,9 @@ namespace OpenSim.Region.Framework.Scenes public event AvatarKillData OnAvatarKilled; public delegate void AvatarKillData(uint KillerLocalID, ScenePresence avatar); - /* - public delegate void ScriptTimerEvent(uint localID, double timerinterval); - /// - /// Used to be triggered when the LSL timer event fires. - /// - /// - /// Triggered by - /// via - /// - public event ScriptTimerEvent OnScriptTimerEvent; - */ +// public delegate void ScriptTimerEvent(uint localID, double timerinterval); + +// public event ScriptTimerEvent OnScriptTimerEvent; public delegate void EstateToolsSunUpdate(ulong regionHandle, bool FixedTime, bool EstateSun, float LindenHour); public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); @@ -763,27 +352,12 @@ namespace OpenSim.Region.Framework.Scenes /// /// Triggered when an object is added to the scene. /// - /// - /// Triggered by - /// in , - /// , - /// - /// public event Action OnObjectAddedToScene; - /// - /// Delegate for - /// - /// The object being removed from the scene - public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); - /// /// Triggered when an object is removed from the scene. /// - /// - /// Triggered by - /// in - /// + public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; public delegate void NoticeNoLandDataFromStorage(); @@ -799,20 +373,6 @@ namespace OpenSim.Region.Framework.Scenes public event RequestParcelPrimCountUpdate OnRequestParcelPrimCountUpdate; public delegate void ParcelPrimCountTainted(); - - /// - /// Triggered when the parcel prim count has been altered. - /// - /// - /// Triggered by in - /// , - /// , - /// , - /// , - /// , - /// , - /// - /// public event ParcelPrimCountTainted OnParcelPrimCountTainted; public event GetScriptRunning OnGetScriptRunning; @@ -876,7 +436,7 @@ namespace OpenSim.Region.Framework.Scenes /// the scripts may not have started yet /// Message is non empty string if there were problems loading the oar file /// - public delegate void OarFileLoaded(Guid guid, List loadedScenes, string message); + public delegate void OarFileLoaded(Guid guid, string message); public event OarFileLoaded OnOarFileLoaded; /// @@ -929,13 +489,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// True if the duplicate will immediately be in the scene, false otherwise - /// - /// Triggered in - /// public event SceneObjectPartCopyDelegate OnSceneObjectPartCopy; public delegate void SceneObjectPartCopyDelegate(SceneObjectPart copy, SceneObjectPart original, bool userExposed); - public delegate void SceneObjectPartUpdated(SceneObjectPart sop, bool full); + public delegate void SceneObjectPartUpdated(SceneObjectPart sop); public event SceneObjectPartUpdated OnSceneObjectPartUpdated; public delegate void ScenePresenceUpdated(ScenePresence sp); @@ -973,28 +530,9 @@ namespace OpenSim.Region.Framework.Scenes public event PrimsLoaded OnPrimsLoaded; public delegate void TeleportStart(IClientAPI client, GridRegion destination, GridRegion finalDestination, uint teleportFlags, bool gridLogout); - - /// - /// Triggered when a teleport starts - /// - /// - /// Triggered by - /// in - /// and - /// via - /// public event TeleportStart OnTeleportStart; public delegate void TeleportFail(IClientAPI client, bool gridLogout); - - /// - /// Trigered when a teleport fails. - /// - /// - /// Triggered by - /// in - /// via - /// public event TeleportFail OnTeleportFail; public class MoneyTransferArgs : EventArgs @@ -1002,9 +540,7 @@ namespace OpenSim.Region.Framework.Scenes public UUID sender; public UUID receiver; - /// - /// Always false. The SL protocol sucks. - /// + // Always false. The SL protocol sucks. public bool authenticated = false; public int amount; @@ -1061,29 +597,8 @@ namespace OpenSim.Region.Framework.Scenes public delegate void LandBuy(Object sender, LandBuyArgs e); - /// - /// Triggered when an attempt to transfer grid currency occurs - /// - /// - /// Triggered in - /// via - /// via - /// via - /// public event MoneyTransferEvent OnMoneyTransfer; - - /// - /// Triggered after after - /// public event LandBuy OnLandBuy; - - /// - /// Triggered to allow or prevent a real estate transaction - /// - /// - /// Triggered in - /// - /// public event LandBuy OnValidateLandBuy; public void TriggerOnAttach(uint localID, UUID itemID, UUID avatarID) @@ -2520,11 +2035,7 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// this lets us keep track of nasty script events like timer, etc. - /// - /// - /// + // this lets us keep track of nasty script events like timer, etc. public void TriggerTimerEvent(uint objLocalID, double Interval) { throw new NotImplementedException("TriggerTimerEvent was thought to be not used anymore and the registration for the event from scene object part has been commented out due to a memory leak"); @@ -2586,7 +2097,7 @@ namespace OpenSim.Region.Framework.Scenes return 6; } - public void TriggerOarFileLoaded(Guid requestId, List loadedScenes, string message) + public void TriggerOarFileLoaded(Guid requestId, string message) { OarFileLoaded handlerOarFileLoaded = OnOarFileLoaded; if (handlerOarFileLoaded != null) @@ -2595,7 +2106,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(requestId, loadedScenes, message); + d(requestId, message); } catch (Exception e) { @@ -2880,7 +2391,7 @@ namespace OpenSim.Region.Framework.Scenes } } - public void TriggerSceneObjectPartUpdated(SceneObjectPart sop, bool full) + public void TriggerSceneObjectPartUpdated(SceneObjectPart sop) { SceneObjectPartUpdated handler = OnSceneObjectPartUpdated; if (handler != null) @@ -2889,7 +2400,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(sop, full); + d(sop); } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 6208a57433..906c1ee942 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -93,7 +93,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void StartScripts() { -// m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); + m_log.InfoFormat("[SCENE]: Starting scripts in {0}, please wait.", RegionInfo.RegionName); IScriptModule[] engines = RequestModuleInterfaces(); @@ -1469,7 +1469,7 @@ namespace OpenSim.Region.Framework.Scenes return newFolderID; } - public void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) + private void SendInventoryUpdate(IClientAPI client, InventoryFolderBase folder, bool fetchFolders, bool fetchItems) { if (folder == null) return; @@ -1997,9 +1997,6 @@ namespace OpenSim.Region.Framework.Scenes // If child prims have invalid perms, fix them grp.AdjustChildPrimPermissions(); - // If child prims have invalid perms, fix them - grp.AdjustChildPrimPermissions(); - if (remoteClient == null) { // Autoreturn has a null client. Nothing else does. So diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index ce6415a8b9..e9705435bc 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -38,20 +38,8 @@ namespace OpenSim.Region.Framework.Scenes { public partial class Scene { - /// - /// Send chat to listeners. - /// - /// - /// /param> - /// - /// - /// - /// - /// - /// - /// public void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, - UUID fromID, UUID targetID, bool fromAgent, bool broadcast) + UUID fromID, bool fromAgent, bool broadcast, UUID destination) { OSChatMessage args = new OSChatMessage(); @@ -61,7 +49,7 @@ namespace OpenSim.Region.Framework.Scenes args.Position = fromPos; args.SenderUUID = fromID; args.Scene = this; - args.Destination = targetID; + args.Destination = destination; if (fromAgent) { @@ -78,10 +66,6 @@ namespace OpenSim.Region.Framework.Scenes args.From = fromName; //args. -// m_log.DebugFormat( -// "[SCENE]: Sending message {0} on channel {1}, type {2} from {3}, broadcast {4}", -// args.Message.Replace("\n", "\\n"), args.Channel, args.Type, fromName, broadcast); - if (broadcast) EventManager.TriggerOnChatBroadcast(this, args); else @@ -91,7 +75,7 @@ namespace OpenSim.Region.Framework.Scenes protected void SimChat(byte[] message, ChatTypeEnum type, int channel, Vector3 fromPos, string fromName, UUID fromID, bool fromAgent, bool broadcast) { - SimChat(message, type, channel, fromPos, fromName, fromID, UUID.Zero, fromAgent, broadcast); + SimChat(message, type, channel, fromPos, fromName, fromID, fromAgent, broadcast, UUID.Zero); } /// @@ -559,7 +543,7 @@ namespace OpenSim.Region.Framework.Scenes if (!InventoryService.AddFolder(folder)) { m_log.WarnFormat( - "[AGENT INVENTORY]: Failed to create folder for user {0} {1}", + "[AGENT INVENTORY]: Failed to move create folder for user {0} {1}", remoteClient.Name, remoteClient.AgentId); } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 254333301e..649d54559e 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -79,11 +79,6 @@ namespace OpenSim.Region.Framework.Scenes public SynchronizeSceneHandler SynchronizeScene; - /// - /// Used to prevent simultaneous calls to RemoveClient() for the same agent from interfering with each other. - /// - private object m_removeClientLock = new object(); - /// /// Statistical information for this scene. /// @@ -108,31 +103,8 @@ namespace OpenSim.Region.Framework.Scenes /// public bool CollidablePrims { get; private set; } - /// - /// Minimum value of the size of a non-physical prim in each axis - /// - public float m_minNonphys = 0.001f; - - /// - /// Maximum value of the size of a non-physical prim in each axis - /// public float m_maxNonphys = 256; - - /// - /// Minimum value of the size of a physical prim in each axis - /// - public float m_minPhys = 0.01f; - - /// - /// Maximum value of the size of a physical prim in each axis - /// public float m_maxPhys = 10; - - /// - /// Max prims an object will hold - /// - public int m_linksetCapacity = 0; - public bool m_clampPrimSize; public bool m_trustBinaries; public bool m_allowScriptCrossings; @@ -313,31 +285,6 @@ namespace OpenSim.Region.Framework.Scenes } private volatile bool m_shuttingDown; - /// - /// Is the scene active? - /// - /// - /// If false, maintenance and update loops are not being run. Updates can still be triggered manually if - /// the scene is not active. - /// - public bool Active - { - get { return m_active; } - set - { - if (value) - { - if (!m_active) - Start(); - } - else - { - m_active = false; - } - } - } - private volatile bool m_active; - // private int m_lastUpdate; private bool m_firstHeartbeat = true; @@ -799,24 +746,12 @@ namespace OpenSim.Region.Framework.Scenes PhysicalPrims = startupConfig.GetBoolean("physical_prim", true); CollidablePrims = startupConfig.GetBoolean("collidable_prim", true); - m_minNonphys = startupConfig.GetFloat("NonPhysicalPrimMin", m_minNonphys); - if (RegionInfo.NonphysPrimMin > 0) - { - m_minNonphys = RegionInfo.NonphysPrimMin; - } - - m_maxNonphys = startupConfig.GetFloat("NonPhysicalPrimMax", m_maxNonphys); + m_maxNonphys = startupConfig.GetFloat("NonphysicalPrimMax", m_maxNonphys); if (RegionInfo.NonphysPrimMax > 0) { m_maxNonphys = RegionInfo.NonphysPrimMax; } - m_minPhys = startupConfig.GetFloat("PhysicalPrimMin", m_minPhys); - if (RegionInfo.PhysPrimMin > 0) - { - m_minPhys = RegionInfo.PhysPrimMin; - } - m_maxPhys = startupConfig.GetFloat("PhysicalPrimMax", m_maxPhys); if (RegionInfo.PhysPrimMax > 0) @@ -824,12 +759,6 @@ namespace OpenSim.Region.Framework.Scenes m_maxPhys = RegionInfo.PhysPrimMax; } - m_linksetCapacity = startupConfig.GetInt("LinksetPrims", m_linksetCapacity); - if (RegionInfo.LinksetCapacity > 0) - { - m_linksetCapacity = RegionInfo.LinksetCapacity; - } - SpawnPointRouting = startupConfig.GetString("SpawnPointRouting", "closest"); TelehubAllowLandmarks = startupConfig.GetBoolean("TelehubAllowLandmark", false); @@ -855,6 +784,13 @@ namespace OpenSim.Region.Framework.Scenes m_defaultScriptEngine = startupConfig.GetString("DefaultScriptEngine", "XEngine"); m_log.InfoFormat("[SCENE]: Default script engine {0}", m_defaultScriptEngine); + IConfig packetConfig = m_config.Configs["PacketPool"]; + if (packetConfig != null) + { + PacketPool.Instance.RecyclePackets = packetConfig.GetBoolean("RecyclePackets", true); + PacketPool.Instance.RecycleDataBlocks = packetConfig.GetBoolean("RecycleDataBlocks", true); + } + m_strictAccessControl = startupConfig.GetBoolean("StrictAccessControl", m_strictAccessControl); m_seeIntoBannedRegion = startupConfig.GetBoolean("SeeIntoBannedRegion", m_seeIntoBannedRegion); CombineRegions = startupConfig.GetBoolean("CombineContiguousRegions", false); @@ -918,8 +854,6 @@ namespace OpenSim.Region.Framework.Scenes } // FIXME: Ultimately this should be in a module. - SendPeriodicAppearanceUpdates = true; - IConfig appearanceConfig = m_config.Configs["Appearance"]; if (appearanceConfig != null) { @@ -1217,14 +1151,6 @@ namespace OpenSim.Region.Framework.Scenes public void SetSceneCoreDebug(Dictionary options) { - if (options.ContainsKey("active")) - { - bool active; - - if (bool.TryParse(options["active"], out active)) - Active = active; - } - if (options.ContainsKey("scripting")) { bool enableScripts = true; @@ -1300,12 +1226,6 @@ namespace OpenSim.Region.Framework.Scenes // This is the method that shuts down the scene. public override void Close() { - if (m_shuttingDown) - { - m_log.WarnFormat("[SCENE]: Ignoring close request because already closing {0}", Name); - return; - } - m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); StatsReporter.Close(); @@ -1352,14 +1272,6 @@ namespace OpenSim.Region.Framework.Scenes m_log.Debug("[SCENE]: Graph close"); m_sceneGraph.Close(); - if (!GridService.DeregisterRegion(RegionInfo.RegionID)) - m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); - - base.Close(); - - // XEngine currently listens to the EventManager.OnShutdown event to trigger script stop and persistence. - // Therefore. we must dispose of the PhysicsScene after this to prevent a window where script code can - // attempt to reference a null or disposed physics scene. if (PhysicsScene != null) { m_log.Debug("[SCENE]: Dispose Physics"); @@ -1369,6 +1281,13 @@ namespace OpenSim.Region.Framework.Scenes phys.Dispose(); phys = null; } + + if (!GridService.DeregisterRegion(RegionInfo.RegionID)) + m_log.WarnFormat("[SCENE]: Deregister from grid failed for region {0}", Name); + + // call the base class Close method. + m_log.Debug("[SCENE]: Base close"); + base.Close(); } /// @@ -1376,8 +1295,6 @@ namespace OpenSim.Region.Framework.Scenes /// public void Start() { - m_active = true; - // m_log.DebugFormat("[SCENE]: Starting Heartbeat timer for {0}", RegionInfo.RegionName); //m_heartbeatTimer.Enabled = true; @@ -1437,7 +1354,7 @@ namespace OpenSim.Region.Framework.Scenes #region Update Methods /// - /// Activate the various loops necessary to continually update the scene. + /// Performs per-frame updates regularly /// private void Heartbeat() { @@ -1494,7 +1411,7 @@ namespace OpenSim.Region.Framework.Scenes List coarseLocations; List avatarUUIDs; - while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) + while (!m_shuttingDown && (endRun == null || MaintenanceRun < endRun)) { runtc = Util.EnvironmentTickCount(); ++MaintenanceRun; @@ -1556,7 +1473,7 @@ namespace OpenSim.Region.Framework.Scenes int sleepMS; int framestart; - while (!m_shuttingDown && ((endFrame == null && Active) || Frame < endFrame)) + while (!m_shuttingDown && (endFrame == null || Frame < endFrame)) { framestart = Util.EnvironmentTickCount(); ++Frame; @@ -1755,19 +1672,15 @@ namespace OpenSim.Region.Framework.Scenes private void CheckAtTargets() { - List objs = null; - + List objs = new List(); lock (m_groupsWithTargets) { - if (m_groupsWithTargets.Count != 0) - objs = new List(m_groupsWithTargets.Values); + foreach (SceneObjectGroup grp in m_groupsWithTargets.Values) + objs.Add(grp); } - if (objs != null) - { - foreach (SceneObjectGroup entry in objs) - entry.checkAtTargets(); - } + foreach (SceneObjectGroup entry in objs) + entry.checkAtTargets(); } /// @@ -2280,14 +2193,10 @@ namespace OpenSim.Region.Framework.Scenes public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { - if (m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates)) - { + bool result = m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); + if (result) sceneObject.IsDeleted = false; - EventManager.TriggerObjectAddedToScene(sceneObject); - return true; - } - - return false; + return result; } /// @@ -2928,89 +2837,77 @@ namespace OpenSim.Region.Framework.Scenes public override ISceneAgent AddNewClient(IClientAPI client, PresenceType type) { - ScenePresence sp; - bool vialogin; - // Validation occurs in LLUDPServer - // - // XXX: A race condition exists here where two simultaneous calls to AddNewClient can interfere with - // each other. In practice, this does not currently occur in the code. AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(client.CircuitCode); - // We lock here on AgentCircuitData to prevent a race condition between the thread adding a new connection - // and a simultaneous one that removes it (as can happen if the client is closed at a particular point - // whilst connecting). - // - // It would be easier to lock across all NewUserConnection(), AddNewClient() and - // RemoveClient() calls for all agents, but this would allow a slow call (e.g. because of slow service - // response in some module listening to AddNewClient()) from holding up unrelated agent calls. - // - // In practice, the lock (this) in LLUDPServer.AddNewClient() currently lock across all - // AddNewClient() operations (though not other ops). - // In the future this can be relieved once locking per agent (not necessarily on AgentCircuitData) is improved. - lock (aCircuit) + bool vialogin + = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 + || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; + + CheckHeartbeat(); + + ScenePresence sp = GetScenePresence(client.AgentId); + + // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this + // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause + // other problems, and possible the code calling AddNewClient() should ensure that no client is already + // connected. + if (sp == null) { - vialogin - = (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0 - || (aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaLogin) != 0; - - CheckHeartbeat(); - - sp = GetScenePresence(client.AgentId); + m_log.DebugFormat( + "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", + client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); - // XXX: Not sure how good it is to add a new client if a scene presence already exists. Possibly this - // could occur if a viewer crashes and relogs before the old client is kicked out. But this could cause - // other problems, and possible the code calling AddNewClient() should ensure that no client is already - // connected. - if (sp == null) - { - m_log.DebugFormat( - "[SCENE]: Adding new child scene presence {0} {1} to scene {2} at pos {3}", - client.Name, client.AgentId, RegionInfo.RegionName, client.StartPos); - - m_clientManager.Add(client); - SubscribeToClientEvents(client); - - sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); - m_eventManager.TriggerOnNewPresence(sp); - - 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. - // All other AddNewClient calls find aCircuit.child to be true. - if (aCircuit.child == false) - { - // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to - // start the scripts again (since this is done in RezAttachments()). - // XXX: This is convoluted. - sp.IsChildAgent = false; - - if (AttachmentsModule != null) - Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); - } - } - else - { - m_log.WarnFormat( - "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", - sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); - } - - // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the - // client is for a root or child agent. - client.SceneAgent = sp; + m_clientManager.Add(client); + SubscribeToClientEvents(client); - // Cache the user's name - CacheUserName(sp, aCircuit); - - EventManager.TriggerOnNewClient(client); - if (vialogin) - EventManager.TriggerOnClientLogin(client); + sp = m_sceneGraph.CreateAndAddChildScenePresence(client, aCircuit.Appearance, type); + m_eventManager.TriggerOnNewPresence(sp); + + 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. + // All other AddNewClient calls find aCircuit.child to be true. + if (aCircuit.child == false) + { + // We have to set SP to be a root agent here so that SP.MakeRootAgent() will later not try to + // start the scripts again (since this is done in RezAttachments()). + // XXX: This is convoluted. + sp.IsChildAgent = false; + + if (AttachmentsModule != null) + Util.FireAndForget(delegate(object o) { AttachmentsModule.RezAttachments(sp); }); + } + } + else + { + m_log.WarnFormat( + "[SCENE]: Already found {0} scene presence for {1} in {2} when asked to add new scene presence", + sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); } + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + client.SceneAgent = sp; + m_LastLogin = Util.EnvironmentTickCount(); + // Cache the user's name + CacheUserName(sp, aCircuit); + + EventManager.TriggerOnNewClient(client); + if (vialogin) + { + EventManager.TriggerOnClientLogin(client); + // Send initial parcel data +/* this is done on TriggerOnNewClient by landmanegement respective event handler + Vector3 pos = sp.AbsolutePosition; + ILandObject land = LandChannel.GetLandObject(pos.X, pos.Y); + land.SendLandUpdateToClient(client); +*/ + } + return sp; } @@ -3550,132 +3447,110 @@ namespace OpenSim.Region.Framework.Scenes { // CheckHeartbeat(); bool isChildAgent = false; - AgentCircuitData acd; + ScenePresence avatar = GetScenePresence(agentID); - lock (m_removeClientLock) + if (avatar == null) { - acd = m_authenticateHandler.GetAgentCircuitData(agentID); + m_log.WarnFormat( + "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - if (acd == null) - { - m_log.ErrorFormat("[SCENE]: No agent circuit found for {0}, aborting Scene.RemoveClient", agentID); - return; - } - else - { - // We remove the acd up here to avoid later race conditions if two RemoveClient() calls occurred - // simultaneously. - // We also need to remove by agent ID since NPCs will have no circuit code. - m_authenticateHandler.RemoveCircuit(agentID); - } + return; } - lock (acd) + try { - ScenePresence avatar = GetScenePresence(agentID); - - if (avatar == null) + isChildAgent = avatar.IsChildAgent; + + m_log.DebugFormat( + "[SCENE]: Removing {0} agent {1} {2} from {3}", + (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); + + // Don't do this to root agents, it's not nice for the viewer + if (closeChildAgents && isChildAgent) { - m_log.WarnFormat( - "[SCENE]: Called RemoveClient() with agent ID {0} but no such presence is in the scene.", agentID); - - return; + // Tell a single agent to disconnect from the region. + IEventQueue eq = RequestModuleInterface(); + if (eq != null) + { + eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); + } + else + { + avatar.ControllingClient.SendShutdownConnectionNotice(); + } } - + + // Only applies to root agents. + if (avatar.ParentID != 0) + { + avatar.StandUp(); + } + + 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 + if (closeChildAgents && CapsModule != null) + CapsModule.RemoveCaps(agentID); + + // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever + // this method is doing is HORRIBLE!!! + avatar.Scene.NeedSceneCacheClear(avatar.UUID); + + if (closeChildAgents && !isChildAgent) + { + List regions = avatar.KnownRegionHandles; + regions.Remove(RegionInfo.RegionHandle); + m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); + } + + m_eventManager.TriggerClientClosed(agentID, this); + m_eventManager.TriggerOnRemovePresence(agentID); + + if (!isChildAgent) + { + if (AttachmentsModule != null) + { + AttachmentsModule.DeRezAttachments(avatar); + } + + ForEachClient( + delegate(IClientAPI client) + { + //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway + try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } + catch (NullReferenceException) { } + }); + } + + // It's possible for child agents to have transactions if changes are being made cross-border. + if (AgentTransactionsModule != null) + AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); + + m_authenticateHandler.RemoveCircuit(avatar.ControllingClient.CircuitCode); + m_log.Debug("[Scene] The avatar has left the building"); + } + catch (Exception e) + { + m_log.Error( + string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); + } + finally + { try { - isChildAgent = avatar.IsChildAgent; - - m_log.DebugFormat( - "[SCENE]: Removing {0} agent {1} {2} from {3}", - (isChildAgent ? "child" : "root"), avatar.Name, agentID, RegionInfo.RegionName); + // Always clean these structures up so that any failure above doesn't cause them to remain in the + // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering + // the same cleanup exception continually. + m_sceneGraph.RemoveScenePresence(agentID); + m_clientManager.Remove(agentID); - // Don't do this to root agents, it's not nice for the viewer - if (closeChildAgents && isChildAgent) - { - // Tell a single agent to disconnect from the region. - IEventQueue eq = RequestModuleInterface(); - if (eq != null) - { - eq.DisableSimulator(RegionInfo.RegionHandle, avatar.UUID); - } - else - { - avatar.ControllingClient.SendShutdownConnectionNotice(); - } - } - - // Only applies to root agents. - if (avatar.ParentID != 0) - { - avatar.StandUp(); - } - - 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 - if (closeChildAgents && CapsModule != null) - CapsModule.RemoveCaps(agentID); - -// // REFACTORING PROBLEM -- well not really a problem, but just to point out that whatever -// // this method is doing is HORRIBLE!!! - // Commented pending deletion since this method no longer appears to do anything at all -// avatar.Scene.NeedSceneCacheClear(avatar.UUID); - - if (closeChildAgents && !isChildAgent) - { - List regions = avatar.KnownRegionHandles; - regions.Remove(RegionInfo.RegionHandle); - m_sceneGridService.SendCloseChildAgentConnections(agentID, regions); - } - - m_eventManager.TriggerClientClosed(agentID, this); - m_eventManager.TriggerOnRemovePresence(agentID); - - if (!isChildAgent) - { - if (AttachmentsModule != null) - { - AttachmentsModule.DeRezAttachments(avatar); - } - - ForEachClient( - delegate(IClientAPI client) - { - //We can safely ignore null reference exceptions. It means the avatar is dead and cleaned up anyway - try { client.SendKillObject(avatar.RegionHandle, new List { avatar.LocalId }); } - catch (NullReferenceException) { } - }); - } - - // It's possible for child agents to have transactions if changes are being made cross-border. - if (AgentTransactionsModule != null) - AgentTransactionsModule.RemoveAgentAssetTransactions(agentID); - m_log.Debug("[Scene] The avatar has left the building"); + avatar.Close(); } catch (Exception e) { m_log.Error( - string.Format("[SCENE]: Exception removing {0} from {1}. Cleaning up. Exception ", avatar.Name, Name), e); - } - finally - { - try - { - // Always clean these structures up so that any failure above doesn't cause them to remain in the - // scene with possibly bad effects (e.g. continually timing out on unacked packets and triggering - // the same cleanup exception continually. - m_sceneGraph.RemoveScenePresence(agentID); - m_clientManager.Remove(agentID); - - avatar.Close(); - } - catch (Exception e) - { - m_log.Error( - string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); - } + string.Format("[SCENE]: Exception in final clean up of {0} in {1}. Exception ", avatar.Name, Name), e); } } @@ -3734,9 +3609,11 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. + /// At the moment, this consists of setting up the caps infrastructure + /// The return bool should allow for connections to be refused, but as not all calling paths + /// take proper notice of it let, we allowed banned users in still. /// /// CircuitData of the agent who is connecting - /// /// Outputs the reason for the false response on this string /// True if the region accepts this agent. False if it does not. False will /// also return a reason. @@ -3747,20 +3624,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// Do the work necessary to initiate a new user connection for a particular scene. - /// - /// - /// The return bool should allow for connections to be refused, but as not all calling paths - /// take proper notice of it yet, we still allowed banned users in. - /// - /// At the moment this method consists of setting up the caps infrastructure + /// At the moment, this consists of setting up the caps infrastructure /// The return bool should allow for connections to be refused, but as not all calling paths /// take proper notice of it let, we allowed banned users in still. - /// - /// This method is called by the login service (in the case of login) or another simulator (in the case of region - /// cross or teleport) to initiate the connection. It is not triggered by the viewer itself - the connection - /// is activated later when the viewer sends the initial UseCircuitCodePacket UDP packet (in the case of - /// the LLUDP stack). - /// + /// /// CircuitData of the agent who is connecting /// Outputs the reason for the false response on this string /// True for normal presence. False for NPC @@ -3859,86 +3726,83 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE]: Existing root scene presence detected for {0} {1} in {2} when connecting. Removing existing presence.", sp.Name, sp.UUID, RegionInfo.RegionName); - sp.ControllingClient.Close(true, true); + sp.ControllingClient.Close(); sp = null; } - lock (agent) + + //On login test land permisions + if (vialogin) { - //On login test land permisions - if (vialogin) + IUserAccountCacheModule cache = RequestModuleInterface(); + if (cache != null) + cache.Remove(agent.firstname + " " + agent.lastname); + if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) { - IUserAccountCacheModule cache = RequestModuleInterface(); - if (cache != null) - cache.Remove(agent.firstname + " " + agent.lastname); - if (!TestLandRestrictions(agent.AgentID, out reason, ref agent.startpos.X, ref agent.startpos.Y)) - { - m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); - return false; - } + m_log.DebugFormat("[CONNECTION BEGIN]: Denying access to {0} due to no land access", agent.AgentID.ToString()); + return false; } + } - if (sp == null) // We don't have an [child] agent here already + if (sp == null) // We don't have an [child] agent here already + { + if (requirePresenceLookup) { - if (requirePresenceLookup) - { - try - { - if (!VerifyUserPresence(agent, out reason)) - return false; - } catch (Exception e) - { - m_log.ErrorFormat( - "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); - return false; - } - } - try { - // Always check estate if this is a login. Always - // check if banned regions are to be blacked out. - if (vialogin || (!m_seeIntoBannedRegion)) - { - if (!AuthorizeUser(agent, out reason)) - return false; - } - } - catch (Exception e) + if (!VerifyUserPresence(agent, out reason)) + return false; + } catch (Exception e) { m_log.ErrorFormat( - "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); + "[SCENE]: Exception verifying presence {0}{1}", e.Message, e.StackTrace); return false; } + } - m_log.InfoFormat( - "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", - RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, - agent.AgentID, agent.circuitcode); - - if (CapsModule != null) + try + { + // Always check estate if this is a login. Always + // check if banned regions are to be blacked out. + if (vialogin || (!m_seeIntoBannedRegion)) { - CapsModule.SetAgentCapsSeeds(agent); - CapsModule.CreateCaps(agent.AgentID); + if (!AuthorizeUser(agent, out reason)) + return false; } } - else + catch (Exception e) { - // Let the SP know how we got here. This has a lot of interesting - // uses down the line. - sp.TeleportFlags = (TPFlags)teleportFlags; + m_log.ErrorFormat( + "[SCENE]: Exception authorizing user {0}{1}", e.Message, e.StackTrace); + return false; + } - if (sp.IsChildAgent) - { - m_log.DebugFormat( - "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", - agent.AgentID, RegionInfo.RegionName); + m_log.InfoFormat( + "[SCENE]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", + RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, + agent.AgentID, agent.circuitcode); - sp.AdjustKnownSeeds(); + if (CapsModule != null) + { + CapsModule.SetAgentCapsSeeds(agent); + CapsModule.CreateCaps(agent.AgentID); + } + } else + { + // Let the SP know how we got here. This has a lot of interesting + // uses down the line. + sp.TeleportFlags = (TPFlags)teleportFlags; - if (CapsModule != null) - CapsModule.SetAgentCapsSeeds(agent); - } + if (sp.IsChildAgent) + { + m_log.DebugFormat( + "[SCENE]: Adjusting known seeds for existing agent {0} in {1}", + agent.AgentID, RegionInfo.RegionName); + + sp.AdjustKnownSeeds(); + + if (CapsModule != null) + CapsModule.SetAgentCapsSeeds(agent); } } @@ -4369,9 +4233,8 @@ namespace OpenSim.Region.Framework.Scenes return false; } - // We have to wait until the viewer contacts this region - // after receiving the EnableSimulator HTTP Event Queue message. This triggers the viewer to send - // a UseCircuitCode packet which in turn calls AddNewClient which finally creates the ScenePresence. + // We have to wait until the viewer contacts this region after receiving EAC. + // That calls AddNewClient, which finally creates the ScenePresence ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); if (childAgentUpdate != null) @@ -4466,18 +4329,15 @@ namespace OpenSim.Region.Framework.Scenes /// Tell a single agent to disconnect from the region. /// /// - /// - /// Force the agent to close even if it might be in the middle of some other operation. You do not want to - /// force unless you are absolutely sure that the agent is dead and a normal close is not working. - /// - public bool IncomingCloseAgent(UUID agentID, bool force) + /// + public bool IncomingCloseAgent(UUID agentID, bool childOnly) { //m_log.DebugFormat("[SCENE]: Processing incoming close agent for {0}", agentID); ScenePresence presence = m_sceneGraph.GetScenePresence(agentID); if (presence != null) { - presence.ControllingClient.Close(force, force); + presence.ControllingClient.Close(false); return true; } @@ -4683,16 +4543,6 @@ namespace OpenSim.Region.Framework.Scenes return LandChannel.GetLandObject(x, y).LandData; } - /// - /// Get LandData by position. - /// - /// - /// - public LandData GetLandData(Vector3 pos) - { - return GetLandData(pos.X, pos.Y); - } - public LandData GetLandData(uint x, uint y) { m_log.DebugFormat("[SCENE]: returning land for {0},{1}", x, y); @@ -4923,23 +4773,12 @@ namespace OpenSim.Region.Framework.Scenes /// Get a group via its UUID /// /// - /// null if no group with that id exists + /// null if no group with that name exists public SceneObjectGroup GetSceneObjectGroup(UUID fullID) { return m_sceneGraph.GetSceneObjectGroup(fullID); } - /// - /// Get a group via its local ID - /// - /// This will only return a group if the local ID matches a root part - /// - /// null if no group with that id exists - public SceneObjectGroup GetSceneObjectGroup(uint localID) - { - return m_sceneGraph.GetSceneObjectGroup(localID); - } - /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) @@ -4951,18 +4790,6 @@ namespace OpenSim.Region.Framework.Scenes return m_sceneGraph.GetSceneObjectGroup(name); } - /// - /// Attempt to get the SOG via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectGroup(UUID fullID, out SceneObjectGroup sog) - { - sog = GetSceneObjectGroup(fullID); - return sog != null; - } - /// /// Get a prim by name from the scene (will return the first /// found, if there are more than one prim with the same name) @@ -4994,18 +4821,6 @@ namespace OpenSim.Region.Framework.Scenes return m_sceneGraph.GetSceneObjectPart(fullID); } - /// - /// Attempt to get a prim via its UUID - /// - /// - /// - /// - public bool TryGetSceneObjectPart(UUID fullID, out SceneObjectPart sop) - { - sop = GetSceneObjectPart(fullID); - return sop != null; - } - /// /// Get a scene object group that contains the prim with the given local id /// @@ -5100,15 +4915,14 @@ namespace OpenSim.Region.Framework.Scenes client.SendRegionHandle(regionID, handle); } -// Commented pending deletion since this method no longer appears to do anything at all -// public bool NeedSceneCacheClear(UUID agentID) -// { -// IInventoryTransferModule inv = RequestModuleInterface(); -// if (inv == null) -// return true; -// -// return inv.NeedSceneCacheClear(agentID, this); -// } + public bool NeedSceneCacheClear(UUID agentID) + { + IInventoryTransferModule inv = RequestModuleInterface(); + if (inv == null) + return true; + + return inv.NeedSceneCacheClear(agentID, this); + } public void CleanTempObjects() { @@ -6062,9 +5876,6 @@ Environment.Exit(1); public string GetExtraSetting(string name) { - if (m_extraSettings == null) - return String.Empty; - string val; if (!m_extraSettings.TryGetValue(name, out val)) @@ -6075,9 +5886,6 @@ Environment.Exit(1); public void StoreExtraSetting(string name, string val) { - if (m_extraSettings == null) - return; - string oldVal; if (m_extraSettings.TryGetValue(name, out oldVal)) @@ -6095,9 +5903,6 @@ Environment.Exit(1); public void RemoveExtraSetting(string name) { - if (m_extraSettings == null) - return; - if (!m_extraSettings.ContainsKey(name)) return; diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index e599e908c7..af13b46568 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -342,7 +342,7 @@ namespace OpenSim.Region.Framework.Scenes public bool AddNewSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { - AddNewSceneObject(sceneObject, attachToBackup, false); + AddNewSceneObject(sceneObject, true, false); if (pos != null) sceneObject.AbsolutePosition = (Vector3)pos; @@ -421,9 +421,12 @@ namespace OpenSim.Region.Framework.Scenes { Vector3 scale = part.Shape.Scale; - scale.X = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(m_parentScene.m_minNonphys, Math.Min(m_parentScene.m_maxNonphys, scale.Z)); + if (scale.X > m_parentScene.m_maxNonphys) + scale.X = m_parentScene.m_maxNonphys; + if (scale.Y > m_parentScene.m_maxNonphys) + scale.Y = m_parentScene.m_maxNonphys; + if (scale.Z > m_parentScene.m_maxNonphys) + scale.Z = m_parentScene.m_maxNonphys; part.Shape.Scale = scale; } @@ -1062,30 +1065,6 @@ namespace OpenSim.Region.Framework.Scenes return null; } - /// - /// Get a group in the scene - /// - /// - /// This will only return a group if the local ID matches the root part, not other parts. - /// - /// Local id of the root part of the group - /// null if no such group was found - protected internal SceneObjectGroup GetSceneObjectGroup(uint localID) - { - lock (SceneObjectGroupsByLocalPartID) - { - if (SceneObjectGroupsByLocalPartID.ContainsKey(localID)) - { - SceneObjectGroup so = SceneObjectGroupsByLocalPartID[localID]; - - if (so.LocalId == localID) - return so; - } - } - - return null; - } - /// /// Get a group by name from the scene (will return the first /// found, if there are more than one prim with the same name) diff --git a/OpenSim/Region/Framework/Scenes/SceneManager.cs b/OpenSim/Region/Framework/Scenes/SceneManager.cs index dba3a6133b..f1b09cac37 100644 --- a/OpenSim/Region/Framework/Scenes/SceneManager.cs +++ b/OpenSim/Region/Framework/Scenes/SceneManager.cs @@ -92,11 +92,7 @@ namespace OpenSim.Region.Framework.Scenes private static SceneManager m_instance = null; public static SceneManager Instance { - get { - if (m_instance == null) - m_instance = new SceneManager(); - return m_instance; - } + get { return m_instance; } } private readonly DoubleDictionary m_localScenes = new DoubleDictionary(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 74d2629489..ee61de6505 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -2747,25 +2747,6 @@ namespace OpenSim.Region.Framework.Scenes if (objectGroup == this) return; - // If the configured linkset capacity is greater than zero, - // and the new linkset would have a prim count higher than this - // value, do not link it. - if (m_scene.m_linksetCapacity > 0 && - (PrimCount + objectGroup.PrimCount) > - m_scene.m_linksetCapacity) - { - m_log.DebugFormat( - "[SCENE OBJECT GROUP]: Cannot link group with root" + - " part {0}, {1} ({2} prims) to group with root part" + - " {3}, {4} ({5} prims) because the new linkset" + - " would exceed the configured maximum of {6}", - objectGroup.RootPart.Name, objectGroup.RootPart.UUID, - objectGroup.PrimCount, RootPart.Name, RootPart.UUID, - PrimCount, m_scene.m_linksetCapacity); - - return; - } - // 'linkPart' == the root of the group being linked into this group SceneObjectPart linkPart = objectGroup.m_rootPart; @@ -3511,33 +3492,27 @@ namespace OpenSim.Region.Framework.Scenes /// public void GroupResize(Vector3 scale) { -// m_log.DebugFormat( -// "[SCENE OBJECT GROUP]: Group resizing {0} {1} from {2} to {3}", Name, LocalId, RootPart.Scale, scale); + scale.X = Math.Min(scale.X, Scene.m_maxNonphys); + scale.Y = Math.Min(scale.Y, Scene.m_maxNonphys); + scale.Z = Math.Min(scale.Z, Scene.m_maxNonphys); PhysicsActor pa = m_rootPart.PhysActor; - if (Scene != null) + if (pa != null && pa.IsPhysical) { - scale.X = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(Scene.m_minNonphys, Math.Min(Scene.m_maxNonphys, scale.Z)); - - if (pa != null && pa.IsPhysical) - { - scale.X = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(Scene.m_minPhys, Math.Min(Scene.m_maxPhys, scale.Z)); - } + scale.X = Math.Min(scale.X, Scene.m_maxPhys); + scale.Y = Math.Min(scale.Y, Scene.m_maxPhys); + scale.Z = Math.Min(scale.Z, Scene.m_maxPhys); } float x = (scale.X / RootPart.Scale.X); float y = (scale.Y / RootPart.Scale.Y); float z = (scale.Z / RootPart.Scale.Z); - SceneObjectPart[] parts = m_parts.GetArray(); - - if (Scene != null & (x > 1.0f || y > 1.0f || z > 1.0f)) + SceneObjectPart[] parts; + if (x > 1.0f || y > 1.0f || z > 1.0f) { + parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; @@ -3550,7 +3525,7 @@ namespace OpenSim.Region.Framework.Scenes if (pa != null && pa.IsPhysical) { - if (oldSize.X * x > Scene.m_maxPhys) + if (oldSize.X * x > m_scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.X; a = f / x; @@ -3558,16 +3533,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < Scene.m_minPhys) - { - f = m_scene.m_minPhys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y * y > Scene.m_maxPhys) + if (oldSize.Y * y > m_scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Y; a = f / y; @@ -3575,16 +3542,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < Scene.m_minPhys) - { - f = m_scene.m_minPhys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z * z > Scene.m_maxPhys) + if (oldSize.Z * z > m_scene.m_maxPhys) { f = m_scene.m_maxPhys / oldSize.Z; a = f / z; @@ -3592,18 +3551,10 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < Scene.m_minPhys) - { - f = m_scene.m_minPhys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } } else { - if (oldSize.X * x > Scene.m_maxNonphys) + if (oldSize.X * x > m_scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.X; a = f / x; @@ -3611,16 +3562,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.X * x < Scene.m_minNonphys) - { - f = m_scene.m_minNonphys / oldSize.X; - a = f / x; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Y * y > Scene.m_maxNonphys) + if (oldSize.Y * y > m_scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Y; a = f / y; @@ -3628,16 +3571,8 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Y * y < Scene.m_minNonphys) - { - f = m_scene.m_minNonphys / oldSize.Y; - a = f / y; - x *= a; - y *= a; - z *= a; - } - if (oldSize.Z * z > Scene.m_maxNonphys) + if (oldSize.Z * z > m_scene.m_maxNonphys) { f = m_scene.m_maxNonphys / oldSize.Z; a = f / z; @@ -3645,14 +3580,6 @@ namespace OpenSim.Region.Framework.Scenes y *= a; z *= a; } - else if (oldSize.Z * z < Scene.m_minNonphys) - { - f = m_scene.m_minNonphys / oldSize.Z; - a = f / z; - x *= a; - y *= a; - z *= a; - } } } } @@ -3665,6 +3592,7 @@ namespace OpenSim.Region.Framework.Scenes RootPart.Resize(prevScale); + parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart obPart = parts[i]; diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 2191cfa4d4..165dd8503d 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -790,7 +790,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.ErrorFormat("[SCENEOBJECTPART]: GROUP POSITION. {0}", e); + m_log.Error("[SCENEOBJECTPART]: GROUP POSITION. " + e.Message); } } } @@ -2864,35 +2864,6 @@ namespace OpenSim.Region.Framework.Scenes SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); } - // The Collision sounds code calls this - public void SendCollisionSound(UUID soundID, double volume, Vector3 position) - { - if (soundID == UUID.Zero) - return; - - ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); - if (soundModule == null) - return; - - if (volume > 1) - volume = 1; - if (volume < 0) - volume = 0; - - int now = Util.EnvironmentTickCount(); - if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) - return; - - LastColSoundSentTime = now; - - UUID ownerID = OwnerID; - UUID objectID = ParentGroup.RootPart.UUID; - UUID parentID = ParentGroup.UUID; - ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; - - soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 ); - } - public void PhysicsOutOfBounds(Vector3 pos) { m_log.Error("[PHYSICS]: Physical Object went out of bounds."); @@ -2924,6 +2895,38 @@ namespace OpenSim.Region.Framework.Scenes ScheduleTerseUpdate(); } + public void PreloadSound(string sound) + { + // UUID ownerID = OwnerID; + UUID objectID = ParentGroup.RootPart.UUID; + UUID soundID = UUID.Zero; + + if (!UUID.TryParse(sound, out soundID)) + { + //Trys to fetch sound id from prim's inventory. + //Prim's inventory doesn't support non script items yet + + TaskInventory.LockItemsForRead(true); + + foreach (KeyValuePair item in TaskInventory) + { + if (item.Value.Name == sound) + { + soundID = item.Value.ItemID; + break; + } + } + + TaskInventory.LockItemsForRead(false); + } + + ParentGroup.Scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + if (!(Util.GetDistanceTo(sp.AbsolutePosition, AbsolutePosition) >= 100)) + sp.ControllingClient.SendPreLoadSound(objectID, objectID, soundID); + }); + } + public void RemFlag(PrimFlags flag) { // PrimFlags prevflag = Flags; @@ -2976,20 +2979,17 @@ namespace OpenSim.Region.Framework.Scenes /// public void Resize(Vector3 scale) { + scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxNonphys); + scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxNonphys); + scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxNonphys); + PhysicsActor pa = PhysActor; - if (ParentGroup.Scene != null) + if (pa != null && pa.IsPhysical) { - scale.X = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minNonphys, Math.Min(ParentGroup.Scene.m_maxNonphys, scale.Z)); - - if (pa != null && pa.IsPhysical) - { - scale.X = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.X)); - scale.Y = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Y)); - scale.Z = Math.Max(ParentGroup.Scene.m_minPhys, Math.Min(ParentGroup.Scene.m_maxPhys, scale.Z)); - } + scale.X = Math.Min(scale.X, ParentGroup.Scene.m_maxPhys); + scale.Y = Math.Min(scale.Y, ParentGroup.Scene.m_maxPhys); + scale.Z = Math.Min(scale.Z, ParentGroup.Scene.m_maxPhys); } // m_log.DebugFormat("[SCENE OBJECT PART]: Resizing {0} {1} to {2}", Name, LocalId, scale); @@ -3086,7 +3086,7 @@ namespace OpenSim.Region.Framework.Scenes // UUID, Name, TimeStampFull); if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); } /// @@ -3120,7 +3120,7 @@ namespace OpenSim.Region.Framework.Scenes } if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this); } public void ScriptSetPhysicsStatus(bool UsePhysics) @@ -3294,6 +3294,126 @@ namespace OpenSim.Region.Framework.Scenes } } + /// + /// Trigger or play an attached sound in this part's inventory. + /// + /// + /// + /// + /// + public void SendSound(string sound, double volume, bool triggered, byte flags, float radius, bool useMaster, bool isMaster) + { + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + + UUID ownerID = OwnerID; + UUID objectID = ParentGroup.RootPart.UUID; + UUID parentID = ParentGroup.UUID; + + UUID soundID = UUID.Zero; + Vector3 position = AbsolutePosition; // region local + ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + + if (!UUID.TryParse(sound, out soundID)) + { + // search sound file from inventory + TaskInventory.LockItemsForRead(true); + foreach (KeyValuePair item in TaskInventory) + { + if (item.Value.Name == sound && item.Value.Type == (int)AssetType.Sound) + { + soundID = item.Value.ItemID; + break; + } + } + TaskInventory.LockItemsForRead(false); + } + + if (soundID == UUID.Zero) + return; + + ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); + if (soundModule != null) + { + if (useMaster) + { + if (isMaster) + { + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + ParentGroup.PlaySoundMasterPrim = this; + ownerID = OwnerID; + objectID = ParentGroup.RootPart.UUID; + parentID = ParentGroup.UUID; + position = AbsolutePosition; // region local + regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + foreach (SceneObjectPart prim in ParentGroup.PlaySoundSlavePrims) + { + ownerID = prim.OwnerID; + objectID = prim.ParentGroup.RootPart.UUID; + parentID = prim.ParentGroup.UUID; + position = prim.AbsolutePosition; // region local + regionHandle = prim.ParentGroup.Scene.RegionInfo.RegionHandle; + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + } + ParentGroup.PlaySoundSlavePrims.Clear(); + ParentGroup.PlaySoundMasterPrim = null; + } + else + { + ParentGroup.PlaySoundSlavePrims.Add(this); + } + } + else + { + if (triggered) + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, radius); + else + soundModule.PlayAttachedSound(soundID, ownerID, objectID, volume, position, flags, radius); + } + } + } + + public void SendCollisionSound(UUID soundID, double volume, Vector3 position) + { + if (soundID == UUID.Zero) + return; + + ISoundModule soundModule = ParentGroup.Scene.RequestModuleInterface(); + if (soundModule == null) + return; + + if (volume > 1) + volume = 1; + if (volume < 0) + volume = 0; + + int now = Util.EnvironmentTickCount(); + if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) + return; + + LastColSoundSentTime = now; + + UUID ownerID = OwnerID; + UUID objectID = ParentGroup.RootPart.UUID; + UUID parentID = ParentGroup.UUID; + ulong regionHandle = ParentGroup.Scene.RegionInfo.RegionHandle; + + soundModule.TriggerSound(soundID, ownerID, objectID, parentID, volume, position, regionHandle, 0 ); + } + + /// /// Send a terse update to all clients /// @@ -3455,32 +3575,23 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Set the color & alpha of prim faces + /// Set the color of prim faces /// - /// /// - /// - public void SetFaceColorAlpha(int face, Vector3 color, double ?alpha) + /// + public void SetFaceColor(Vector3 color, int face) { - Vector3 clippedColor = Util.Clip(color, 0.0f, 1.0f); - float clippedAlpha = alpha.HasValue ? - Util.Clip((float)alpha.Value, 0.0f, 1.0f) : 0; - // The only way to get a deep copy/ If we don't do this, we can - // never detect color changes further down. + // mever detect color changes further down. Byte[] buf = Shape.Textures.GetBytes(); Primitive.TextureEntry tex = new Primitive.TextureEntry(buf, 0, buf.Length); Color4 texcolor; if (face >= 0 && face < GetNumberOfSides()) { texcolor = tex.CreateFace((uint)face).RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - if (alpha.HasValue) - { - texcolor.A = clippedAlpha; - } + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); tex.FaceTextures[face].RGBA = texcolor; UpdateTextureEntry(tex.GetBytes()); return; @@ -3492,23 +3603,15 @@ namespace OpenSim.Region.Framework.Scenes if (tex.FaceTextures[i] != null) { texcolor = tex.FaceTextures[i].RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - if (alpha.HasValue) - { - texcolor.A = clippedAlpha; - } + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); tex.FaceTextures[i].RGBA = texcolor; } texcolor = tex.DefaultTexture.RGBA; - texcolor.R = clippedColor.X; - texcolor.G = clippedColor.Y; - texcolor.B = clippedColor.Z; - if (alpha.HasValue) - { - texcolor.A = clippedAlpha; - } + texcolor.R = Util.Clip((float)color.X, 0.0f, 1.0f); + texcolor.G = Util.Clip((float)color.Y, 0.0f, 1.0f); + texcolor.B = Util.Clip((float)color.Z, 0.0f, 1.0f); tex.DefaultTexture.RGBA = texcolor; } UpdateTextureEntry(tex.GetBytes()); @@ -4796,57 +4899,6 @@ namespace OpenSim.Region.Framework.Scenes ScheduleFullUpdate(); } - public void UpdateSlice(float begin, float end) - { - if (end < begin) - { - float temp = begin; - begin = end; - end = temp; - } - end = Math.Min(1f, Math.Max(0f, end)); - begin = Math.Min(Math.Min(1f, Math.Max(0f, begin)), end - 0.02f); - if (begin < 0.02f && end < 0.02f) - { - begin = 0f; - end = 0.02f; - } - - ushort uBegin = (ushort)(50000.0 * begin); - ushort uEnd = (ushort)(50000.0 * (1f - end)); - bool updatePossiblyNeeded = false; - PrimType primType = GetPrimType(); - if (primType == PrimType.SPHERE || primType == PrimType.TORUS || primType == PrimType.TUBE || primType == PrimType.RING) - { - if (m_shape.ProfileBegin != uBegin || m_shape.ProfileEnd != uEnd) - { - m_shape.ProfileBegin = uBegin; - m_shape.ProfileEnd = uEnd; - updatePossiblyNeeded = true; - } - } - else if (m_shape.PathBegin != uBegin || m_shape.PathEnd != uEnd) - { - m_shape.PathBegin = uBegin; - m_shape.PathEnd = uEnd; - updatePossiblyNeeded = true; - } - - if (updatePossiblyNeeded && ParentGroup != null) - { - ParentGroup.HasGroupChanged = true; - } - if (updatePossiblyNeeded && PhysActor != null) - { - PhysActor.Shape = m_shape; - ParentGroup.Scene.PhysicsScene.AddPhysicsActorTaint(PhysActor); - } - if (updatePossiblyNeeded) - { - ScheduleFullUpdate(); - } - } - /// /// If the part is a sculpt/mesh, retrieve the mesh data and reinsert it into the shape so that the physics /// engine can use it. diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 3a9a146ee0..e010864b59 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -97,15 +97,6 @@ namespace OpenSim.Region.Framework.Scenes QueryScriptStates(); } } - - public int Count - { - get - { - lock (m_items) - return m_items.Count; - } - } /// /// Constructor @@ -244,52 +235,31 @@ namespace OpenSim.Region.Framework.Scenes if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) return; + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + if (engines == null) // No engine at all + return; + Items.LockItemsForRead(true); foreach (TaskInventoryItem item in Items.Values) { if (item.InvType == (int)InventoryType.LSL) { - bool running; - if (TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running)) - item.ScriptRunning = running; + foreach (IScriptModule e in engines) + { + bool running; + + if (e.HasScript(item.ItemID, out running)) + { + item.ScriptRunning = running; + break; + } + } } } Items.LockItemsForRead(false); } - public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) - { - running = false; - - TaskInventoryItem item = GetInventoryItem(itemId); - - if (item == null) - return false; - - return TryGetScriptInstanceRunning(m_part.ParentGroup.Scene, item, out running); - } - - public static bool TryGetScriptInstanceRunning(Scene scene, TaskInventoryItem item, out bool running) - { - running = false; - - if (item.InvType != (int)InventoryType.LSL) - return false; - - IScriptModule[] engines = scene.RequestModuleInterfaces(); - if (engines == null) // No engine at all - return false; - - foreach (IScriptModule e in engines) - { - if (e.HasScript(item.ItemID, out running)) - return true; - } - - return false; - } - public int CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) { int scriptsValidForStarting = 0; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 25a53b4142..2b9665cc38 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -69,15 +69,14 @@ namespace OpenSim.Region.Framework.Scenes public ScriptControlled eventControls; } - public delegate void SendCoarseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); + public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); public class ScenePresence : EntityBase, IScenePresence { // ~ScenePresence() // { -// m_log.DebugFormat("[SCENE PRESENCE]: Destructor called on {0}", Name); +// m_log.Debug("[SCENE PRESENCE] Destructor called"); // } - private void TriggerScenePresenceUpdated() { if (m_scene != null) @@ -189,7 +188,7 @@ namespace OpenSim.Region.Framework.Scenes /// public bool SitGround { get; private set; } - private SendCoarseLocationsMethod m_sendCoarseLocationsMethod; + private SendCourseLocationsMethod m_sendCourseLocationsMethod; //private Vector3 m_requestedSitOffset = new Vector3(); @@ -547,7 +546,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - PhysicsActor.TargetVelocity = value; + PhysicsActor.Velocity = value; } catch (Exception e) { @@ -712,7 +711,7 @@ namespace OpenSim.Region.Framework.Scenes AttachmentsSyncLock = new Object(); AllowMovement = true; IsChildAgent = true; - m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; + m_sendCourseLocationsMethod = SendCoarseLocationsDefault; Animator = new ScenePresenceAnimator(this); PresenceType = type; DrawDistance = world.DefaultDrawDistance; @@ -976,9 +975,7 @@ namespace OpenSim.Region.Framework.Scenes { if (wasChild && HasAttachments()) { - m_log.DebugFormat( - "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); - + m_log.DebugFormat("[SCENE PRESENCE]: Restarting scripts in attachments..."); // Resume scripts Util.FireAndForget(delegate(object x) { foreach (SceneObjectGroup sog in m_attachments) @@ -1534,22 +1531,17 @@ namespace OpenSim.Region.Framework.Scenes bool DCFlagKeyPressed = false; Vector3 agent_control_v3 = Vector3.Zero; - bool newFlying = actor.Flying; + bool oldflying = Flying; if (ForceFly) - newFlying = true; + actor.Flying = true; else if (FlyDisabled) - newFlying = false; + actor.Flying = false; else - newFlying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); + actor.Flying = ((flags & AgentManager.ControlFlags.AGENT_CONTROL_FLY) != 0); - if (actor.Flying != newFlying) - { - // Note: ScenePresence.Flying is actually fetched from the physical actor - // so setting PhysActor.Flying here also sets the ScenePresence's value. - actor.Flying = newFlying; + if (actor.Flying != oldflying) update_movementflag = true; - } if (ParentID == 0) { @@ -2631,17 +2623,17 @@ namespace OpenSim.Region.Framework.Scenes public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) { - SendCoarseLocationsMethod d = m_sendCoarseLocationsMethod; + SendCourseLocationsMethod d = m_sendCourseLocationsMethod; if (d != null) { d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); } } - public void SetSendCoarseLocationMethod(SendCoarseLocationsMethod d) + public void SetSendCourseLocationMethod(SendCourseLocationsMethod d) { if (d != null) - m_sendCoarseLocationsMethod = d; + m_sendCourseLocationsMethod = d; } public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) @@ -2845,7 +2837,7 @@ namespace OpenSim.Region.Framework.Scenes #region Significant Movement Method /// - /// This checks for a significant movement and sends a coarselocationchange update + /// This checks for a significant movement and sends a courselocationchange update /// protected void CheckForSignificantMovement() { @@ -3282,7 +3274,6 @@ namespace OpenSim.Region.Framework.Scenes } catch { } cAgent.DefaultAnim = Animator.Animations.DefaultAnimation; - cAgent.AnimState = Animator.Animations.ImplicitDefaultAnimation; if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(this, cAgent); @@ -3359,8 +3350,6 @@ namespace OpenSim.Region.Framework.Scenes Animator.Animations.FromArray(cAgent.Anims); if (cAgent.DefaultAnim != null) Animator.Animations.SetDefaultAnimation(cAgent.DefaultAnim.AnimID, cAgent.DefaultAnim.SequenceNum, UUID.Zero); - if (cAgent.AnimState != null) - Animator.Animations.SetImplicitDefaultAnimation(cAgent.AnimState.AnimID, cAgent.AnimState.SequenceNum, UUID.Zero); if (Scene.AttachmentsModule != null) Scene.AttachmentsModule.CopyAttachments(cAgent, this); @@ -3643,16 +3632,13 @@ namespace OpenSim.Region.Framework.Scenes public List GetAttachments(uint attachmentPoint) { List attachments = new List(); - - if (attachmentPoint >= 0) + + lock (m_attachments) { - lock (m_attachments) + foreach (SceneObjectGroup so in m_attachments) { - foreach (SceneObjectGroup so in m_attachments) - { - if (attachmentPoint == so.AttachmentPoint) - attachments.Add(so); - } + if (attachmentPoint == so.AttachmentPoint) + attachments.Add(so); } } diff --git a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs index 5398ab9816..756b1f44cd 100644 --- a/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs +++ b/OpenSim/Region/Framework/Scenes/SimStatsReporter.cs @@ -47,7 +47,6 @@ namespace OpenSim.Region.Framework.Scenes = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); public const string LastReportedObjectUpdateStatName = "LastReportedObjectUpdates"; - public const string SlowFramesStatName = "SlowFrames"; public delegate void SendStatResult(SimStats stats); @@ -129,16 +128,6 @@ namespace OpenSim.Region.Framework.Scenes get { return lastReportedSimStats; } } - /// - /// Number of frames that have taken longer to process than Scene.MIN_FRAME_TIME - /// - public Stat SlowFramesStat { get; private set; } - - /// - /// The threshold at which we log a slow frame. - /// - public int SlowFramesStatReportThreshold { get; private set; } - /// /// Extra sim statistics that are used by monitors but not sent to the client. /// @@ -237,24 +226,6 @@ namespace OpenSim.Region.Framework.Scenes if (StatsManager.SimExtraStats != null) OnSendStatsResult += StatsManager.SimExtraStats.ReceiveClassicSimStatsPacket; - - /// At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit - /// longer than ideal (which in itself is a concern). - SlowFramesStatReportThreshold = (int)Math.Ceiling(m_scene.MinFrameTime * 1000 * 1.2); - - SlowFramesStat - = new Stat( - "SlowFrames", - "Slow Frames", - "Number of frames where frame time has been significantly longer than the desired frame time.", - " frames", - "scene", - m_scene.Name, - StatType.Push, - null, - StatVerbosity.Info); - - StatsManager.RegisterStat(SlowFramesStat); } public void Close() @@ -472,7 +443,6 @@ namespace OpenSim.Region.Framework.Scenes lock (m_lastReportedExtraSimStats) { m_lastReportedExtraSimStats[LastReportedObjectUpdateStatName] = m_objectUpdates / m_statsUpdateFactor; - m_lastReportedExtraSimStats[SlowFramesStat.ShortName] = (float)SlowFramesStat.Value; Dictionary physicsStats = m_scene.PhysicsScene.GetStats(); @@ -593,11 +563,6 @@ namespace OpenSim.Region.Framework.Scenes public void addFrameMS(int ms) { m_frameMS += ms; - - // At the moment, we'll only report if a frame is over 120% of target, since commonly frames are a bit - // longer than ideal due to the inaccuracy of the Sleep in Scene.Update() (which in itself is a concern). - if (ms > SlowFramesStatReportThreshold) - SlowFramesStat.Value++; } public void addNetMS(int ms) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs index 5faf131caf..5758869e7a 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAgentTests.cs @@ -141,7 +141,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests TestScene scene = new SceneHelpers().SetupScene(); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); - scene.IncomingCloseAgent(sp.UUID, false); + scene.IncomingCloseAgent(sp.UUID); Assert.That(scene.GetScenePresence(sp.UUID), Is.Null); Assert.That(scene.AuthenticateHandler.GetAgentCircuitData(sp.UUID), Is.Null); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs index ac3da1e2cc..d722a0990a 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneTests.cs @@ -65,22 +65,5 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(scene.Frame, Is.EqualTo(1)); } - - [Test] - public void TestShutdownScene() - { - TestHelpers.InMethod(); - - Scene scene = new SceneHelpers().SetupScene(); - scene.Close(); - - Assert.That(scene.ShuttingDown, Is.True); - Assert.That(scene.Active, Is.False); - - // Trying to update a shutdown scene should result in no update - scene.Update(1); - - Assert.That(scene.Frame, Is.EqualTo(0)); - } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index 9457ebb374..44d2d452d5 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -50,40 +50,8 @@ using OpenSim.Tests.Common.Mock; namespace OpenSim.Region.Framework.Tests { [TestFixture] - public class UserInventoryTests : OpenSimTestCase + public class UserInventoryTests { - [Test] - public void TestCreateInventoryFolders() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // For this test both folders will have the same name which is legal in SL user inventories. - string foldersName = "f1"; - - Scene scene = new SceneHelpers().SetupScene(); - UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); - - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); - - List oneFolder - = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); - - Assert.That(oneFolder.Count, Is.EqualTo(1)); - InventoryFolderBase firstRetrievedFolder = oneFolder[0]; - Assert.That(firstRetrievedFolder.Name, Is.EqualTo(foldersName)); - - UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, foldersName); - - List twoFolders - = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, foldersName); - - Assert.That(twoFolders.Count, Is.EqualTo(2)); - Assert.That(twoFolders[0].Name, Is.EqualTo(foldersName)); - Assert.That(twoFolders[1].Name, Is.EqualTo(foldersName)); - Assert.That(twoFolders[0].ID, Is.Not.EqualTo(twoFolders[1].ID)); - } - [Test] public void TestGiveInventoryItem() { @@ -115,7 +83,7 @@ namespace OpenSim.Region.Framework.Tests public void TestGiveInventoryFolder() { TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); +// log4net.Config.XmlConfigurator.Configure(); Scene scene = new SceneHelpers().SetupScene(); UserAccount user1 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1001)); diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 2279e628b2..411e4214fe 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -52,23 +52,26 @@ namespace OpenSim.Region.Framework.Scenes public class UuidGatherer { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// Asset cache used for gathering assets + /// + protected IAssetService m_assetCache; + + /// + /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate + /// asset was found by the asset service. + /// + private AssetBase m_requestedObjectAsset; - protected IAssetService m_assetService; - -// /// -// /// Used as a temporary store of an asset which represents an object. This can be a null if no appropriate -// /// asset was found by the asset service. -// /// -// private AssetBase m_requestedObjectAsset; -// -// /// -// /// Signal whether we are currently waiting for the asset service to deliver an asset. -// /// -// private bool m_waitingForObjectAsset; + /// + /// Signal whether we are currently waiting for the asset service to deliver an asset. + /// + private bool m_waitingForObjectAsset; - public UuidGatherer(IAssetService assetService) + public UuidGatherer(IAssetService assetCache) { - m_assetService = assetService; + m_assetCache = assetCache; } /// @@ -188,18 +191,18 @@ namespace OpenSim.Region.Framework.Scenes } } -// /// -// /// The callback made when we request the asset for an object from the asset service. -// /// -// private void AssetReceived(string id, Object sender, AssetBase asset) -// { -// lock (this) -// { -// m_requestedObjectAsset = asset; -// m_waitingForObjectAsset = false; -// Monitor.Pulse(this); -// } -// } + /// + /// The callback made when we request the asset for an object from the asset service. + /// + private void AssetReceived(string id, Object sender, AssetBase asset) + { + lock (this) + { + m_requestedObjectAsset = asset; + m_waitingForObjectAsset = false; + Monitor.Pulse(this); + } + } /// /// Get an asset synchronously, potentially using an asynchronous callback. If the @@ -209,29 +212,25 @@ namespace OpenSim.Region.Framework.Scenes /// protected virtual AssetBase GetAsset(UUID uuid) { - return m_assetService.Get(uuid.ToString()); + m_waitingForObjectAsset = true; + m_assetCache.Get(uuid.ToString(), this, AssetReceived); - // XXX: Switching to do this synchronously where the call was async before but we always waited for it - // to complete anyway! -// m_waitingForObjectAsset = true; -// m_assetCache.Get(uuid.ToString(), this, AssetReceived); -// -// // The asset cache callback can either -// // -// // 1. Complete on the same thread (if the asset is already in the cache) or -// // 2. Come in via a different thread (if we need to go fetch it). -// // -// // The code below handles both these alternatives. -// lock (this) -// { -// if (m_waitingForObjectAsset) -// { -// Monitor.Wait(this); -// m_waitingForObjectAsset = false; -// } -// } -// -// return m_requestedObjectAsset; + // The asset cache callback can either + // + // 1. Complete on the same thread (if the asset is already in the cache) or + // 2. Come in via a different thread (if we need to go fetch it). + // + // The code below handles both these alternatives. + lock (this) + { + if (m_waitingForObjectAsset) + { + Monitor.Wait(this); + m_waitingForObjectAsset = false; + } + } + + return m_requestedObjectAsset; } /// @@ -362,47 +361,4 @@ namespace OpenSim.Region.Framework.Scenes } } } - - public class HGUuidGatherer : UuidGatherer - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - protected string m_assetServerURL; - - public HGUuidGatherer(IAssetService assetService, string assetServerURL) - : base(assetService) - { - m_assetServerURL = assetServerURL; - if (!m_assetServerURL.EndsWith("/") && !m_assetServerURL.EndsWith("=")) - m_assetServerURL = m_assetServerURL + "/"; - } - - protected override AssetBase GetAsset(UUID uuid) - { - if (string.Empty == m_assetServerURL) - return base.GetAsset(uuid); - else - return FetchAsset(uuid); - } - - public AssetBase FetchAsset(UUID assetID) - { - - // Test if it's already here - AssetBase asset = m_assetService.Get(assetID.ToString()); - if (asset == null) - { - // It's not, so fetch it from abroad - asset = m_assetService.Get(m_assetServerURL + assetID.ToString()); - if (asset != null) - m_log.DebugFormat("[HGUUIDGatherer]: Copied asset {0} from {1} to local asset server", assetID, m_assetServerURL); - else - m_log.DebugFormat("[HGUUIDGatherer]: Failed to fetch asset {0} from {1}", assetID, m_assetServerURL); - } - //else - // m_log.DebugFormat("[HGUUIDGatherer]: Asset {0} from {1} was already here", assetID, m_assetServerURL); - - return asset; - } - } } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 254eeb4d89..28b8293ece 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -891,10 +891,10 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Close() { - Close(true, false); + Close(true); } - public void Close(bool sendStop, bool force) + public void Close(bool sendStop) { Disconnect(); } @@ -959,8 +959,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, UUID ownerID, byte source, byte audible) + public void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, UUID fromAgentID, byte source, byte audible) { if (audible > 0 && message.Length > 0) IRC_SendChannelPrivmsg(fromName, message); diff --git a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs index 7639c6ce45..41ec14f224 100644 --- a/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Asset/AssetInfoModule.cs @@ -127,9 +127,6 @@ namespace OpenSim.Region.OptionalModules.Asset } string fileName = rawAssetId; - - if (!ConsoleUtil.CheckFileDoesNotExist(MainConsole.Instance, fileName)) - return; using (FileStream fs = new FileStream(fileName, FileMode.CreateNew)) { diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs index 68bcb4abff..d68aabc5ca 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/AttachmentsCommandModule.cs @@ -146,7 +146,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments sb.AppendFormat("Attachments for {0}\n", sp.Name); ConsoleDisplayTable ct = new ConsoleDisplayTable() { Indent = 2 }; - ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 50)); + ct.Columns.Add(new ConsoleDisplayTableColumn("Attachment Name", 36)); ct.Columns.Add(new ConsoleDisplayTableColumn("Local ID", 10)); ct.Columns.Add(new ConsoleDisplayTableColumn("Item ID", 36)); ct.Columns.Add(new ConsoleDisplayTableColumn("Attach Point", 14)); diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index 17971e3a58..31d0034444 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -130,37 +130,37 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments SendConsoleOutput(agentID, String.Format("auto_grant_attach_perms set to {0}", val)); } - private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) + private void llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) { SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); if (hostPart == null) - return 0; + return; if (hostPart.ParentGroup.IsAttachment) - return 0; + return; IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface(); if (attachmentsModule == null) - return 0; + return; TaskInventoryItem item = hostPart.Inventory.GetInventoryItem(script); if (item == null) - return 0; + return; if ((item.PermsMask & 32) == 0) // PERMISSION_ATTACH - return 0; + return; ScenePresence target; if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) - return 0; + return; if (target.UUID != hostPart.ParentGroup.OwnerID) { uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) - return 0; + return; hostPart.ParentGroup.SetOwnerId(target.UUID); hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); @@ -183,7 +183,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); } - return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true) ? 1 : 0; + attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, true, true); } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs index a01479896e..ca956fbe91 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Chat/IRCConnector.cs @@ -231,12 +231,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Chat if (m_server == null || m_baseNick == null || m_ircChannel == null || m_user == null) throw new Exception("Invalid connector configuration"); - // Generate an initial nickname + // Generate an initial nickname if randomizing is enabled if (m_randomizeNick) + { m_nick = m_baseNick + Util.RandomClass.Next(1, 99); - else - m_nick = m_baseNick; + } m_log.InfoFormat("[IRC-Connector-{0}]: Initialization complete", idn); diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index 5c3be29e9a..e22618dff3 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -546,9 +546,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge c.SenderUUID = UUID.Zero; c.Scene = agent.Scene; - agent.ControllingClient.SendChatMessage( - msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, UUID.Zero, - (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); + agent.ControllingClient.SendChatMessage(msg, (byte) ChatTypeEnum.Say, PosOfGod, m_whoami, UUID.Zero, + (byte)ChatSourceType.Object, (byte)ChatAudibleLevel.Fully); } private static void checkStringParameters(XmlRpcRequest request, string[] param) diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs index f292a75625..7b20446856 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/FreeSwitchVoice/FreeSwitchVoiceModule.cs @@ -447,7 +447,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.FreeSwitchVoice // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel - LandData land = scene.GetLandData(avatar.AbsolutePosition); + LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); //m_log.DebugFormat("[FreeSwitchVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); diff --git a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs index 8a8a31c27b..a30a38d3e6 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Voice/VivoxVoice/VivoxVoiceModule.cs @@ -623,7 +623,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.Voice.VivoxVoice // settings allow voice, then whether parcel allows // voice, if all do retrieve or obtain the parcel // voice channel - LandData land = scene.GetLandData(avatar.AbsolutePosition); + LandData land = scene.GetLandData(avatar.AbsolutePosition.X, avatar.AbsolutePosition.Y); // m_log.DebugFormat("[VivoxVoice][PARCELVOICE]: region \"{0}\": Parcel \"{1}\" ({2}): avatar \"{3}\": request: {4}, path: {5}, param: {6}", // scene.RegionInfo.RegionName, land.Name, land.LocalID, avatarName, request, path, param); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs index 1528330385..10b83e64dd 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsMessagingModule.cs @@ -27,7 +27,6 @@ using System; using System.Collections.Generic; -using System.Linq; using System.Reflection; using log4net; using Mono.Addins; @@ -37,8 +36,6 @@ using OpenMetaverse.StructuredData; using OpenSim.Framework; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups { @@ -48,7 +45,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private List m_sceneList = new List(); - private IPresenceService m_presenceService; private IMessageTransferModule m_msgTransferModule = null; @@ -58,27 +54,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups private bool m_groupMessagingEnabled = false; private bool m_debugEnabled = true; - /// - /// If enabled, module only tries to send group IMs to online users by querying cached presence information. - /// - private bool m_messageOnlineAgentsOnly; - - /// - /// Cache for online users. - /// - /// - /// Group ID is key, presence information for online members is value. - /// Will only be non-null if m_messageOnlineAgentsOnly = true - /// We cache here so that group messages don't constantly have to re-request the online user list to avoid - /// attempted expensive sending of messages to offline users. - /// The tradeoff is that a user that comes online will not receive messages consistently from all other users - /// until caches have updated. - /// Therefore, we set the cache expiry to just 20 seconds. - /// - private ExpiringCache m_usersOnlineCache; - - private int m_usersOnlineCacheExpirySeconds = 20; - #region IRegionModuleBase Members public void Initialise(IConfigSource config) @@ -108,17 +83,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - m_messageOnlineAgentsOnly = groupsConfig.GetBoolean("MessageOnlineUsersOnly", false); - - if (m_messageOnlineAgentsOnly) - m_usersOnlineCache = new ExpiringCache(); - m_debugEnabled = groupsConfig.GetBoolean("DebugEnabled", true); } - m_log.InfoFormat( - "[GROUPS-MESSAGING]: GroupsMessagingModule enabled with MessageOnlineOnly = {0}, DebugEnabled = {1}", - m_messageOnlineAgentsOnly, m_debugEnabled); + m_log.Info("[GROUPS-MESSAGING]: GroupsMessagingModule starting up"); } public void AddRegion(Scene scene) @@ -158,8 +126,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups return; } - if (m_presenceService == null) - m_presenceService = scene.PresenceService; m_sceneList.Add(scene); @@ -241,42 +207,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void SendMessageToGroup(GridInstantMessage im, UUID groupID) { List groupMembers = m_groupData.GetGroupMembers(new UUID(im.fromAgentID), groupID); - int groupMembersCount = groupMembers.Count; - - if (m_messageOnlineAgentsOnly) - { - string[] t1 = groupMembers.ConvertAll(gmd => gmd.AgentID.ToString()).ToArray(); - - // We cache in order not to overwhlem the presence service on large grids with many groups. This does - // mean that members coming online will not see all group members until after m_usersOnlineCacheExpirySeconds has elapsed. - // (assuming this is the same across all grid simulators). - PresenceInfo[] onlineAgents; - if (!m_usersOnlineCache.TryGetValue(groupID, out onlineAgents)) - { - onlineAgents = m_presenceService.GetAgents(t1); - m_usersOnlineCache.Add(groupID, onlineAgents, m_usersOnlineCacheExpirySeconds); - } - - HashSet onlineAgentsUuidSet = new HashSet(); - Array.ForEach(onlineAgents, pi => onlineAgentsUuidSet.Add(pi.UserID)); - - groupMembers = groupMembers.Where(gmd => onlineAgentsUuidSet.Contains(gmd.AgentID.ToString())).ToList(); - - // if (m_debugEnabled) -// m_log.DebugFormat( -// "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members, {2} online", -// groupID, groupMembersCount, groupMembers.Count()); - } - else - { - if (m_debugEnabled) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", - groupID, groupMembers.Count); - } - - int requestStartTick = Environment.TickCount; - + + if (m_debugEnabled) + m_log.DebugFormat( + "[GROUPS-MESSAGING]: SendMessageToGroup called for group {0} with {1} visible members", + groupID, groupMembers.Count); + foreach (GroupMembersData member in groupMembers) { if (m_groupData.hasAgentDroppedGroupChatSession(member.AgentID, groupID)) @@ -318,12 +254,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups ProcessMessageFromGroupSession(msg); } } - - // Temporary for assessing how long it still takes to send messages to large online groups. - if (m_messageOnlineAgentsOnly) - m_log.DebugFormat( - "[GROUPS-MESSAGING]: SendMessageToGroup for group {0} with {1} visible members, {2} online took {3}ms", - groupID, groupMembersCount, groupMembers.Count(), Environment.TickCount - requestStartTick); } #region SimGridEventHandlers diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 79e9994950..65bd26c773 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -123,36 +123,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups public void AddRegion(Scene scene) { if (m_groupsEnabled) - { scene.RegisterModuleInterface(this); - scene.AddCommand( - "debug", - this, - "debug groups verbose", - "debug groups verbose ", - "This setting turns on very verbose groups debugging", - HandleDebugGroupsVerbose); - } - } - - private void HandleDebugGroupsVerbose(object modules, string[] args) - { - if (args.Length < 4) - { - MainConsole.Instance.Output("Usage: debug groups verbose "); - return; - } - - bool verbose = false; - if (!bool.TryParse(args[3], out verbose)) - { - MainConsole.Instance.Output("Usage: debug groups verbose "); - return; - } - - m_debugEnabled = verbose; - - MainConsole.Instance.OutputFormat("{0} verbose logging set to {1}", Name, m_debugEnabled); } public void RegionLoaded(Scene scene) diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs index 732c28f66d..311531c8d4 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreModule.cs @@ -175,15 +175,14 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore /// /// // ----------------------------------------------------------------- - public bool CreateStore(string value, ref UUID result) + public bool CreateStore(string value, out UUID result) { - if (result == UUID.Zero) - result = UUID.Random(); - - JsonStore map = null; + result = UUID.Zero; if (! m_enabled) return false; + UUID uuid = UUID.Random(); + JsonStore map = null; try { @@ -196,8 +195,9 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore } lock (m_JsonValueStore) - m_JsonValueStore.Add(result,map); + m_JsonValueStore.Add(uuid,map); + result = uuid; return true; } @@ -231,7 +231,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore if (! m_JsonValueStore.TryGetValue(storeID,out map)) { m_log.InfoFormat("[JsonStore] Missing store {0}",storeID); - return false; + return true; } } diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index 6910d14c67..eaba816179 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs @@ -227,7 +227,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore protected UUID JsonCreateStore(UUID hostID, UUID scriptID, string value) { UUID uuid = UUID.Zero; - if (! m_store.CreateStore(value, ref uuid)) + if (! m_store.CreateStore(value, out uuid)) GenerateRuntimeError("Failed to create Json store"); return uuid; diff --git a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs index 5ed1514ad4..aa23fee0c5 100644 --- a/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs +++ b/OpenSim/Region/OptionalModules/Scripting/Minimodule/SOPObject.cs @@ -821,11 +821,8 @@ namespace OpenSim.Region.OptionalModules.Scripting.Minimodule { if (!CanEdit()) return; - ISoundModule module = m_rootScene.RequestModuleInterface(); - if (module != null) - { - module.SendSound(GetSOP().UUID, asset, volume, true, 0, 0, false, false); - } + + GetSOP().SendSound(asset.ToString(), volume, true, 0, 0, false, false); } #endregion diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index bad75f7819..fff3a32010 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -181,7 +181,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady } } - void OnOarFileLoaded(Guid requestId, List loadedScenes, string message) + void OnOarFileLoaded(Guid requestId, string message) { m_oarFileLoading = true; diff --git a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs similarity index 79% rename from OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs rename to OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs index dc54c3f821..c5c96a979f 100644 --- a/OpenSim/Region/CoreModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/ScriptModuleComms/ScriptModuleCommsModule.cs @@ -130,25 +130,13 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms m_scriptModule.PostScriptEvent(script, "link_message", args); } - private static MethodInfo GetMethodInfoFromType(Type target, string meth, bool searchInstanceMethods) - { - BindingFlags getMethodFlags = - BindingFlags.NonPublic | BindingFlags.Public; - - if (searchInstanceMethods) - getMethodFlags |= BindingFlags.Instance; - else - getMethodFlags |= BindingFlags.Static; - - return target.GetMethod(meth, getMethodFlags); - } - public void RegisterScriptInvocation(object target, string meth) { - MethodInfo mi = GetMethodInfoFromType(target.GetType(), meth, true); + MethodInfo mi = target.GetType().GetMethod(meth, + BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance); if (mi == null) { - m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", meth); + m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}",meth); return; } @@ -163,71 +151,38 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms public void RegisterScriptInvocation(object target, MethodInfo mi) { - m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, (target is Type) ? ((Type)target).Name : target.GetType().Name); + m_log.DebugFormat("[MODULE COMMANDS] Register method {0} from type {1}", mi.Name, target.GetType().Name); Type delegateType; - List typeArgs = mi.GetParameters() + var typeArgs = mi.GetParameters() .Select(p => p.ParameterType) .ToList(); if (mi.ReturnType == typeof(void)) { - delegateType = Expression.GetActionType(typeArgs.ToArray()); + delegateType = Expression.GetActionType(typeArgs.ToArray()); } else { - typeArgs.Add(mi.ReturnType); - delegateType = Expression.GetFuncType(typeArgs.ToArray()); + typeArgs.Add(mi.ReturnType); + delegateType = Expression.GetFuncType(typeArgs.ToArray()); } - Delegate fcall; - if (!(target is Type)) - fcall = Delegate.CreateDelegate(delegateType, target, mi); - else - fcall = Delegate.CreateDelegate(delegateType, (Type)target, mi.Name); + Delegate fcall = Delegate.CreateDelegate(delegateType, target, mi); lock (m_scriptInvocation) { - ParameterInfo[] parameters = fcall.Method.GetParameters(); + ParameterInfo[] parameters = fcall.Method.GetParameters (); if (parameters.Length < 2) // Must have two UUID params return; // Hide the first two parameters Type[] parmTypes = new Type[parameters.Length - 2]; - for (int i = 2; i < parameters.Length; i++) + for (int i = 2 ; i < parameters.Length ; i++) parmTypes[i - 2] = parameters[i].ParameterType; m_scriptInvocation[fcall.Method.Name] = new ScriptInvocationData(fcall.Method.Name, fcall, parmTypes, fcall.Method.ReturnType); } } - - public void RegisterScriptInvocation(Type target, string[] methods) - { - foreach (string method in methods) - { - MethodInfo mi = GetMethodInfoFromType(target, method, false); - if (mi == null) - m_log.WarnFormat("[MODULE COMMANDS] Failed to register method {0}", method); - else - RegisterScriptInvocation(target, mi); - } - } - - public void RegisterScriptInvocations(IRegionModuleBase target) - { - foreach(MethodInfo method in target.GetType().GetMethods( - BindingFlags.Public | BindingFlags.Instance | - BindingFlags.Static)) - { - if(method.GetCustomAttributes( - typeof(ScriptInvocationAttribute), true).Any()) - { - if(method.IsStatic) - RegisterScriptInvocation(target.GetType(), method); - else - RegisterScriptInvocation(target, method); - } - } - } public Delegate[] GetScriptInvocationList() { @@ -330,20 +285,6 @@ namespace OpenSim.Region.OptionalModules.Scripting.ScriptModuleComms } } - public void RegisterConstants(IRegionModuleBase target) - { - foreach (FieldInfo field in target.GetType().GetFields( - BindingFlags.Public | BindingFlags.Static | - BindingFlags.Instance)) - { - if (field.GetCustomAttributes( - typeof(ScriptConstantAttribute), true).Any()) - { - RegisterConstant(field.Name, field.GetValue(target)); - } - } - } - /// /// Operation to check for a registered constant /// diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 3a03101751..6c8e2fc9dc 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -148,7 +148,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC OnInstantMessage(this, new GridInstantMessage(m_scene, m_uuid, m_firstname + " " + m_lastname, target, 0, false, message, - UUID.Zero, false, Position, new byte[0], true)); + UUID.Zero, false, Position, new byte[0])); } public void SendAgentOffline(UUID[] agentIDs) @@ -607,15 +607,13 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void SendChatMessage( - string message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible) + public virtual void SendChatMessage(string message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) { } - public virtual void SendChatMessage( - byte[] message, byte type, Vector3 fromPos, string fromName, - UUID fromAgentID, UUID ownerID, byte source, byte audible) + public virtual void SendChatMessage(byte[] message, byte type, Vector3 fromPos, string fromName, + UUID fromAgentID, byte source, byte audible) { } @@ -911,13 +909,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void Close() { - Close(true, false); + Close(true); } - public void Close(bool sendStop, bool force) + public void Close(bool sendStop) { - // Remove ourselves from the scene - m_scene.RemoveClient(AgentId, false); } public void Start() diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index 52ed8468c6..91799667ab 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -117,12 +117,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(npc, Is.Not.Null); Assert.That(npc.Appearance.Texture.FaceTextures[8].TextureID, Is.EqualTo(originalFace8TextureId)); Assert.That(m_umMod.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); - - IClientAPI client; - Assert.That(m_scene.TryGetClient(npcId, out client), Is.True); - - // Have to account for both SP and NPC. - Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2)); } [Test] @@ -142,11 +136,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests ScenePresence deletedNpc = m_scene.GetScenePresence(npcId); Assert.That(deletedNpc, Is.Null); - IClientAPI client; - Assert.That(m_scene.TryGetClient(npcId, out client), Is.False); - - // Have to account for SP still present. - Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(1)); } [Test] diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs similarity index 57% rename from OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs rename to OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs index 23ef0523d8..683bc51163 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint6Dof.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BS6DofConstraint.cs @@ -32,14 +32,10 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSConstraint6Dof : BSConstraint +public class BS6DofConstraint : BSConstraint { - private static string LogHeader = "[BULLETSIM 6DOF CONSTRAINT]"; - - public override ConstraintType Type { get { return ConstraintType.D6_CONSTRAINT_TYPE; } } - // Create a btGeneric6DofConstraint - public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, + public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 frame1, Quaternion frame1rot, Vector3 frame2, Quaternion frame2rot, bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) @@ -48,52 +44,25 @@ public sealed class BSConstraint6Dof : BSConstraint m_body1 = obj1; m_body2 = obj2; m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, + BulletSimAPI.Create6DofConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, frame1, frame1rot, frame2, frame2rot, useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); m_enabled = true; - world.physicsScene.DetailLog("{0},BS6DofConstraint,createFrame,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); } - public BSConstraint6Dof(BulletSim world, BulletBody obj1, BulletBody obj2, + public BS6DofConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, Vector3 joinPoint, bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) { m_world = world; m_body1 = obj1; m_body2 = obj2; - if (obj1.ptr == IntPtr.Zero || obj2.ptr == IntPtr.Zero) - { - world.physicsScene.DetailLog("{0},BS6DOFConstraint,badBodyPtr,wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - BSScene.DetailLogZero, world.worldID, - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - world.physicsScene.Logger.ErrorFormat("{0} Attempt to build 6DOF constraint with missing bodies: wID={1}, rID={2}, rBody={3}, cID={4}, cBody={5}", - LogHeader, world.worldID, obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - m_enabled = false; - } - else - { - m_constraint = new BulletConstraint( - BulletSimAPI.Create6DofConstraintToPoint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - joinPoint, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - world.physicsScene.DetailLog("{0},BS6DofConstraint,createMidPoint,wID={1}, csrt={2}, rID={3}, rBody={4}, cID={5}, cBody={6}", - BSScene.DetailLogZero, world.worldID, m_constraint.ptr.ToString("X"), - obj1.ID, obj1.ptr.ToString("X"), obj2.ID, obj2.ptr.ToString("X")); - if (m_constraint.ptr == IntPtr.Zero) - { - world.physicsScene.Logger.ErrorFormat("{0} Failed creation of 6Dof constraint. rootID={1}, childID={2}", - LogHeader, obj1.ID, obj2.ID); - m_enabled = false; - } - else - { - m_enabled = true; - } - } + m_constraint = new BulletConstraint( + BulletSimAPI.Create6DofConstraintToPoint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + joinPoint, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; } public bool SetFrames(Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot) @@ -101,7 +70,7 @@ public sealed class BSConstraint6Dof : BSConstraint bool ret = false; if (m_enabled) { - BulletSimAPI.SetFrames2(m_constraint.ptr, frameA, frameArot, frameB, frameBrot); + BulletSimAPI.SetFrames2(m_constraint.Ptr, frameA, frameArot, frameB, frameBrot); ret = true; } return ret; @@ -112,9 +81,9 @@ public sealed class BSConstraint6Dof : BSConstraint bool ret = false; if (m_enabled) { - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); - BulletSimAPI.SetConstraintParam2(m_constraint.ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_CFM, cfm, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_STOP_ERP, erp, ConstraintParamAxis.AXIS_ALL); + BulletSimAPI.SetConstraintParam2(m_constraint.Ptr, ConstraintParams.BT_CONSTRAINT_CFM, cfm, ConstraintParamAxis.AXIS_ALL); ret = true; } return ret; @@ -125,7 +94,7 @@ public sealed class BSConstraint6Dof : BSConstraint bool ret = false; float onOff = useOffset ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) - ret = BulletSimAPI.UseFrameOffset2(m_constraint.ptr, onOff); + ret = BulletSimAPI.UseFrameOffset2(m_constraint.Ptr, onOff); return ret; } @@ -134,11 +103,7 @@ public sealed class BSConstraint6Dof : BSConstraint bool ret = false; float onOff = enable ? ConfigurationParameters.numericTrue : ConfigurationParameters.numericFalse; if (m_enabled) - { - ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.ptr, onOff, targetVelocity, maxMotorForce); - m_world.physicsScene.DetailLog("{0},BS6DOFConstraint,TransLimitMotor,enable={1},vel={2},maxForce={3}", - BSScene.DetailLogZero, enable, targetVelocity, maxMotorForce); - } + ret = BulletSimAPI.TranslationalLimitMotor2(m_constraint.Ptr, onOff, targetVelocity, maxMotorForce); return ret; } @@ -146,7 +111,7 @@ public sealed class BSConstraint6Dof : BSConstraint { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.ptr, threshold); + ret = BulletSimAPI.SetBreakingImpulseThreshold2(m_constraint.Ptr, threshold); return ret; } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs index 2a5397e9f4..e2f7af924c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSCharacter.cs @@ -28,48 +28,62 @@ using System; using System.Collections.Generic; using System.Reflection; using log4net; -using OMV = OpenMetaverse; +using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSCharacter : BSPhysObject +public class BSCharacter : PhysicsActor { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS CHAR]"; + private BSScene _scene; + public BSScene Scene { get { return _scene; } } + private String _avName; // private bool _stopped; - private OMV.Vector3 _size; + private Vector3 _size; + private Vector3 _scale; + private PrimitiveBaseShape _pbs; + private uint _localID = 0; private bool _grabbed; private bool _selected; - private OMV.Vector3 _position; + private Vector3 _position; private float _mass; - private float _avatarDensity; - private float _avatarVolume; - private OMV.Vector3 _force; - private OMV.Vector3 _velocity; - private OMV.Vector3 _torque; + public float _density; + public float _avatarVolume; + private Vector3 _force; + private Vector3 _velocity; + private Vector3 _torque; private float _collisionScore; - private OMV.Vector3 _acceleration; - private OMV.Quaternion _orientation; + private Vector3 _acceleration; + private Quaternion _orientation; private int _physicsActorType; private bool _isPhysical; private bool _flying; private bool _setAlwaysRun; private bool _throttleUpdates; private bool _isColliding; + private long _collidingStep; + private bool _collidingGround; + private long _collidingGroundStep; private bool _collidingObj; private bool _floatOnWater; - private OMV.Vector3 _rotationalVelocity; + private Vector3 _rotationalVelocity; private bool _kinematic; private float _buoyancy; - // The friction and velocity of the avatar is modified depending on whether walking or not. - private OMV.Vector3 _appliedVelocity; // the last velocity applied to the avatar - private float _currentFriction; // the friction currently being used (changed by setVelocity). + private BulletBody m_body; + public BulletBody Body { + get { return m_body; } + set { m_body = value; } + } - private OMV.Vector3 _PIDTarget; + private int _subscribedEventsMs = 0; + private int _nextCollisionOkTime = 0; + + private Vector3 _PIDTarget; private bool _usePID; private float _PIDTau; private bool _useHoverPID; @@ -77,507 +91,332 @@ public sealed class BSCharacter : BSPhysObject private PIDHoverType _PIDHoverType; private float _PIDHoverTao; - public BSCharacter(uint localID, String avName, BSScene parent_scene, OMV.Vector3 pos, OMV.Vector3 size, bool isFlying) + public BSCharacter(uint localID, String avName, BSScene parent_scene, Vector3 pos, Vector3 size, bool isFlying) { - base.BaseInitialize(parent_scene, localID, avName, "BSCharacter"); - _physicsActorType = (int)ActorTypes.Agent; + _localID = localID; + _avName = avName; + _scene = parent_scene; _position = pos; _size = size; _flying = isFlying; - _orientation = OMV.Quaternion.Identity; - _velocity = OMV.Vector3.Zero; - _appliedVelocity = OMV.Vector3.Zero; + _orientation = Quaternion.Identity; + _velocity = Vector3.Zero; _buoyancy = ComputeBuoyancyFromFlying(isFlying); - _currentFriction = PhysicsScene.Params.avatarStandingFriction; - _avatarDensity = PhysicsScene.Params.avatarDensity; - // The dimensions of the avatar capsule are kept in the scale. // Physics creates a unit capsule which is scaled by the physics engine. - ComputeAvatarScale(_size); - // set _avatarVolume and _mass based on capsule size, _density and Scale - ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.create,call,size={1},scale={2},density={3},volume={4},mass={5}", - LocalID, _size, Scale, _avatarDensity, _avatarVolume, RawMass); + _scale = new Vector3(_scene.Params.avatarCapsuleRadius, _scene.Params.avatarCapsuleRadius, size.Z); + _density = _scene.Params.avatarDensity; + ComputeAvatarVolumeAndMass(); // set _avatarVolume and _mass based on capsule size, _density and _scale + + ShapeData shapeData = new ShapeData(); + shapeData.ID = _localID; + shapeData.Type = ShapeData.PhysicsShapeType.SHAPE_AVATAR; + shapeData.Position = _position; + shapeData.Rotation = _orientation; + shapeData.Velocity = _velocity; + shapeData.Scale = _scale; + shapeData.Mass = _mass; + shapeData.Buoyancy = _buoyancy; + shapeData.Static = ShapeData.numericFalse; + shapeData.Friction = _scene.Params.avatarFriction; + shapeData.Restitution = _scene.Params.avatarRestitution; // do actual create at taint time - PhysicsScene.TaintedObject("BSCharacter.create", delegate() + _scene.TaintedObject("BSCharacter.create", delegate() { - DetailLog("{0},BSCharacter.create,taint", LocalID); - // New body and shape into BSBody and BSShape - PhysicsScene.Shapes.GetBodyAndShape(true, PhysicsScene.World, this, null, null); + BulletSimAPI.CreateObject(parent_scene.WorldID, shapeData); - SetPhysicalProperties(); + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + // avatars get all collisions no matter what + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); }); + return; } // called when this character is being destroyed and the resources should be released - public override void Destroy() + public void Destroy() { - DetailLog("{0},BSCharacter.Destroy", LocalID); - PhysicsScene.TaintedObject("BSCharacter.destroy", delegate() + // DetailLog("{0},BSCharacter.Destroy", LocalID); + _scene.TaintedObject("BSCharacter.destroy", delegate() { - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); + BulletSimAPI.DestroyObject(_scene.WorldID, _localID); }); } - private void SetPhysicalProperties() - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - ZeroMotion(); - ForcePosition = _position; - // Set the velocity and compute the proper friction - ForceVelocity = _velocity; - - BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.avatarRestitution); - BulletSimAPI.SetMargin2(PhysShape.ptr, PhysicsScene.Params.collisionMargin); - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - if (PhysicsScene.Params.ccdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - - UpdatePhysicalMassProperties(RawMass); - - // Make so capsule does not fall over - BulletSimAPI.SetAngularFactorV2(PhysBody.ptr, OMV.Vector3.Zero); - - BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_CHARACTER_OBJECT); - - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ACTIVE_TAG); - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_DEACTIVATION); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Do this after the object has been added to the world - BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, - (uint)CollisionFilterGroups.AvatarFilter, - (uint)CollisionFilterGroups.AvatarMask); - } - public override void RequestPhysicsterseUpdate() { base.RequestPhysicsterseUpdate(); } // No one calls this method so I don't know what it could possibly mean - public override bool Stopped { get { return false; } } - - public override OMV.Vector3 Size { + public override bool Stopped { + get { return false; } + } + public override Vector3 Size { get { // Avatar capsule size is kept in the scale parameter. - // return _size; - return new OMV.Vector3(Scale.X * 2f, Scale.Y * 2f, Scale.Z); + return new Vector3(_scale.X * 2, _scale.Y * 2, _scale.Z); } - set { - // When an avatar's size is set, only the height is changed. + set { + // When an avatar's size is set, only the height is changed + // and that really only depends on the radius. _size = value; - ComputeAvatarScale(_size); - ComputeAvatarVolumeAndMass(); - DetailLog("{0},BSCharacter.setSize,call,scale={1},density={2},volume={3},mass={4}", - LocalID, Scale, _avatarDensity, _avatarVolume, RawMass); + _scale.Z = (_size.Z * 1.15f) - (_scale.X + _scale.Y); - PhysicsScene.TaintedObject("BSCharacter.setSize", delegate() + // TODO: something has to be done with the avatar's vertical position + + ComputeAvatarVolumeAndMass(); + + _scene.TaintedObject("BSCharacter.setSize", delegate() { - BulletSimAPI.SetLocalScaling2(PhysShape.ptr, Scale); - UpdatePhysicalMassProperties(RawMass); + BulletSimAPI.SetObjectScaleMass(_scene.WorldID, LocalID, _scale, _mass, true); }); + } + } + public override PrimitiveBaseShape Shape { + set { _pbs = value; + } + } + public override uint LocalID { + set { _localID = value; } + get { return _localID; } } - - public override OMV.Vector3 Scale { get; set; } - - public override PrimitiveBaseShape Shape - { - set { BaseShape = value; } + public override bool Grabbed { + set { _grabbed = value; + } } - // I want the physics engine to make an avatar capsule - public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { - get {return ShapeData.PhysicsShapeType.SHAPE_AVATAR; } - } - - public override bool Grabbed { - set { _grabbed = value; } - } - public override bool Selected { - set { _selected = value; } + public override bool Selected { + set { _selected = value; + } } public override void CrossingFailure() { return; } public override void link(PhysicsActor obj) { return; } public override void delink() { return; } + public override void LockAngularMotion(Vector3 axis) { return; } - // Set motion values to zero. - // Do it to the properties so the values get set in the physics engine. - // Push the setting of the values to the viewer. - // Called at taint time! - public override void ZeroMotion() - { - _velocity = OMV.Vector3.Zero; - _acceleration = OMV.Vector3.Zero; - _rotationalVelocity = OMV.Vector3.Zero; - - // Zero some other properties directly into the physics engine - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, OMV.Vector3.Zero); - BulletSimAPI.SetInterpolationVelocity2(PhysBody.ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); - BulletSimAPI.ClearForces2(PhysBody.ptr); - } - - public override void LockAngularMotion(OMV.Vector3 axis) { return; } - - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { + public override Vector3 Position { get { - // Don't refetch the position because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition2(Scene.World.ptr, LocalID); - return _position; - } + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + return _position; + } set { _position = value; PositionSanityCheck(); - PhysicsScene.TaintedObject("BSCharacter.setPosition", delegate() + _scene.TaintedObject("BSCharacter.setPosition", delegate() { DetailLog("{0},BSCharacter.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } + } } - public override OMV.Vector3 ForcePosition { - get { - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } - } - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain or on water. + // Check for being below terrain and being out of bounds. // Returns 'true' of the position was made sane by some action. private bool PositionSanityCheck() { bool ret = false; - + // If below the ground, move the avatar up - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - if (Position.Z < terrainHeight) + float terrainHeight = Scene.GetTerrainHeightAtXYZ(_position); + if (_position.Z < terrainHeight) { - DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); + DetailLog("{0},BSCharacter.PositionAdjustUnderGround,call,pos={1},orient={2}", LocalID, _position, _orientation); _position.Z = terrainHeight + 2.0f; ret = true; } - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); - if (Position.Z < waterHeight) - { - _position.Z = waterHeight; - ret = true; - } - } // TODO: check for out of bounds + return ret; } - // A version of the sanity check that also makes sure a new position value is - // pushed back to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) - { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSCharacter.PositionSanityCheck", delegate() - { - DetailLog("{0},BSCharacter.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - }); - ret = true; - } - return ret; + public override float Mass { + get { + return _mass; + } } - - public override float Mass { get { return _mass; } } - - // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get {return _mass; } - } - public override void UpdatePhysicalMassProperties(float physMass) - { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); - } - - public override OMV.Vector3 Force { - get { return _force; } + public override Vector3 Force { + get { return _force; } set { _force = value; // m_log.DebugFormat("{0}: Force = {1}", LogHeader, _force); - PhysicsScene.TaintedObject("BSCharacter.SetForce", delegate() + Scene.TaintedObject("BSCharacter.SetForce", delegate() { DetailLog("{0},BSCharacter.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + BulletSimAPI.SetObjectForce(Scene.WorldID, LocalID, _force); }); - } + } } - // Avatars don't do vehicles - public override int VehicleType { get { return (int)Vehicle.TYPE_NONE; } set { return; } } + public override int VehicleType { + get { return 0; } + set { return; } + } public override void VehicleFloatParam(int param, float value) { } - public override void VehicleVectorParam(int param, OMV.Vector3 value) {} - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { } + public override void VehicleVectorParam(int param, Vector3 value) {} + public override void VehicleRotationParam(int param, Quaternion rotation) { } public override void VehicleFlags(int param, bool remove) { } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { return; } - public override OMV.Vector3 GeometricCenter { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 CenterOfMass { get { return OMV.Vector3.Zero; } } - public override OMV.Vector3 Velocity { - get { return _velocity; } + public override Vector3 GeometricCenter { get { return Vector3.Zero; } } + public override Vector3 CenterOfMass { get { return Vector3.Zero; } } + public override Vector3 Velocity { + get { return _velocity; } set { _velocity = value; // m_log.DebugFormat("{0}: set velocity = {1}", LogHeader, _velocity); - PhysicsScene.TaintedObject("BSCharacter.setVelocity", delegate() + _scene.TaintedObject("BSCharacter.setVelocity", delegate() { DetailLog("{0},BSCharacter.setVelocity,taint,vel={1}", LocalID, _velocity); - ForceVelocity = _velocity; + BulletSimAPI.SetObjectVelocity(_scene.WorldID, _localID, _velocity); }); - } + } } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - // Depending on whether the avatar is moving or not, change the friction - // to keep the avatar from slipping around - if (_velocity.Length() == 0) - { - if (_currentFriction != PhysicsScene.Params.avatarStandingFriction) - { - _currentFriction = PhysicsScene.Params.avatarStandingFriction; - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - else - { - if (_currentFriction != PhysicsScene.Params.avatarFriction) - { - _currentFriction = PhysicsScene.Params.avatarFriction; - BulletSimAPI.SetFriction2(PhysBody.ptr, _currentFriction); - } - } - _velocity = value; - // Remember the set velocity so we can suppress the reduction by friction, ... - _appliedVelocity = value; - - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - BulletSimAPI.Activate2(PhysBody.ptr, true); - } + public override Vector3 Torque { + get { return _torque; } + set { _torque = value; + } } - public override OMV.Vector3 Torque { - get { return _torque; } - set { _torque = value; - } + public override float CollisionScore { + get { return _collisionScore; } + set { _collisionScore = value; + } } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } - } - public override OMV.Vector3 Acceleration { + public override Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { - get { return _orientation; } + public override Quaternion Orientation { + get { return _orientation; } set { _orientation = value; // m_log.DebugFormat("{0}: set orientation to {1}", LogHeader, _orientation); - PhysicsScene.TaintedObject("BSCharacter.setOrientation", delegate() + _scene.TaintedObject("BSCharacter.setOrientation", delegate() { - // _position = BulletSimAPI.GetPosition2(BSBody.ptr); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } + } } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); - return _orientation; - } - set - { - _orientation = value; - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } + public override int PhysicsActorType { + get { return _physicsActorType; } + set { _physicsActorType = value; + } } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; - } - } - public override bool IsPhysical { - get { return _isPhysical; } + public override bool IsPhysical { + get { return _isPhysical; } set { _isPhysical = value; - } + } } - public override bool IsSolid { - get { return true; } - } - public override bool IsStatic { - get { return false; } - } - public override bool Flying { - get { return _flying; } + public override bool Flying { + get { return _flying; } set { - _flying = value; - // simulate flying by changing the effect of gravity - Buoyancy = ComputeBuoyancyFromFlying(_flying); - } + if (_flying != value) + { + _flying = value; + // simulate flying by changing the effect of gravity + this.Buoyancy = ComputeBuoyancyFromFlying(_flying); + } + } } - // Flying is implimented by changing the avatar's buoyancy. - // Would this be done better with a vehicle type? private float ComputeBuoyancyFromFlying(bool ifFlying) { return ifFlying ? 1f : 0f; } - public override bool - SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } + public override bool + SetAlwaysRun { + get { return _setAlwaysRun; } + set { _setAlwaysRun = value; } } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } + public override bool ThrottleUpdates { + get { return _throttleUpdates; } + set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { _isColliding = value; } + get { return (_collidingStep == _scene.SimulationStep); } + set { _isColliding = value; } } public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { CollidingGround = value; } + get { return (_collidingGroundStep == _scene.SimulationStep); } + set { _collidingGround = value; } } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } + public override bool CollidingObj { + get { return _collidingObj; } + set { _collidingObj = value; } } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSCharacter.setFloatOnWater", delegate() - { - if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - }); - } + public override bool FloatOnWater { + set { _floatOnWater = value; } } - public override OMV.Vector3 RotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } + public override Vector3 RotationalVelocity { + get { return _rotationalVelocity; } + set { _rotationalVelocity = value; } } - public override OMV.Vector3 ForceRotationalVelocity { - get { return _rotationalVelocity; } - set { _rotationalVelocity = value; } - } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; } + public override bool Kinematic { + get { return _kinematic; } + set { _kinematic = value; } } // neg=fall quickly, 0=1g, 1=0g, pos=float up - public override float Buoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - PhysicsScene.TaintedObject("BSCharacter.setBuoyancy", delegate() + public override float Buoyancy { + get { return _buoyancy; } + set { _buoyancy = value; + _scene.TaintedObject("BSCharacter.setBuoyancy", delegate() { DetailLog("{0},BSCharacter.setBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - ForceBuoyancy = _buoyancy; + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, LocalID, _buoyancy); }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { _buoyancy = value; - DetailLog("{0},BSCharacter.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); - } + } } // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } + public override Vector3 PIDTarget { + set { _PIDTarget = value; } } - public override bool PIDActive { - set { _usePID = value; } + public override bool PIDActive { + set { _usePID = value; } } - public override float PIDTau { - set { _PIDTau = value; } + public override float PIDTau { + set { _PIDTau = value; } } // Used for llSetHoverHeight and maybe vehicle height // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { + public override bool PIDHoverActive { set { _useHoverPID = value; } } - public override float PIDHoverHeight { + public override float PIDHoverHeight { set { _PIDHoverHeight = value; } } - public override PIDHoverType PIDHoverType { + public override PIDHoverType PIDHoverType { set { _PIDHoverType = value; } } - public override float PIDHoverTau { + public override float PIDHoverTau { set { _PIDHoverTao = value; } } // For RotLookAt - public override OMV.Quaternion APIDTarget { set { return; } } + public override Quaternion APIDTarget { set { return; } } public override bool APIDActive { set { return; } } public override float APIDStrength { set { return; } } public override float APIDDamping { set { return; } } - public override void AddForce(OMV.Vector3 force, bool pushforce) { + public override void AddForce(Vector3 force, bool pushforce) { if (force.IsFinite()) { _force.X += force.X; _force.Y += force.Y; _force.Z += force.Z; // m_log.DebugFormat("{0}: AddForce. adding={1}, newForce={2}", LogHeader, force, _force); - PhysicsScene.TaintedObject("BSCharacter.AddForce", delegate() + _scene.TaintedObject("BSCharacter.AddForce", delegate() { DetailLog("{0},BSCharacter.setAddForce,taint,addedForce={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + BulletSimAPI.AddObjectForce2(Body.Ptr, _force); }); } else @@ -587,75 +426,129 @@ public sealed class BSCharacter : BSPhysObject //m_lastUpdateSent = false; } - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + public override void AddAngularForce(Vector3 force, bool pushforce) { } - public override void SetMomentum(OMV.Vector3 momentum) { + public override void SetMomentum(Vector3 momentum) { } - private void ComputeAvatarScale(OMV.Vector3 size) - { - // The 'size' given by the simulator is the mid-point of the avatar - // and X and Y are unspecified. + // Turn on collision events at a rate no faster than one every the given milliseconds + public override void SubscribeEvents(int ms) { + _subscribedEventsMs = ms; + if (ms > 0) + { + // make sure first collision happens + _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; - OMV.Vector3 newScale = OMV.Vector3.Zero; - newScale.X = PhysicsScene.Params.avatarCapsuleRadius; - newScale.Y = PhysicsScene.Params.avatarCapsuleRadius; - - // From the total height, remove the capsule half spheres that are at each end - newScale.Z = size.Z- (newScale.X + newScale.Y); - Scale = newScale; + Scene.TaintedObject("BSCharacter.SubscribeEvents", delegate() + { + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } + } + // Stop collision events + public override void UnSubscribeEvents() { + _subscribedEventsMs = 0; + // Avatars get all their collision events + // Scene.TaintedObject("BSCharacter.UnSubscribeEvents", delegate() + // { + // BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + // }); + } + // Return 'true' if someone has subscribed to events + public override bool SubscribedEvents() { + return (_subscribedEventsMs > 0); } - // set _avatarVolume and _mass based on capsule size, _density and Scale + // set _avatarVolume and _mass based on capsule size, _density and _scale private void ComputeAvatarVolumeAndMass() { _avatarVolume = (float)( Math.PI - * Scale.X - * Scale.Y // the area of capsule cylinder - * Scale.Z // times height of capsule cylinder + * _scale.X + * _scale.Y // the area of capsule cylinder + * _scale.Z // times height of capsule cylinder + 1.33333333f * Math.PI - * Scale.X - * Math.Min(Scale.X, Scale.Y) - * Scale.Y // plus the volume of the capsule end caps + * _scale.X + * Math.Min(_scale.X, _scale.Y) + * _scale.Y // plus the volume of the capsule end caps ); - _mass = _avatarDensity * _avatarVolume; + _mass = _density * _avatarVolume; } // The physics engine says that properties have updated. Update same and inform // the world that things have changed. - public override void UpdateProperties(EntityProperties entprop) + public void UpdateProperties(EntityProperties entprop) { _position = entprop.Position; _orientation = entprop.Rotation; _velocity = entprop.Velocity; _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - // Do some sanity checking for the avatar. Make sure it's above ground and inbounds. - PositionSanityCheck(true); - - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - - if (entprop.Velocity != LastEntityProperties.Velocity) - { - // Changes in the velocity are suppressed in avatars. - // That's just the way they are defined. - OMV.Vector3 avVel = new OMV.Vector3(_appliedVelocity.X, _appliedVelocity.Y, entprop.Velocity.Z); - _velocity = avVel; - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, avVel); - } - - // Tell the linkset about value changes - Linkset.UpdateProperties(this); - // Avatars don't report their changes the usual way. Changes are checked for in the heartbeat loop. // base.RequestPhysicsterseUpdate(); + /* DetailLog("{0},BSCharacter.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + entprop.Acceleration, entprop.RotationalVelocity); + */ + } + + // Called by the scene when a collision with this object is reported + // The collision, if it should be reported to the character, is placed in a collection + // that will later be sent to the simulator when SendCollisions() is called. + CollisionEventUpdate collisionCollection = null; + public void Collide(uint collidingWith, ActorTypes type, Vector3 contactPoint, Vector3 contactNormal, float pentrationDepth) + { + // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); + + // The following makes IsColliding() and IsCollidingGround() work + _collidingStep = _scene.SimulationStep; + if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) + { + _collidingGroundStep = _scene.SimulationStep; + } + // DetailLog("{0},BSCharacter.Collison,call,with={1}", LocalID, collidingWith); + + // throttle collisions to the rate specified in the subscription + if (_subscribedEventsMs != 0) { + int nowTime = _scene.SimulationNowTime; + if (nowTime >= _nextCollisionOkTime) { + _nextCollisionOkTime = nowTime + _subscribedEventsMs; + + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + } + } + } + + public void SendCollisions() + { + /* + if (collisionCollection != null && collisionCollection.Count > 0) + { + base.SendCollisionUpdate(collisionCollection); + collisionCollection = null; + } + */ + // Kludge to make a collision call even if there are no collisions. + // This causes the avatar animation to get updated. + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + base.SendCollisionUpdate(collisionCollection); + // If there were any collisions in the collection, make sure we don't use the + // same instance next time. + if (collisionCollection.Count > 0) + collisionCollection = null; + // End kludge + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + Scene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs index 65fac00316..25084d80ac 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraint.cs @@ -34,20 +34,12 @@ namespace OpenSim.Region.Physics.BulletSPlugin public abstract class BSConstraint : IDisposable { - private static string LogHeader = "[BULLETSIM CONSTRAINT]"; - protected BulletSim m_world; protected BulletBody m_body1; protected BulletBody m_body2; protected BulletConstraint m_constraint; protected bool m_enabled = false; - public BulletBody Body1 { get { return m_body1; } } - public BulletBody Body2 { get { return m_body2; } } - public BulletConstraint Constraint { get { return m_constraint; } } - public abstract ConstraintType Type { get; } - public bool IsEnabled { get { return m_enabled; } } - public BSConstraint() { } @@ -56,25 +48,22 @@ public abstract class BSConstraint : IDisposable { if (m_enabled) { + // BulletSimAPI.RemoveConstraint(m_world.ID, m_body1.ID, m_body2.ID); + bool success = BulletSimAPI.DestroyConstraint2(m_world.Ptr, m_constraint.Ptr); + m_world.scene.DetailLog("{0},BSConstraint.Dispose,taint,body1={1},body2={2},success={3}", BSScene.DetailLogZero, m_body1.ID, m_body2.ID, success); + m_constraint.Ptr = System.IntPtr.Zero; m_enabled = false; - if (m_constraint.ptr != IntPtr.Zero) - { - bool success = BulletSimAPI.DestroyConstraint2(m_world.ptr, m_constraint.ptr); - m_world.physicsScene.DetailLog("{0},BSConstraint.Dispose,taint,id1={1},body1={2},id2={3},body2={4},success={5}", - BSScene.DetailLogZero, - m_body1.ID, m_body1.ptr.ToString("X"), - m_body2.ID, m_body2.ptr.ToString("X"), - success); - m_constraint.ptr = System.IntPtr.Zero; - } } } + public BulletBody Body1 { get { return m_body1; } } + public BulletBody Body2 { get { return m_body2; } } + public virtual bool SetLinearLimits(Vector3 low, Vector3 high) { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetLinearLimits2(m_constraint.ptr, low, high); + ret = BulletSimAPI.SetLinearLimits2(m_constraint.Ptr, low, high); return ret; } @@ -82,18 +71,7 @@ public abstract class BSConstraint : IDisposable { bool ret = false; if (m_enabled) - ret = BulletSimAPI.SetAngularLimits2(m_constraint.ptr, low, high); - return ret; - } - - public virtual bool SetSolverIterations(float cnt) - { - bool ret = false; - if (m_enabled) - { - BulletSimAPI.SetConstraintNumSolverIterations2(m_constraint.ptr, cnt); - ret = true; - } + ret = BulletSimAPI.SetAngularLimits2(m_constraint.Ptr, low, high); return ret; } @@ -103,7 +81,7 @@ public abstract class BSConstraint : IDisposable if (m_enabled) { // Recompute the internal transforms - BulletSimAPI.CalculateTransforms2(m_constraint.ptr); + BulletSimAPI.CalculateTransforms2(m_constraint.Ptr); ret = true; } return ret; @@ -119,14 +97,13 @@ public abstract class BSConstraint : IDisposable ret = CalculateTransforms(); if (ret) { - // Setting an object's mass to zero (making it static like when it's selected) - // automatically disables the constraints. - // If the link is enabled, be sure to set the constraint itself to enabled. - BulletSimAPI.SetConstraintEnable2(m_constraint.ptr, m_world.physicsScene.NumericBool(true)); + // m_world.scene.PhysicsLogging.Write("{0},BSConstraint.RecomputeConstraintVariables,taint,enabling,A={1},B={2}", + // BSScene.DetailLogZero, Body1.ID, Body2.ID); + BulletSimAPI.SetConstraintEnable2(m_constraint.Ptr, m_world.scene.NumericBool(true)); } else { - m_world.physicsScene.Logger.ErrorFormat("{0} CalculateTransforms failed. A={1}, B={2}", LogHeader, Body1.ID, Body2.ID); + m_world.scene.Logger.ErrorFormat("[BULLETSIM CONSTRAINT] CalculateTransforms failed. A={0}, B={1}", Body1.ID, Body2.ID); } } return ret; diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs index a9fd826528..22ea3671fc 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSConstraintCollection.cs @@ -33,7 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSConstraintCollection : IDisposable +public class BSConstraintCollection : IDisposable { // private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); // private static readonly string LogHeader = "[CONSTRAINT COLLECTION]"; @@ -143,6 +143,8 @@ public sealed class BSConstraintCollection : IDisposable // Return 'true' if any constraints were destroyed. public bool RemoveAndDestroyConstraint(BulletBody body1) { + // return BulletSimAPI.RemoveConstraintByID(m_world.ID, obj.ID); + List toRemove = new List(); uint lookingID = body1.ID; lock (m_constraints) diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 819635a98e..5a9f135c71 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -23,7 +23,7 @@ * 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. - * + */ /* RA: June 14, 2011. Copied from ODEDynamics.cs and converted to * call the BulletSim system. @@ -52,15 +52,19 @@ using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Physics.BulletSPlugin { - public sealed class BSDynamics + public class BSDynamics { - private BSScene PhysicsScene { get; set; } - // the prim this dynamic controller belongs to - private BSPrim Prim { get; set; } + private int frcount = 0; // Used to limit dynamics debug output to + // every 100th frame + + private BSPrim m_prim; // the prim this dynamic controller belongs to // Vehicle properties - public Vehicle Type { get; set; } - + private Vehicle m_type = Vehicle.TYPE_NONE; // If a 'VEHICLE', and what kind + public Vehicle Type + { + get { return m_type; } + } // private Quaternion m_referenceFrame = Quaternion.Identity; // Axis modifier private VehicleFlag m_flags = (VehicleFlag) 0; // Boolean settings: // HOVER_TERRAIN_ONLY @@ -70,15 +74,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // HOVER_UP_ONLY // LIMIT_MOTOR_UP // LIMIT_ROLL_ONLY + private VehicleFlag m_Hoverflags = (VehicleFlag)0; private Vector3 m_BlockingEndPoint = Vector3.Zero; private Quaternion m_RollreferenceFrame = Quaternion.Identity; - private Quaternion m_referenceFrame = Quaternion.Identity; - // Linear properties private Vector3 m_linearMotorDirection = Vector3.Zero; // velocity requested by LSL, decayed by time - private Vector3 m_linearMotorOffset = Vector3.Zero; // the point of force can be offset from the center private Vector3 m_linearMotorDirectionLASTSET = Vector3.Zero; // velocity requested by LSL - private Vector3 m_newVelocity = Vector3.Zero; // velocity computed to be applied to body + private Vector3 m_dir = Vector3.Zero; // velocity applied to body private Vector3 m_linearFrictionTimescale = Vector3.Zero; private float m_linearMotorDecayTimescale = 0; private float m_linearMotorTimescale = 0; @@ -89,28 +91,28 @@ namespace OpenSim.Region.Physics.BulletSPlugin //Angular properties private Vector3 m_angularMotorDirection = Vector3.Zero; // angular velocity requested by LSL motor - // private int m_angularMotorApply = 0; // application frame counter + private int m_angularMotorApply = 0; // application frame counter private Vector3 m_angularMotorVelocity = Vector3.Zero; // current angular motor velocity private float m_angularMotorTimescale = 0; // motor angular velocity ramp up rate private float m_angularMotorDecayTimescale = 0; // motor angular velocity decay rate private Vector3 m_angularFrictionTimescale = Vector3.Zero; // body angular velocity decay rate private Vector3 m_lastAngularVelocity = Vector3.Zero; // what was last applied to body - private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body + // private Vector3 m_lastVertAttractor = Vector3.Zero; // what VA was last applied to body //Deflection properties - private float m_angularDeflectionEfficiency = 0; - private float m_angularDeflectionTimescale = 0; - private float m_linearDeflectionEfficiency = 0; - private float m_linearDeflectionTimescale = 0; + // private float m_angularDeflectionEfficiency = 0; + // private float m_angularDeflectionTimescale = 0; + // private float m_linearDeflectionEfficiency = 0; + // private float m_linearDeflectionTimescale = 0; //Banking properties - private float m_bankingEfficiency = 0; - private float m_bankingMix = 0; - private float m_bankingTimescale = 0; + // private float m_bankingEfficiency = 0; + // private float m_bankingMix = 0; + // private float m_bankingTimescale = 0; //Hover and Buoyancy properties private float m_VhoverHeight = 0f; - private float m_VhoverEfficiency = 0f; +// private float m_VhoverEfficiency = 0f; private float m_VhoverTimescale = 0f; private float m_VhoverTargetHeight = -1.0f; // if <0 then no hover, else its the current target height private float m_VehicleBuoyancy = 0f; //KF: m_VehicleBuoyancy is set by VEHICLE_BUOYANCY for a vehicle. @@ -122,74 +124,86 @@ namespace OpenSim.Region.Physics.BulletSPlugin private float m_verticalAttractionEfficiency = 1.0f; // damped private float m_verticalAttractionTimescale = 500f; // Timescale > 300 means no vert attractor. - public BSDynamics(BSScene myScene, BSPrim myPrim) + public BSDynamics(BSPrim myPrim) { - PhysicsScene = myScene; - Prim = myPrim; - Type = Vehicle.TYPE_NONE; + m_prim = myPrim; + m_type = Vehicle.TYPE_NONE; } - // Return 'true' if this vehicle is doing vehicle things - public bool IsActive + internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue, float timestep) { - get { return Type != Vehicle.TYPE_NONE; } - } - - internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) - { - VDetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); + DetailLog("{0},ProcessFloatVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_DEFLECTION_EFFICIENCY: - m_angularDeflectionEfficiency = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionEfficiency = pValue; break; case Vehicle.ANGULAR_DEFLECTION_TIMESCALE: - m_angularDeflectionTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_angularDeflectionTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_DECAY_TIMESCALE: - m_angularMotorDecayTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorDecayTimescale = pValue; break; case Vehicle.ANGULAR_MOTOR_TIMESCALE: - m_angularMotorTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_angularMotorTimescale = pValue; break; case Vehicle.BANKING_EFFICIENCY: - m_bankingEfficiency = Math.Max(-1f, Math.Min(pValue, 1f)); + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingEfficiency = pValue; break; case Vehicle.BANKING_MIX: - m_bankingMix = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingMix = pValue; break; case Vehicle.BANKING_TIMESCALE: - m_bankingTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_bankingTimescale = pValue; break; case Vehicle.BUOYANCY: - m_VehicleBuoyancy = Math.Max(-1f, Math.Min(pValue, 1f)); - break; - case Vehicle.HOVER_EFFICIENCY: - m_VhoverEfficiency = Math.Max(0f, Math.Min(pValue, 1f)); + if (pValue < -1f) pValue = -1f; + if (pValue > 1f) pValue = 1f; + m_VehicleBuoyancy = pValue; break; +// case Vehicle.HOVER_EFFICIENCY: +// if (pValue < 0f) pValue = 0f; +// if (pValue > 1f) pValue = 1f; +// m_VhoverEfficiency = pValue; +// break; case Vehicle.HOVER_HEIGHT: m_VhoverHeight = pValue; break; case Vehicle.HOVER_TIMESCALE: - m_VhoverTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_VhoverTimescale = pValue; break; case Vehicle.LINEAR_DEFLECTION_EFFICIENCY: - m_linearDeflectionEfficiency = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionEfficiency = pValue; break; case Vehicle.LINEAR_DEFLECTION_TIMESCALE: - m_linearDeflectionTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + // m_linearDeflectionTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_DECAY_TIMESCALE: - m_linearMotorDecayTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorDecayTimescale = pValue; break; case Vehicle.LINEAR_MOTOR_TIMESCALE: - m_linearMotorTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_linearMotorTimescale = pValue; break; case Vehicle.VERTICAL_ATTRACTION_EFFICIENCY: - m_verticalAttractionEfficiency = Math.Max(0.1f, Math.Min(pValue, 1f)); + if (pValue < 0.1f) pValue = 0.1f; // Less goes unstable + if (pValue > 1.0f) pValue = 1.0f; + m_verticalAttractionEfficiency = pValue; break; case Vehicle.VERTICAL_ATTRACTION_TIMESCALE: - m_verticalAttractionTimescale = Math.Max(pValue, 0.01f); + if (pValue < 0.01f) pValue = 0.01f; + m_verticalAttractionTimescale = pValue; break; // These are vector properties but the engine lets you use a single float value to @@ -199,7 +213,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin break; case Vehicle.ANGULAR_MOTOR_DIRECTION: m_angularMotorDirection = new Vector3(pValue, pValue, pValue); - // m_angularMotorApply = 100; + m_angularMotorApply = 10; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue, pValue, pValue); @@ -209,27 +223,30 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue, pValue, pValue); break; case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue, pValue, pValue); + // m_linearMotorOffset = new Vector3(pValue, pValue, pValue); break; } }//end ProcessFloatVehicleParam - internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) + internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue, float timestep) { - VDetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); + DetailLog("{0},ProcessVectorVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.ANGULAR_FRICTION_TIMESCALE: m_angularFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.ANGULAR_MOTOR_DIRECTION: - // Limit requested angular speed to 2 rps= 4 pi rads/sec - pValue.X = Math.Max(-12.56f, Math.Min(pValue.X, 12.56f)); - pValue.Y = Math.Max(-12.56f, Math.Min(pValue.Y, 12.56f)); - pValue.Z = Math.Max(-12.56f, Math.Min(pValue.Z, 12.56f)); m_angularMotorDirection = new Vector3(pValue.X, pValue.Y, pValue.Z); - // m_angularMotorApply = 100; + // Limit requested angular speed to 2 rps= 4 pi rads/sec + if (m_angularMotorDirection.X > 12.56f) m_angularMotorDirection.X = 12.56f; + if (m_angularMotorDirection.X < - 12.56f) m_angularMotorDirection.X = - 12.56f; + if (m_angularMotorDirection.Y > 12.56f) m_angularMotorDirection.Y = 12.56f; + if (m_angularMotorDirection.Y < - 12.56f) m_angularMotorDirection.Y = - 12.56f; + if (m_angularMotorDirection.Z > 12.56f) m_angularMotorDirection.Z = 12.56f; + if (m_angularMotorDirection.Z < - 12.56f) m_angularMotorDirection.Z = - 12.56f; + m_angularMotorApply = 10; break; case Vehicle.LINEAR_FRICTION_TIMESCALE: m_linearFrictionTimescale = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -239,7 +256,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin m_linearMotorDirectionLASTSET = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.LINEAR_MOTOR_OFFSET: - m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); + // m_linearMotorOffset = new Vector3(pValue.X, pValue.Y, pValue.Z); break; case Vehicle.BLOCK_EXIT: m_BlockingEndPoint = new Vector3(pValue.X, pValue.Y, pValue.Z); @@ -249,11 +266,11 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessRotationVehicleParam(Vehicle pParam, Quaternion pValue) { - VDetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", Prim.LocalID, pParam, pValue); + DetailLog("{0},ProcessRotationalVehicleParam,param={1},val={2}", m_prim.LocalID, pParam, pValue); switch (pParam) { case Vehicle.REFERENCE_FRAME: - m_referenceFrame = pValue; + // m_referenceFrame = pValue; break; case Vehicle.ROLL_FRAME: m_RollreferenceFrame = pValue; @@ -263,416 +280,417 @@ namespace OpenSim.Region.Physics.BulletSPlugin internal void ProcessVehicleFlags(int pParam, bool remove) { - VDetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", Prim.LocalID, pParam, remove); - VehicleFlag parm = (VehicleFlag)pParam; - if (pParam == -1) - m_flags = (VehicleFlag)0; + DetailLog("{0},ProcessVehicleFlags,param={1},remove={2}", m_prim.LocalID, pParam, remove); + if (remove) + { + if (pParam == -1) + { + m_flags = (VehicleFlag)0; + m_Hoverflags = (VehicleFlag)0; + return; + } + if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) + { + if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_GLOBAL_HEIGHT); + } + if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) + { + if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY); + } + if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) + { + if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_UP_ONLY); + } + if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) + { + if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY); + } + if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) + { + if ((m_flags & VehicleFlag.LIMIT_MOTOR_UP) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.LIMIT_MOTOR_UP); + } + if ((pParam & (int)VehicleFlag.LIMIT_ROLL_ONLY) == (int)VehicleFlag.LIMIT_ROLL_ONLY) + { + if ((m_flags & VehicleFlag.LIMIT_ROLL_ONLY) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) + { + if ((m_flags & VehicleFlag.MOUSELOOK_BANK) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.MOUSELOOK_BANK); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) + { + if ((m_flags & VehicleFlag.MOUSELOOK_STEER) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.MOUSELOOK_STEER); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) + { + if ((m_flags & VehicleFlag.NO_DEFLECTION_UP) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP); + } + if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) + { + if ((m_flags & VehicleFlag.CAMERA_DECOUPLED) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.CAMERA_DECOUPLED); + } + if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) + { + if ((m_flags & VehicleFlag.NO_X) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_X); + } + if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) + { + if ((m_flags & VehicleFlag.NO_Y) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_Y); + } + if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) + { + if ((m_flags & VehicleFlag.NO_Z) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_Z); + } + if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) + { + if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != (VehicleFlag)0) + m_Hoverflags &= ~(VehicleFlag.LOCK_HOVER_HEIGHT); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) + { + if ((m_flags & VehicleFlag.NO_DEFLECTION) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.NO_DEFLECTION); + } + if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) + { + if ((m_flags & VehicleFlag.LOCK_ROTATION) != (VehicleFlag)0) + m_flags &= ~(VehicleFlag.LOCK_ROTATION); + } + } else { - if (remove) - m_flags &= ~parm; - else - m_flags |= parm; + if ((pParam & (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) == (int)VehicleFlag.HOVER_GLOBAL_HEIGHT) + { + m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT | m_flags); + } + if ((pParam & (int)VehicleFlag.HOVER_TERRAIN_ONLY) == (int)VehicleFlag.HOVER_TERRAIN_ONLY) + { + m_Hoverflags |= (VehicleFlag.HOVER_TERRAIN_ONLY | m_flags); + } + if ((pParam & (int)VehicleFlag.HOVER_UP_ONLY) == (int)VehicleFlag.HOVER_UP_ONLY) + { + m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY | m_flags); + } + if ((pParam & (int)VehicleFlag.HOVER_WATER_ONLY) == (int)VehicleFlag.HOVER_WATER_ONLY) + { + m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY | m_flags); + } + if ((pParam & (int)VehicleFlag.LIMIT_MOTOR_UP) == (int)VehicleFlag.LIMIT_MOTOR_UP) + { + m_flags |= (VehicleFlag.LIMIT_MOTOR_UP | m_flags); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_BANK) == (int)VehicleFlag.MOUSELOOK_BANK) + { + m_flags |= (VehicleFlag.MOUSELOOK_BANK | m_flags); + } + if ((pParam & (int)VehicleFlag.MOUSELOOK_STEER) == (int)VehicleFlag.MOUSELOOK_STEER) + { + m_flags |= (VehicleFlag.MOUSELOOK_STEER | m_flags); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION_UP) == (int)VehicleFlag.NO_DEFLECTION_UP) + { + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | m_flags); + } + if ((pParam & (int)VehicleFlag.CAMERA_DECOUPLED) == (int)VehicleFlag.CAMERA_DECOUPLED) + { + m_flags |= (VehicleFlag.CAMERA_DECOUPLED | m_flags); + } + if ((pParam & (int)VehicleFlag.NO_X) == (int)VehicleFlag.NO_X) + { + m_flags |= (VehicleFlag.NO_X); + } + if ((pParam & (int)VehicleFlag.NO_Y) == (int)VehicleFlag.NO_Y) + { + m_flags |= (VehicleFlag.NO_Y); + } + if ((pParam & (int)VehicleFlag.NO_Z) == (int)VehicleFlag.NO_Z) + { + m_flags |= (VehicleFlag.NO_Z); + } + if ((pParam & (int)VehicleFlag.LOCK_HOVER_HEIGHT) == (int)VehicleFlag.LOCK_HOVER_HEIGHT) + { + m_Hoverflags |= (VehicleFlag.LOCK_HOVER_HEIGHT); + } + if ((pParam & (int)VehicleFlag.NO_DEFLECTION) == (int)VehicleFlag.NO_DEFLECTION) + { + m_flags |= (VehicleFlag.NO_DEFLECTION); + } + if ((pParam & (int)VehicleFlag.LOCK_ROTATION) == (int)VehicleFlag.LOCK_ROTATION) + { + m_flags |= (VehicleFlag.LOCK_ROTATION); + } } - } + }//end ProcessVehicleFlags internal void ProcessTypeChange(Vehicle pType) { - VDetailLog("{0},ProcessTypeChange,type={1}", Prim.LocalID, pType); + DetailLog("{0},ProcessTypeChange,type={1}", m_prim.LocalID, pType); // Set Defaults For Type - Type = pType; + m_type = pType; switch (pType) { - case Vehicle.TYPE_NONE: + case Vehicle.TYPE_NONE: + m_linearFrictionTimescale = new Vector3(0, 0, 0); + m_angularFrictionTimescale = new Vector3(0, 0, 0); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 0; m_linearMotorDecayTimescale = 0; - m_linearFrictionTimescale = new Vector3(0, 0, 0); - m_angularMotorDirection = Vector3.Zero; - m_angularMotorDecayTimescale = 0; m_angularMotorTimescale = 0; - m_angularFrictionTimescale = new Vector3(0, 0, 0); - + m_angularMotorDecayTimescale = 0; m_VhoverHeight = 0; - m_VhoverEfficiency = 0; m_VhoverTimescale = 0; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 1000; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; m_flags = (VehicleFlag)0; break; case Vehicle.TYPE_SLED: + m_linearFrictionTimescale = new Vector3(30, 1, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1000; m_linearMotorDecayTimescale = 120; - m_linearFrictionTimescale = new Vector3(30, 1, 1000); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1000; m_angularMotorDecayTimescale = 120; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_VhoverHeight = 0; - m_VhoverEfficiency = 10; // TODO: this looks wrong!! +// m_VhoverEfficiency = 1; m_VhoverTimescale = 10; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 1; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 1000; - - m_verticalAttractionEfficiency = 0; - m_verticalAttractionTimescale = 0; - - m_bankingEfficiency = 0; - m_bankingTimescale = 10; - m_bankingMix = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); - m_flags &= + // m_linearDeflectionEfficiency = 1; + // m_linearDeflectionTimescale = 1; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 1000; + // m_bankingEfficiency = 0; + // m_bankingMix = 1; + // m_bankingTimescale = 10; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | VehicleFlag.LIMIT_MOTOR_UP); break; case Vehicle.TYPE_CAR: + m_linearFrictionTimescale = new Vector3(100, 2, 1000); + m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 1; m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(100, 2, 1000); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 1; m_angularMotorDecayTimescale = 0.8f; - m_angularFrictionTimescale = new Vector3(1000, 1000, 1000); - m_VhoverHeight = 0; - m_VhoverEfficiency = 0; +// m_VhoverEfficiency = 0; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 1; - m_linearDeflectionTimescale = 2; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 10; - + // // m_linearDeflectionEfficiency = 1; + // // m_linearDeflectionTimescale = 2; + // // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 10; m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 10f; - - m_bankingEfficiency = -0.2f; - m_bankingMix = 1; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_UP_ONLY); + // m_bankingEfficiency = -0.2f; + // m_bankingMix = 1; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_ROLL_ONLY | + VehicleFlag.LIMIT_MOTOR_UP); + m_Hoverflags |= (VehicleFlag.HOVER_UP_ONLY); break; case Vehicle.TYPE_BOAT: + m_linearFrictionTimescale = new Vector3(10, 3, 2); + m_angularFrictionTimescale = new Vector3(10,10,10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(10, 3, 2); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(10,10,10); - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; +// m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 2; m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 0.5f; - m_angularDeflectionTimescale = 5; - + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 0.5f; + // m_angularDeflectionTimescale = 5; m_verticalAttractionEfficiency = 0.5f; m_verticalAttractionTimescale = 5f; - - m_bankingEfficiency = -0.3f; - m_bankingMix = 0.8f; - m_bankingTimescale = 1; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_UP_ONLY); - m_flags |= (VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP - | VehicleFlag.HOVER_WATER_ONLY); + // m_bankingEfficiency = -0.3f; + // m_bankingMix = 0.8f; + // m_bankingTimescale = 1; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.LIMIT_ROLL_ONLY); + m_flags |= (VehicleFlag.NO_DEFLECTION_UP | + VehicleFlag.LIMIT_MOTOR_UP); + m_Hoverflags |= (VehicleFlag.HOVER_WATER_ONLY); break; case Vehicle.TYPE_AIRPLANE: + m_linearFrictionTimescale = new Vector3(200, 10, 5); + m_angularFrictionTimescale = new Vector3(20, 20, 20); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 2; m_linearMotorDecayTimescale = 60; - m_linearFrictionTimescale = new Vector3(200, 10, 5); - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 4; m_angularMotorDecayTimescale = 4; - m_angularFrictionTimescale = new Vector3(20, 20, 20); - m_VhoverHeight = 0; - m_VhoverEfficiency = 0.5f; +// m_VhoverEfficiency = 0.5f; m_VhoverTimescale = 1000; m_VehicleBuoyancy = 0; - - m_linearDeflectionEfficiency = 0.5f; - m_linearDeflectionTimescale = 3; - - m_angularDeflectionEfficiency = 1; - m_angularDeflectionTimescale = 2; - + // m_linearDeflectionEfficiency = 0.5f; + // m_linearDeflectionTimescale = 3; + // m_angularDeflectionEfficiency = 1; + // m_angularDeflectionTimescale = 2; m_verticalAttractionEfficiency = 0.9f; m_verticalAttractionTimescale = 2f; - - m_bankingEfficiency = 1; - m_bankingMix = 0.7f; - m_bankingTimescale = 2; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); + // m_bankingEfficiency = 1; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 2; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_GLOBAL_HEIGHT | VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); break; case Vehicle.TYPE_BALLOON: + m_linearFrictionTimescale = new Vector3(5, 5, 5); + m_angularFrictionTimescale = new Vector3(10, 10, 10); m_linearMotorDirection = Vector3.Zero; m_linearMotorTimescale = 5; - m_linearFrictionTimescale = new Vector3(5, 5, 5); m_linearMotorDecayTimescale = 60; - m_angularMotorDirection = Vector3.Zero; m_angularMotorTimescale = 6; - m_angularFrictionTimescale = new Vector3(10, 10, 10); m_angularMotorDecayTimescale = 10; - m_VhoverHeight = 5; - m_VhoverEfficiency = 0.8f; +// m_VhoverEfficiency = 0.8f; m_VhoverTimescale = 10; m_VehicleBuoyancy = 1; - - m_linearDeflectionEfficiency = 0; - m_linearDeflectionTimescale = 5; - - m_angularDeflectionEfficiency = 0; - m_angularDeflectionTimescale = 5; - + // m_linearDeflectionEfficiency = 0; + // m_linearDeflectionTimescale = 5; + // m_angularDeflectionEfficiency = 0; + // m_angularDeflectionTimescale = 5; m_verticalAttractionEfficiency = 1f; m_verticalAttractionTimescale = 100f; - - m_bankingEfficiency = 0; - m_bankingMix = 0.7f; - m_bankingTimescale = 5; - m_referenceFrame = Quaternion.Identity; - - m_referenceFrame = Quaternion.Identity; - m_flags &= ~(VehicleFlag.HOVER_WATER_ONLY - | VehicleFlag.HOVER_TERRAIN_ONLY - | VehicleFlag.HOVER_UP_ONLY - | VehicleFlag.NO_DEFLECTION_UP - | VehicleFlag.LIMIT_MOTOR_UP); - m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY - | VehicleFlag.HOVER_GLOBAL_HEIGHT); + // m_bankingEfficiency = 0; + // m_bankingMix = 0.7f; + // m_bankingTimescale = 5; + // m_referenceFrame = Quaternion.Identity; + m_Hoverflags &= ~(VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | + VehicleFlag.HOVER_UP_ONLY); + m_flags &= ~(VehicleFlag.NO_DEFLECTION_UP | VehicleFlag.LIMIT_MOTOR_UP); + m_flags |= (VehicleFlag.LIMIT_ROLL_ONLY); + m_Hoverflags |= (VehicleFlag.HOVER_GLOBAL_HEIGHT); break; } - } + }//end SetDefaultsForType - // Some of the properties of this prim may have changed. - // Do any updating needed for a vehicle - public void Refresh() - { - if (IsActive) - { - // Friction effects are handled by this vehicle code - BulletSimAPI.SetFriction2(Prim.PhysBody.ptr, 0f); - BulletSimAPI.SetHitFraction2(Prim.PhysBody.ptr, 0f); - } - } - - // One step of the vehicle properties for the next 'pTimestep' seconds. internal void Step(float pTimestep) { - if (!IsActive) return; + if (m_type == Vehicle.TYPE_NONE) return; - // DEBUG - // Because Bullet does apply forces to the vehicle, our last computed - // linear and angular velocities are not what is happening now. - // Vector3 externalAngularVelocity = Prim.ForceRotationalVelocity - m_lastAngularVelocity; - // m_lastAngularVelocity += (externalAngularVelocity * 0.5f) * pTimestep; - // m_lastAngularVelocity = Prim.ForceRotationalVelocity; // DEBUG: account for what Bullet did last time - // m_lastLinearVelocityVector = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG: - // END DEBUG + frcount++; // used to limit debug comment output + if (frcount > 100) + frcount = 0; MoveLinear(pTimestep); MoveAngular(pTimestep); LimitRotation(pTimestep); - // DEBUG: Trying to figure out why Bullet goes crazy when the root prim is moved. - // BulletSimAPI.SetInterpolationVelocity2(Prim.BSBody.ptr, m_newVelocity, m_lastAngularVelocity); // DEBUG DEBUG DEBUG - - // remember the position so next step we can limit absolute movement effects - m_lastPositionVector = Prim.ForcePosition; - - VDetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", - Prim.LocalID, Prim.ForcePosition, Prim.Force, Prim.ForceVelocity, Prim.RotationalVelocity); + DetailLog("{0},BSDynamics.Step,done,pos={1},force={2},velocity={3},angvel={4}", + m_prim.LocalID, m_prim.Position, m_prim.Force, m_prim.Velocity, m_prim.RotationalVelocity); }// end Step - // Apply the effect of the linear motor. - // Also does hover and float. private void MoveLinear(float pTimestep) { - // m_linearMotorDirection is the target direction we are moving relative to the vehicle coordinates - // m_lastLinearVelocityVector is the current speed we are moving in that direction - if (m_linearMotorDirection.LengthSquared() > 0.001f) + // requested m_linearMotorDirection is significant + // if (!m_linearMotorDirection.ApproxEquals(Vector3.Zero, 0.01f)) + if (m_linearMotorDirection.LengthSquared() > 0.0001f) { Vector3 origDir = m_linearMotorDirection; Vector3 origVel = m_lastLinearVelocityVector; - Vector3 vehicleVelocity = Prim.ForceVelocity * Quaternion.Inverse(Prim.ForceOrientation); // DEBUG // add drive to body - Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/(m_linearMotorTimescale) * pTimestep; - // lastLinearVelocityVector is the current body velocity vector + // Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale/pTimestep); + Vector3 addAmount = m_linearMotorDirection/(m_linearMotorTimescale); + // lastLinearVelocityVector is the current body velocity vector? + // RA: Not sure what the *10 is for. A correction for pTimestep? + // m_lastLinearVelocityVector += (addAmount*10); + m_lastLinearVelocityVector += addAmount; + + // This will work temporarily, but we really need to compare speed on an axis + // KF: Limit body velocity to applied velocity? + // Limit the velocity vector to less than the last set linear motor direction + if (Math.Abs(m_lastLinearVelocityVector.X) > Math.Abs(m_linearMotorDirectionLASTSET.X)) + m_lastLinearVelocityVector.X = m_linearMotorDirectionLASTSET.X; + if (Math.Abs(m_lastLinearVelocityVector.Y) > Math.Abs(m_linearMotorDirectionLASTSET.Y)) + m_lastLinearVelocityVector.Y = m_linearMotorDirectionLASTSET.Y; + if (Math.Abs(m_lastLinearVelocityVector.Z) > Math.Abs(m_linearMotorDirectionLASTSET.Z)) + m_lastLinearVelocityVector.Z = m_linearMotorDirectionLASTSET.Z; + + // decay applied velocity + Vector3 decayfraction = ((Vector3.One/(m_linearMotorDecayTimescale/pTimestep))); + m_linearMotorDirection -= m_linearMotorDirection * decayfraction * 0.5f; + + /* + Vector3 addAmount = (m_linearMotorDirection - m_lastLinearVelocityVector)/m_linearMotorTimescale; m_lastLinearVelocityVector += addAmount; - float decayFactor = (1.0f / m_linearMotorDecayTimescale) * pTimestep; - m_linearMotorDirection *= (1f - decayFactor); + float decayfraction = (1.0f - 1.0f / m_linearMotorDecayTimescale); + m_linearMotorDirection *= decayfraction; - Vector3 frictionFactor = (Vector3.One / m_linearFrictionTimescale) * pTimestep; - m_lastLinearVelocityVector *= (Vector3.One - frictionFactor); + */ - // Rotate new object velocity from vehicle relative to world coordinates - m_newVelocity = m_lastLinearVelocityVector * Prim.ForceOrientation; - - VDetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},vehVel={3},add={4},decay={5},frict={6},lmDir={7},lmVel={8},newVel={9}", - Prim.LocalID, origDir, origVel, vehicleVelocity, addAmount, decayFactor, frictionFactor, - m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity); + DetailLog("{0},MoveLinear,nonZero,origdir={1},origvel={2},add={3},decay={4},dir={5},vel={6}", + m_prim.LocalID, origDir, origVel, addAmount, decayfraction, m_linearMotorDirection, m_lastLinearVelocityVector); } else { - // if what remains of direction is very small, zero it. + // if what remains of applied is small, zero it. + // if (m_lastLinearVelocityVector.ApproxEquals(Vector3.Zero, 0.01f)) + // m_lastLinearVelocityVector = Vector3.Zero; m_linearMotorDirection = Vector3.Zero; m_lastLinearVelocityVector = Vector3.Zero; - m_newVelocity = Vector3.Zero; - - VDetailLog("{0},MoveLinear,zeroed", Prim.LocalID); } - // m_newVelocity is velocity computed from linear motor in world coordinates + // convert requested object velocity to world-referenced vector + Quaternion rotq = m_prim.Orientation; + m_dir = m_lastLinearVelocityVector * rotq; - // Gravity and Buoyancy + // Add the various forces into m_dir which will be our new direction vector (velocity) + + // add Gravity and Buoyancy + // KF: So far I have found no good method to combine a script-requested + // .Z velocity and gravity. Therefore only 0g will used script-requested + // .Z velocity. >0g (m_VehicleBuoyancy < 1) will used modified gravity only. + Vector3 grav = Vector3.Zero; // There is some gravity, make a gravity force vector that is applied after object velocity. // m_VehicleBuoyancy: -1=2g; 0=1g; 1=0g; - Vector3 grav = Prim.PhysicsScene.DefaultGravity * (1f - m_VehicleBuoyancy); - - /* - * RA: Not sure why one would do this unless we are hoping external forces are doing gravity, ... + grav.Z = m_prim.Scene.DefaultGravity.Z * m_prim.Mass * (1f - m_VehicleBuoyancy); // Preserve the current Z velocity Vector3 vel_now = m_prim.Velocity; m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity - */ - Vector3 pos = Prim.ForcePosition; + Vector3 pos = m_prim.Position; + Vector3 posChange = pos; // Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); - - // If below the terrain, move us above the ground a little. - float terrainHeight = Prim.PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(pos); - // Taking the rotated size doesn't work here because m_prim.Size is the size of the root prim and not the linkset. - // Need to add a m_prim.LinkSet.Size similar to m_prim.LinkSet.Mass. - // Vector3 rotatedSize = m_prim.Size * m_prim.ForceOrientation; - // if (rotatedSize.Z < terrainHeight) - if (pos.Z < terrainHeight) - { - pos.Z = terrainHeight + 2; - Prim.ForcePosition = pos; - VDetailLog("{0},MoveLinear,terrainHeight,terrainHeight={1},pos={2}", Prim.LocalID, terrainHeight, pos); - } - - // Check if hovering - // m_VhoverEfficiency: 0=bouncy, 1=totally damped - // m_VhoverTimescale: time to achieve height - if ((m_flags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) - { - // We should hover, get the target height - if ((m_flags & VehicleFlag.HOVER_WATER_ONLY) != 0) - { - m_VhoverTargetHeight = Prim.PhysicsScene.GetWaterLevelAtXYZ(pos) + m_VhoverHeight; - } - if ((m_flags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) - { - m_VhoverTargetHeight = terrainHeight + m_VhoverHeight; - } - if ((m_flags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) - { - m_VhoverTargetHeight = m_VhoverHeight; - } - - if ((m_flags & VehicleFlag.HOVER_UP_ONLY) != 0) - { - // If body is aready heigher, use its height as target height - if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; - } - if ((m_flags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) - { - if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) - { - Prim.ForcePosition = pos; - } - } - else - { - float verticalError = pos.Z - m_VhoverTargetHeight; - // RA: where does the 50 come from? - float verticalCorrectionVelocity = pTimestep * ((verticalError * 50.0f) / m_VhoverTimescale); - // Replace Vertical speed with correction figure if significant - if (Math.Abs(verticalError) > 0.01f) - { - m_newVelocity.Z += verticalCorrectionVelocity; - //KF: m_VhoverEfficiency is not yet implemented - } - else if (verticalError < -0.01) - { - m_newVelocity.Z -= verticalCorrectionVelocity; - } - else - { - m_newVelocity.Z = 0f; - } - } - - VDetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", Prim.LocalID, pos, m_newVelocity, m_VhoverHeight, m_VhoverTargetHeight); - } - - Vector3 posChange = pos - m_lastPositionVector; + double Zchange = Math.Abs(posChange.Z); if (m_BlockingEndPoint != Vector3.Zero) { bool changed = false; @@ -703,52 +721,134 @@ namespace OpenSim.Region.Physics.BulletSPlugin } if (changed) { - Prim.ForcePosition = pos; - VDetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", - Prim.LocalID, m_BlockingEndPoint, posChange, pos); + m_prim.Position = pos; + DetailLog("{0},MoveLinear,blockingEndPoint,block={1},origPos={2},pos={3}", + m_prim.LocalID, m_BlockingEndPoint, posChange, pos); } } - // Limit absolute vertical change - float Zchange = Math.Abs(posChange.Z); - if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) + // If below the terrain, move us above the ground a little. + if (pos.Z < m_prim.Scene.GetTerrainHeightAtXYZ(pos)) { - if (Zchange > .3) - grav.Z = (float)(grav.Z * 3); - if (Zchange > .15) - grav.Z = (float)(grav.Z * 2); - if (Zchange > .75) - grav.Z = (float)(grav.Z * 1.5); - if (Zchange > .05) - grav.Z = (float)(grav.Z * 1.25); - if (Zchange > .025) - grav.Z = (float)(grav.Z * 1.125); - float postemp = (pos.Z - terrainHeight); - if (postemp > 2.5f) - grav.Z = (float)(grav.Z * 1.037125); - VDetailLog("{0},MoveLinear,limitMotorUp,grav={1}", Prim.LocalID, grav); + pos.Z = m_prim.Scene.GetTerrainHeightAtXYZ(pos) + 2; + m_prim.Position = pos; + DetailLog("{0},MoveLinear,terrainHeight,pos={1}", m_prim.LocalID, pos); } - // If not changing some axis, reduce out velocity + // Check if hovering + if ((m_Hoverflags & (VehicleFlag.HOVER_WATER_ONLY | VehicleFlag.HOVER_TERRAIN_ONLY | VehicleFlag.HOVER_GLOBAL_HEIGHT)) != 0) + { + // We should hover, get the target height + if ((m_Hoverflags & VehicleFlag.HOVER_WATER_ONLY) != 0) + { + m_VhoverTargetHeight = m_prim.Scene.GetWaterLevel() + m_VhoverHeight; + } + if ((m_Hoverflags & VehicleFlag.HOVER_TERRAIN_ONLY) != 0) + { + m_VhoverTargetHeight = m_prim.Scene.GetTerrainHeightAtXY(pos.X, pos.Y) + m_VhoverHeight; + } + if ((m_Hoverflags & VehicleFlag.HOVER_GLOBAL_HEIGHT) != 0) + { + m_VhoverTargetHeight = m_VhoverHeight; + } + + if ((m_Hoverflags & VehicleFlag.HOVER_UP_ONLY) != 0) + { + // If body is aready heigher, use its height as target height + if (pos.Z > m_VhoverTargetHeight) m_VhoverTargetHeight = pos.Z; + } + if ((m_Hoverflags & VehicleFlag.LOCK_HOVER_HEIGHT) != 0) + { + if ((pos.Z - m_VhoverTargetHeight) > .2 || (pos.Z - m_VhoverTargetHeight) < -.2) + { + m_prim.Position = pos; + } + } + else + { + float herr0 = pos.Z - m_VhoverTargetHeight; + // Replace Vertical speed with correction figure if significant + if (Math.Abs(herr0) > 0.01f) + { + m_dir.Z = -((herr0 * pTimestep * 50.0f) / m_VhoverTimescale); + //KF: m_VhoverEfficiency is not yet implemented + } + else + { + m_dir.Z = 0f; + } + } + + DetailLog("{0},MoveLinear,hover,pos={1},dir={2},height={3},target={4}", m_prim.LocalID, pos, m_dir, m_VhoverHeight, m_VhoverTargetHeight); + +// m_VhoverEfficiency = 0f; // 0=boucy, 1=Crit.damped +// m_VhoverTimescale = 0f; // time to acheive height +// pTimestep is time since last frame,in secs + } + + if ((m_flags & (VehicleFlag.LIMIT_MOTOR_UP)) != 0) + { + //Start Experimental Values + if (Zchange > .3) + { + grav.Z = (float)(grav.Z * 3); + } + if (Zchange > .15) + { + grav.Z = (float)(grav.Z * 2); + } + if (Zchange > .75) + { + grav.Z = (float)(grav.Z * 1.5); + } + if (Zchange > .05) + { + grav.Z = (float)(grav.Z * 1.25); + } + if (Zchange > .025) + { + grav.Z = (float)(grav.Z * 1.125); + } + float terraintemp = m_prim.Scene.GetTerrainHeightAtXYZ(pos); + float postemp = (pos.Z - terraintemp); + if (postemp > 2.5f) + { + grav.Z = (float)(grav.Z * 1.037125); + } + DetailLog("{0},MoveLinear,limitMotorUp,grav={1}", m_prim.LocalID, grav); + //End Experimental Values + } if ((m_flags & (VehicleFlag.NO_X)) != 0) - m_newVelocity.X = 0; + { + m_dir.X = 0; + } if ((m_flags & (VehicleFlag.NO_Y)) != 0) - m_newVelocity.Y = 0; + { + m_dir.Y = 0; + } if ((m_flags & (VehicleFlag.NO_Z)) != 0) - m_newVelocity.Z = 0; + { + m_dir.Z = 0; + } + + m_lastPositionVector = m_prim.Position; // Apply velocity - Prim.ForceVelocity = m_newVelocity; - // Prim.AddForce(m_newVelocity * Prim.Linkset.LinksetMass, false); - Prim.AddForce(grav * Prim.Linkset.LinksetMass, false); + m_prim.Velocity = m_dir; + // apply gravity force + // Why is this set here? The physics engine already does gravity. + // m_prim.AddForce(grav, false); + // m_prim.Force = grav; - VDetailLog("{0},MoveLinear,done,lmDir={1},lmVel={2},newVel={3},grav={4}", - Prim.LocalID, m_linearMotorDirection, m_lastLinearVelocityVector, m_newVelocity, grav); + // Apply friction + Vector3 decayamount = Vector3.One / (m_linearFrictionTimescale / pTimestep); + m_lastLinearVelocityVector -= m_lastLinearVelocityVector * decayamount; + + DetailLog("{0},MoveLinear,done,pos={1},vel={2},force={3},decay={4}", + m_prim.LocalID, m_lastPositionVector, m_dir, grav, decayamount); } // end MoveLinear() - // ======================================================================= - // Apply the effect of the angular motor. private void MoveAngular(float pTimestep) { // m_angularMotorDirection // angular velocity requested by LSL motor @@ -759,223 +859,160 @@ namespace OpenSim.Region.Physics.BulletSPlugin // m_angularFrictionTimescale // body angular velocity decay rate // m_lastAngularVelocity // what was last applied to body - if (m_angularMotorDirection.LengthSquared() > 0.0001) + // Get what the body is doing, this includes 'external' influences + Vector3 angularVelocity = m_prim.RotationalVelocity; + + if (m_angularMotorApply > 0) { - Vector3 origVel = m_angularMotorVelocity; - Vector3 origDir = m_angularMotorDirection; + // Rather than snapping the angular motor velocity from the old value to + // a newly set velocity, this routine steps the value from the previous + // value (m_angularMotorVelocity) to the requested value (m_angularMotorDirection). + // There are m_angularMotorApply steps. + Vector3 origAngularVelocity = m_angularMotorVelocity; + // ramp up to new value + // current velocity += error / (time to get there / step interval) + // requested speed - last motor speed + m_angularMotorVelocity.X += (m_angularMotorDirection.X - m_angularMotorVelocity.X) / (m_angularMotorTimescale / pTimestep); + m_angularMotorVelocity.Y += (m_angularMotorDirection.Y - m_angularMotorVelocity.Y) / (m_angularMotorTimescale / pTimestep); + m_angularMotorVelocity.Z += (m_angularMotorDirection.Z - m_angularMotorVelocity.Z) / (m_angularMotorTimescale / pTimestep); - // new velocity += error / ( time to get there / step interval) - // requested speed - last motor speed - m_angularMotorVelocity += (m_angularMotorDirection - m_angularMotorVelocity) / (m_angularMotorTimescale / pTimestep); - // decay requested direction - m_angularMotorDirection *= (1.0f - (pTimestep * 1.0f/m_angularMotorDecayTimescale)); + DetailLog("{0},MoveAngular,angularMotorApply,apply={1},origvel={2},dir={3},vel={4}", + m_prim.LocalID,m_angularMotorApply,origAngularVelocity, m_angularMotorDirection, m_angularMotorVelocity); - VDetailLog("{0},MoveAngular,angularMotorApply,angTScale={1},timeStep={2},origvel={3},origDir={4},vel={5}", - Prim.LocalID, m_angularMotorTimescale, pTimestep, origVel, origDir, m_angularMotorVelocity); + m_angularMotorApply--; // This is done so that if script request rate is less than phys frame rate the expected + // velocity may still be acheived. } else { - m_angularMotorVelocity = Vector3.Zero; - } - - #region Vertical attactor + // No motor recently applied, keep the body velocity + // and decay the velocity + m_angularMotorVelocity -= m_angularMotorVelocity / (m_angularMotorDecayTimescale / pTimestep); + } // end motor section + // Vertical attractor section Vector3 vertattr = Vector3.Zero; - Vector3 deflection = Vector3.Zero; - Vector3 banking = Vector3.Zero; - - if (m_verticalAttractionTimescale < 300 && m_lastAngularVelocity != Vector3.Zero) + if (m_verticalAttractionTimescale < 300) { - float VAservo = pTimestep * 0.2f / m_verticalAttractionTimescale; - if (Prim.Linkset.LinksetIsColliding) - VAservo = pTimestep * 0.05f / (m_verticalAttractionTimescale); - - VAservo *= (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); - - // Create a vector of the vehicle "up" in world coordinates - Vector3 verticalError = Vector3.UnitZ * Prim.ForceOrientation; - // verticalError.X and .Y are the World error amounts. They are 0 when there is no - // error (Vehicle Body is 'vertical'), and .Z will be 1. As the body leans to its - // side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall - // and .Z will go // negative. Similar for tilt and |.Y|. .X and .Y must be - // modulated to prevent a stable inverted body. - - // Error is 0 (no error) to +/- 2 (max error) - if (verticalError.Z < 0.0f) + float VAservo = 0.2f / (m_verticalAttractionTimescale * pTimestep); + // get present body rotation + Quaternion rotq = m_prim.Orientation; + // make a vector pointing up + Vector3 verterr = Vector3.Zero; + verterr.Z = 1.0f; + // rotate it to Body Angle + verterr = verterr * rotq; + // verterr.X and .Y are the World error ammounts. They are 0 when there is no error (Vehicle Body is 'vertical'), and .Z will be 1. + // As the body leans to its side |.X| will increase to 1 and .Z fall to 0. As body inverts |.X| will fall and .Z will go + // negative. Similar for tilt and |.Y|. .X and .Y must be modulated to prevent a stable inverted body. + if (verterr.Z < 0.0f) { - verticalError.X = 2.0f - verticalError.X; - verticalError.Y = 2.0f - verticalError.Y; + verterr.X = 2.0f - verterr.X; + verterr.Y = 2.0f - verterr.Y; } + // Error is 0 (no error) to +/- 2 (max error) // scale it by VAservo - verticalError = verticalError * VAservo; + verterr = verterr * VAservo; - // As the body rotates around the X axis, then verticalError.Y increases; Rotated around Y - // then .X increases, so change Body angular velocity X based on Y, and Y based on X. - // Z is not changed. - vertattr.X = verticalError.Y; - vertattr.Y = - verticalError.X; + // As the body rotates around the X axis, then verterr.Y increases; Rotated around Y then .X increases, so + // Change Body angular velocity X based on Y, and Y based on X. Z is not changed. + vertattr.X = verterr.Y; + vertattr.Y = - verterr.X; vertattr.Z = 0f; // scaling appears better usingsquare-law - Vector3 angularVelocity = Prim.ForceRotationalVelocity; float bounce = 1.0f - (m_verticalAttractionEfficiency * m_verticalAttractionEfficiency); vertattr.X += bounce * angularVelocity.X; vertattr.Y += bounce * angularVelocity.Y; - VDetailLog("{0},MoveAngular,verticalAttraction,verticalError={1},bounce={2},vertattr={3}", - Prim.LocalID, verticalError, bounce, vertattr); + DetailLog("{0},MoveAngular,verticalAttraction,verterr={1},bounce={2},vertattr={3}", + m_prim.LocalID, verterr, bounce, vertattr); - } - #endregion // Vertical attactor + } // else vertical attractor is off - #region Deflection + // m_lastVertAttractor = vertattr; - //Forward is the prefered direction, but if the reference frame has changed, we need to take this into account as well - if (m_angularDeflectionEfficiency != 0) - { - Vector3 preferredAxisOfMotion = - new Vector3((pTimestep * 10 * (m_angularDeflectionEfficiency / m_angularDeflectionTimescale)), 0, 0); - preferredAxisOfMotion *= Quaternion.Add(Prim.ForceOrientation, m_referenceFrame); + // Bank section tba - deflection = (preferredAxisOfMotion * (m_angularDeflectionEfficiency) / m_angularDeflectionTimescale) * pTimestep; - - VDetailLog("{0},MoveAngular,Deflection,perfAxis={1},deflection={2}", - Prim.LocalID, preferredAxisOfMotion, deflection); - } - - #endregion - - #region Banking - - if (m_bankingEfficiency != 0) - { - Vector3 dir = Vector3.One * Prim.ForceOrientation; - float mult = (m_bankingMix*m_bankingMix)*-1*(m_bankingMix < 0 ? -1 : 1); - //Changes which way it banks in and out of turns - - //Use the square of the efficiency, as it looks much more how SL banking works - float effSquared = (m_bankingEfficiency*m_bankingEfficiency); - if (m_bankingEfficiency < 0) - effSquared *= -1; //Keep the negative! - - float mix = Math.Abs(m_bankingMix); - if (m_angularMotorVelocity.X == 0) - { - /*if (!parent.Orientation.ApproxEquals(this.m_referenceFrame, 0.25f)) - { - Vector3 axisAngle; - float angle; - parent.Orientation.GetAxisAngle(out axisAngle, out angle); - Vector3 rotatedVel = parent.Velocity * parent.Orientation; - if ((rotatedVel.X < 0 && axisAngle.Y > 0) || (rotatedVel.X > 0 && axisAngle.Y < 0)) - m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (1f) * 10; - else - m_angularMotorVelocity.X += (effSquared * (mult * mix)) * (-1f) * 10; - }*/ - } - else - banking.Z += (effSquared*(mult*mix))*(m_angularMotorVelocity.X) * 4; - if (!Prim.Linkset.LinksetIsColliding && Math.Abs(m_angularMotorVelocity.X) > mix) - //If they are colliding, we probably shouldn't shove the prim around... probably - { - float angVelZ = m_angularMotorVelocity.X*-1; - /*if(angVelZ > mix) - angVelZ = mix; - else if(angVelZ < -mix) - angVelZ = -mix;*/ - //This controls how fast and how far the banking occurs - Vector3 bankingRot = new Vector3(angVelZ*(effSquared*mult), 0, 0); - if (bankingRot.X > 3) - bankingRot.X = 3; - else if (bankingRot.X < -3) - bankingRot.X = -3; - bankingRot *= Prim.ForceOrientation; - banking += bankingRot; - } - m_angularMotorVelocity.X *= m_bankingEfficiency == 1 ? 0.0f : 1 - m_bankingEfficiency; - VDetailLog("{0},MoveAngular,Banking,bEff={1},angMotVel={2},banking={3}", - Prim.LocalID, m_bankingEfficiency, m_angularMotorVelocity, banking); - } - - #endregion - - m_lastVertAttractor = vertattr; + // Deflection section tba // Sum velocities - m_lastAngularVelocity = m_angularMotorVelocity + vertattr + banking + deflection; - + m_lastAngularVelocity = m_angularMotorVelocity + vertattr; // + bank + deflection + if ((m_flags & (VehicleFlag.NO_DEFLECTION_UP)) != 0) { m_lastAngularVelocity.X = 0; m_lastAngularVelocity.Y = 0; - VDetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); + DetailLog("{0},MoveAngular,noDeflectionUp,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } if (m_lastAngularVelocity.ApproxEquals(Vector3.Zero, 0.01f)) { m_lastAngularVelocity = Vector3.Zero; // Reduce small value to zero. - VDetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", Prim.LocalID, m_lastAngularVelocity); + DetailLog("{0},MoveAngular,zeroSmallValues,lastAngular={1}", m_prim.LocalID, m_lastAngularVelocity); } + // apply friction + Vector3 decayamount = Vector3.One / (m_angularFrictionTimescale / pTimestep); + m_lastAngularVelocity -= m_lastAngularVelocity * decayamount; + // Apply to the body - // The above calculates the absolute angular velocity needed - // Prim.ForceRotationalVelocity = m_lastAngularVelocity; + m_prim.RotationalVelocity = m_lastAngularVelocity; - // Apply a force to overcome current angular velocity - Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity) * Prim.Linkset.LinksetMass; - // Vector3 applyAngularForce = (m_lastAngularVelocity - Prim.ForceRotationalVelocity); - // Prim.AddAngularForce(applyAngularForce, false); - Prim.ApplyTorqueImpulse(applyAngularForce, false); - - // Apply friction for next time - Vector3 decayamount = (Vector3.One / m_angularFrictionTimescale) * pTimestep; - m_lastAngularVelocity *= Vector3.One - decayamount; - - VDetailLog("{0},MoveAngular,done,applyAForce={1},decay={2},lastAngular={3}", - Prim.LocalID, applyAngularForce, decayamount, m_lastAngularVelocity); + DetailLog("{0},MoveAngular,done,decay={1},lastAngular={2}", m_prim.LocalID, decayamount, m_lastAngularVelocity); } //end MoveAngular internal void LimitRotation(float timestep) { - Quaternion rotq = Prim.ForceOrientation; + Quaternion rotq = m_prim.Orientation; Quaternion m_rot = rotq; + bool changed = false; if (m_RollreferenceFrame != Quaternion.Identity) { if (rotq.X >= m_RollreferenceFrame.X) { m_rot.X = rotq.X - (m_RollreferenceFrame.X / 2); + changed = true; } if (rotq.Y >= m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y - (m_RollreferenceFrame.Y / 2); + changed = true; } if (rotq.X <= -m_RollreferenceFrame.X) { m_rot.X = rotq.X + (m_RollreferenceFrame.X / 2); + changed = true; } if (rotq.Y <= -m_RollreferenceFrame.Y) { m_rot.Y = rotq.Y + (m_RollreferenceFrame.Y / 2); + changed = true; } + changed = true; } if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) { m_rot.X = 0; m_rot.Y = 0; + changed = true; } - if (rotq != m_rot) + if ((m_flags & VehicleFlag.LOCK_ROTATION) != 0) { - Prim.ForceOrientation = m_rot; - VDetailLog("{0},LimitRotation,done,orig={1},new={2}", Prim.LocalID, rotq, m_rot); + m_rot.X = 0; + m_rot.Y = 0; + changed = true; } + if (changed) + m_prim.Orientation = m_rot; + DetailLog("{0},LimitRotation,done,changed={1},orig={2},new={3}", m_prim.LocalID, changed, rotq, m_rot); } // Invoke the detailed logger and output something if it's enabled. - private void VDetailLog(string msg, params Object[] args) + private void DetailLog(string msg, params Object[] args) { - if (Prim.PhysicsScene.VehicleLoggingEnabled) - Prim.PhysicsScene.DetailLog(msg, args); + if (m_prim.Scene.VehicleLoggingEnabled) + m_prim.Scene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs similarity index 90% rename from OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs rename to OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs index ed3ffa7f3b..d68048bd0a 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSConstraintHinge.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSHingeConstraint.cs @@ -1,57 +1,55 @@ -/* - * 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 copyrightD - * 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.Text; -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ - -public sealed class BSConstraintHinge : BSConstraint -{ - public override ConstraintType Type { get { return ConstraintType.HINGE_CONSTRAINT_TYPE; } } - - public BSConstraintHinge(BulletSim world, BulletBody obj1, BulletBody obj2, - Vector3 pivotInA, Vector3 pivotInB, - Vector3 axisInA, Vector3 axisInB, - bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) - { - m_world = world; - m_body1 = obj1; - m_body2 = obj2; - m_constraint = new BulletConstraint( - BulletSimAPI.CreateHingeConstraint2(m_world.ptr, m_body1.ptr, m_body2.ptr, - pivotInA, pivotInB, - axisInA, axisInB, - useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); - m_enabled = true; - } - -} - -} +/* + * 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 copyrightD + * 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.Text; +using OpenMetaverse; + +namespace OpenSim.Region.Physics.BulletSPlugin +{ + +class BSHingeConstraint : BSConstraint +{ + public BSHingeConstraint(BulletSim world, BulletBody obj1, BulletBody obj2, + Vector3 pivotInA, Vector3 pivotInB, + Vector3 axisInA, Vector3 axisInB, + bool useLinearReferenceFrameA, bool disableCollisionsBetweenLinkedBodies) + { + m_world = world; + m_body1 = obj1; + m_body2 = obj2; + m_constraint = new BulletConstraint( + BulletSimAPI.CreateHingeConstraint2(m_world.Ptr, m_body1.Ptr, m_body2.Ptr, + pivotInA, pivotInB, + axisInA, axisInB, + useLinearReferenceFrameA, disableCollisionsBetweenLinkedBodies)); + m_enabled = true; + } + +} + +} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs index 3a92f9361a..087b9bbce2 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinkset.cs @@ -32,78 +32,35 @@ using OMV = OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { -public abstract class BSLinkset +public class BSLinkset { - // private static string LogHeader = "[BULLETSIM LINKSET]"; + private static string LogHeader = "[BULLETSIM LINKSET]"; - public enum LinksetImplementation - { - Constraint = 0, // linkset tied together with constraints - Compound = 1, // linkset tied together as a compound object - Manual = 2 // linkset tied together manually (code moves all the pieces) - } - // Create the correct type of linkset for this child - public static BSLinkset Factory(BSScene physScene, BSPhysObject parent) - { - BSLinkset ret = null; + private BSPrim m_linksetRoot; + public BSPrim LinksetRoot { get { return m_linksetRoot; } } - switch ((int)physScene.Params.linksetImplementation) - { - case (int)LinksetImplementation.Compound: - ret = new BSLinksetCompound(physScene, parent); - break; - case (int)LinksetImplementation.Manual: - // ret = new BSLinksetManual(physScene, parent); - break; - default: - ret = new BSLinksetConstraints(physScene, parent); - break; - } - return ret; - } + private BSScene m_physicsScene; + public BSScene PhysicsScene { get { return m_physicsScene; } } - public BSPhysObject LinksetRoot { get; protected set; } - - public BSScene PhysicsScene { get; private set; } - - static int m_nextLinksetID = 1; - public int LinksetID { get; private set; } - - // The children under the root in this linkset. - protected HashSet m_children; + // The children under the root in this linkset + private List m_children; // We lock the diddling of linkset classes to prevent any badness. // This locks the modification of the instances of this class. Changes // to the physical representation is done via the tainting mechenism. - protected object m_linksetActivityLock = new Object(); + private object m_linksetActivityLock = new Object(); - // Some linksets have a preferred physical shape. - // Returns SHAPE_UNKNOWN if there is no preference. Causes the correct shape to be selected. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - } - - // Linksets move around the children so the linkset might need to compute the child position - public virtual OMV.Vector3 Position(BSPhysObject member) - { return member.RawPosition; } - public virtual OMV.Quaternion Orientation(BSPhysObject member) - { return member.RawOrientation; } - // TODO: does this need to be done for Velocity and RotationalVelocityy? - // We keep the prim's mass in the linkset structure since it could be dependent on other prims - protected float m_mass; - public float LinksetMass - { - get + private float m_mass; + public float LinksetMass + { + get { m_mass = ComputeLinksetMass(); return m_mass; } } - public virtual bool LinksetIsColliding { get { return false; } } - public OMV.Vector3 CenterOfMass { get { return ComputeLinksetCenterOfMass(); } @@ -114,30 +71,23 @@ public abstract class BSLinkset get { return ComputeLinksetGeometricCenter(); } } - protected void Initialize(BSScene scene, BSPhysObject parent) + public BSLinkset(BSScene scene, BSPrim parent) { // A simple linkset of one (no children) - LinksetID = m_nextLinksetID++; - // We create LOTS of linksets. - if (m_nextLinksetID <= 0) - m_nextLinksetID = 1; - PhysicsScene = scene; - LinksetRoot = parent; - m_children = new HashSet(); - m_mass = parent.RawMass; + m_physicsScene = scene; + m_linksetRoot = parent; + m_children = new List(); + m_mass = parent.MassRaw; } // Link to a linkset where the child knows the parent. // Parent changing should not happen so do some sanity checking. // We return the parent's linkset so the child can track its membership. - // Called at runtime. - public BSLinkset AddMeToLinkset(BSPhysObject child) + public BSLinkset AddMeToLinkset(BSPrim child) { lock (m_linksetActivityLock) { - // Don't add the root to its own linkset - if (!IsRoot(child)) - AddChildToLinkset(child); + AddChildToLinkset(child); } return this; } @@ -145,27 +95,36 @@ public abstract class BSLinkset // Remove a child from a linkset. // Returns a new linkset for the child which is a linkset of one (just the // orphened child). - // Called at runtime. - public BSLinkset RemoveMeFromLinkset(BSPhysObject child) + public BSLinkset RemoveMeFromLinkset(BSPrim child) { lock (m_linksetActivityLock) { if (IsRoot(child)) { - // Cannot remove the root from a linkset. - return this; + // if root of linkset, take the linkset apart + while (m_children.Count > 0) + { + // Note that we don't do a foreach because the remove routine + // takes it out of the list. + RemoveChildFromOtherLinkset(m_children[0]); + } + m_children.Clear(); // just to make sure + } + else + { + // Just removing a child from an existing linkset + RemoveChildFromLinkset(child); } - RemoveChildFromLinkset(child); } // The child is down to a linkset of just itself - return BSLinkset.Factory(PhysicsScene, child); + return new BSLinkset(PhysicsScene, child); } // Return 'true' if the passed object is the root object of this linkset - public bool IsRoot(BSPhysObject requestor) + public bool IsRoot(BSPrim requestor) { - return (requestor.LocalID == LinksetRoot.LocalID); + return (requestor.LocalID == m_linksetRoot.LocalID); } public int NumberOfChildren { get { return m_children.Count; } } @@ -174,14 +133,12 @@ public abstract class BSLinkset public bool HasAnyChildren { get { return (m_children.Count > 0); } } // Return 'true' if this child is in this linkset - public bool HasChild(BSPhysObject child) + public bool HasChild(BSPrim child) { bool ret = false; lock (m_linksetActivityLock) { - ret = m_children.Contains(child); - /* Safer version but the above should work - foreach (BSPhysObject bp in m_children) + foreach (BSPrim bp in m_children) { if (child.LocalID == bp.LocalID) { @@ -189,102 +146,31 @@ public abstract class BSLinkset break; } } - */ } return ret; } - // Perform an action on each member of the linkset including root prim. - // Depends on the action on whether this should be done at taint time. - public delegate bool ForEachMemberAction(BSPhysObject obj); - public virtual bool ForEachMember(ForEachMemberAction action) + private float ComputeLinksetMass() { - bool ret = false; - lock (m_linksetActivityLock) + float mass = m_linksetRoot.MassRaw; + foreach (BSPrim bp in m_children) { - action(LinksetRoot); - foreach (BSPhysObject po in m_children) - { - if (action(po)) - break; - } - } - return ret; - } - - // I am the root of a linkset and a new child is being added - // Called while LinkActivity is locked. - protected abstract void AddChildToLinkset(BSPhysObject child); - - // I am the root of a linkset and one of my children is being removed. - // Safe to call even if the child is not really in my linkset. - protected abstract void RemoveChildFromLinkset(BSPhysObject child); - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // May be called at runtime or taint-time. - public abstract void Refresh(BSPhysObject requestor); - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeDynamic(BSPhysObject child); - - // The object is going static (non-physical). Do any setup necessary - // for a static linkset. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public abstract bool MakeStatic(BSPhysObject child); - - // Called when a parameter update comes from the physics engine for any object - // of the linkset is received. - // Called at taint-time!! - public abstract void UpdateProperties(BSPhysObject physObject); - - // Routine used when rebuilding the body of the root of the linkset - // Destroy all the constraints have have been made to root. - // This is called when the root body is changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public abstract bool RemoveBodyDependencies(BSPrim child); - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public abstract void RestoreBodyDependencies(BSPrim child); - - // ================================================================ - protected virtual float ComputeLinksetMass() - { - float mass = LinksetRoot.RawMass; - if (HasAnyChildren) - { - lock (m_linksetActivityLock) - { - foreach (BSPhysObject bp in m_children) - { - mass += bp.RawMass; - } - } + mass += bp.MassRaw; } return mass; } - protected virtual OMV.Vector3 ComputeLinksetCenterOfMass() + private OMV.Vector3 ComputeLinksetCenterOfMass() { - OMV.Vector3 com; + OMV.Vector3 com = m_linksetRoot.Position * m_linksetRoot.MassRaw; + float totalMass = m_linksetRoot.MassRaw; + lock (m_linksetActivityLock) { - com = LinksetRoot.Position * LinksetRoot.RawMass; - float totalMass = LinksetRoot.RawMass; - - foreach (BSPhysObject bp in m_children) + foreach (BSPrim bp in m_children) { - com += bp.Position * bp.RawMass; - totalMass += bp.RawMass; + com += bp.Position * bp.MassRaw; + totalMass += bp.MassRaw; } if (totalMass != 0f) com /= totalMass; @@ -293,16 +179,15 @@ public abstract class BSLinkset return com; } - protected virtual OMV.Vector3 ComputeLinksetGeometricCenter() + private OMV.Vector3 ComputeLinksetGeometricCenter() { - OMV.Vector3 com; + OMV.Vector3 com = m_linksetRoot.Position; + lock (m_linksetActivityLock) { - com = LinksetRoot.Position; - - foreach (BSPhysObject bp in m_children) + foreach (BSPrim bp in m_children) { - com += bp.Position * bp.RawMass; + com += bp.Position * bp.MassRaw; } com /= (m_children.Count + 1); } @@ -310,11 +195,225 @@ public abstract class BSLinkset return com; } - // Invoke the detailed logger and output something if it's enabled. - protected void DetailLog(string msg, params Object[] args) + // When physical properties are changed the linkset needs to recalculate + // its internal properties. + public void Refresh(BSPrim requestor) { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); + // If there are no children, there aren't any constraints to recompute + if (!HasAnyChildren) + return; + + // Only the root does the recomputation + if (IsRoot(requestor)) + { + PhysicsScene.TaintedObject("BSLinkSet.Refresh", delegate() + { + RecomputeLinksetConstraintVariables(); + }); + } + } + + // Call each of the constraints that make up this linkset and recompute the + // various transforms and variables. Used when objects are added or removed + // from a linkset to make sure the constraints know about the new mass and + // geometry. + // Must only be called at taint time!! + private bool RecomputeLinksetConstraintVariables() + { + float linksetMass = LinksetMass; + lock (m_linksetActivityLock) + { + foreach (BSPrim child in m_children) + { + BSConstraint constrain; + if (m_physicsScene.Constraints.TryGetConstraint(LinksetRoot.Body, child.Body, out constrain)) + { + // DetailLog("{0},BSLinkset.RecomputeLinksetConstraintVariables,taint,child={1},mass={2},A={3},B={4}", + // LinksetRoot.LocalID, child.LocalID, linksetMass, constrain.Body1.ID, constrain.Body2.ID); + constrain.RecomputeConstraintVariables(linksetMass); + } + else + { + // Non-fatal error that can happen when children are being added to the linkset but + // their constraints have not been created yet. + // Caused by the fact that m_children is built at run time but building constraints + // happens at taint time. + // m_physicsScene.Logger.ErrorFormat("[BULLETSIM LINKSET] RecomputeLinksetConstraintVariables: constraint not found for root={0}, child={1}", + // m_linksetRoot.Body.ID, child.Body.ID); + } + } + } + return false; + } + + // I am the root of a linkset and a new child is being added + // Called while LinkActivity is locked. + private void AddChildToLinkset(BSPrim child) + { + if (!HasChild(child)) + { + m_children.Add(child); + + BSPrim rootx = LinksetRoot; // capture the root as of now + BSPrim childx = child; + m_physicsScene.TaintedObject("AddChildToLinkset", delegate() + { + // DebugLog("{0}: AddChildToLinkset: adding child {1} to {2}", LogHeader, child.LocalID, m_linksetRoot.LocalID); + // DetailLog("{0},AddChildToLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + PhysicallyLinkAChildToRoot(rootx, childx); // build the physical binding between me and the child + }); + } + return; + } + + // Forcefully removing a child from a linkset. + // This is not being called by the child so we have to make sure the child doesn't think + // it's still connected to the linkset. + // Normal OpenSimulator operation will never do this because other SceneObjectPart information + // has to be updated also (like pointer to prim's parent). + private void RemoveChildFromOtherLinkset(BSPrim pchild) + { + pchild.Linkset = new BSLinkset(m_physicsScene, pchild); + RemoveChildFromLinkset(pchild); + } + + // I am the root of a linkset and one of my children is being removed. + // Safe to call even if the child is not really in my linkset. + private void RemoveChildFromLinkset(BSPrim child) + { + if (m_children.Remove(child)) + { + BSPrim rootx = LinksetRoot; // capture the root as of now + BSPrim childx = child; + m_physicsScene.TaintedObject("RemoveChildFromLinkset", delegate() + { + // DebugLog("{0}: RemoveChildFromLinkset: Removing constraint to {1}", LogHeader, child.LocalID); + // DetailLog("{0},RemoveChildFromLinkset,taint,child={1}", m_linksetRoot.LocalID, child.LocalID); + + PhysicallyUnlinkAChildFromRoot(rootx, childx); + }); + + RecomputeLinksetConstraintVariables(); + } + else + { + // This will happen if we remove the root of the linkset first. Non-fatal occurance. + // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); + } + return; + } + + // Create a constraint between me (root of linkset) and the passed prim (the child). + // Called at taint time! + private void PhysicallyLinkAChildToRoot(BSPrim rootPrim, BSPrim childPrim) + { + // Zero motion for children so they don't interpolate + childPrim.ZeroMotion(); + + // Relative position normalized to the root prim + // Essentually a vector pointing from center of rootPrim to center of childPrim + OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; + + // real world coordinate of midpoint between the two objects + OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2},rLoc={3},cLoc={4},midLoc={5}", + rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID, rootPrim.Position, childPrim.Position, midPoint); + BS6DofConstraint constrain = new BS6DofConstraint( + m_physicsScene.World, rootPrim.Body, childPrim.Body, + midPoint, + true, + true + ); + /* NOTE: attempt to build constraint with full frame computation, etc. + * Using the midpoint is easier since it lets the Bullet code use the transforms + * of the objects. + * Code left here as an example. + // ================================================================================== + // relative position normalized to the root prim + OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); + OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; + + // relative rotation of the child to the parent + OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; + OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); + + // create a constraint that allows no freedom of movement between the two objects + // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 + // DebugLog("{0}: CreateLinkset: Adding a constraint between root prim {1} and child prim {2}", LogHeader, LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + BS6DofConstraint constrain = new BS6DofConstraint( + PhysicsScene.World, rootPrim.Body, childPrim.Body, + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(rootPrim.Orientation), + OMV.Vector3.Zero, + OMV.Quaternion.Inverse(childPrim.Orientation), + // A point half way between the parent and child + // childRelativePosition/2, + // childRelativeRotation, + // childRelativePosition/2, + // inverseChildRelativeRotation, + true, + true + ); + // ================================================================================== + */ + + m_physicsScene.Constraints.AddConstraint(constrain); + + // zero linear and angular limits makes the objects unable to move in relation to each other + constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); + + // tweek the constraint to increase stability + constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); + constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), + PhysicsScene.Params.linkConstraintTransMotorMaxVel, + PhysicsScene.Params.linkConstraintTransMotorMaxForce); + constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); + + RecomputeLinksetConstraintVariables(); + } + + // Remove linkage between myself and a particular child + // Called at taint time! + private void PhysicallyUnlinkAChildFromRoot(BSPrim rootPrim, BSPrim childPrim) + { + // DebugLog("{0}: PhysicallyUnlinkAChildFromRoot: RemoveConstraint between root prim {1} and child prim {2}", + // LogHeader, rootPrim.LocalID, childPrim.LocalID); + DetailLog("{0},PhysicallyUnlinkAChildFromRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); + + // Find the constraint for this link and get rid of it from the overall collection and from my list + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body, childPrim.Body); + + // Make the child refresh its location + BulletSimAPI.PushUpdate2(childPrim.Body.Ptr); + } + + // Remove linkage between myself and any possible children I might have + // Called at taint time! + private void PhysicallyUnlinkAllChildrenFromRoot(BSPrim rootPrim) + { + // DebugLog("{0}: PhysicallyUnlinkAllChildren:", LogHeader); + DetailLog("{0},PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); + + m_physicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.Body); + } + + // Invoke the detailed logger and output something if it's enabled. + private void DebugLog(string msg, params Object[] args) + { + if (m_physicsScene.ShouldDebugLog) + m_physicsScene.Logger.DebugFormat(msg, args); + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + m_physicsScene.PhysicsLogging.Write(msg, args); } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs deleted file mode 100755 index 12c6d7a678..0000000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ /dev/null @@ -1,273 +0,0 @@ -/* - * 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 copyrightD - * 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.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSLinksetCompound : BSLinkset -{ - private static string LogHeader = "[BULLETSIM LINKSET COMPOUND]"; - - public BSLinksetCompound(BSScene scene, BSPhysObject parent) - { - base.Initialize(scene, parent); - } - - // For compound implimented linksets, if there are children, use compound shape for the root. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape(BSPhysObject requestor) - { - ShapeData.PhysicsShapeType ret = ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - if (IsRoot(requestor) && HasAnyChildren) - { - ret = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; - } - // DetailLog("{0},BSLinksetCompound.PreferredPhysicalShape,call,shape={1}", LinksetRoot.LocalID, ret); - return ret; - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. - public override void Refresh(BSPhysObject requestor) - { - // External request for Refresh (from BSPrim) is not necessary - // InternalRefresh(requestor); - } - - private void InternalRefresh(BSPhysObject requestor) - { - DetailLog("{0},BSLinksetCompound.Refresh,schedulingRefresh,requestor={1}", LinksetRoot.LocalID, requestor.LocalID); - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetCompound.Refresh", requestor.LocalID, delegate() - { - if (IsRoot(requestor) && HasAnyChildren) - RecomputeLinksetCompound(); - }); - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeDynamic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (!IsRoot(child)) - { - // Physical children are removed from the world as the shape ofthe root compound - // shape takes over. - BulletSimAPI.AddToCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - BulletSimAPI.ForceActivationState2(child.PhysBody.ptr, ActivationState.DISABLE_SIMULATION); - ret = true; - } - return ret; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - bool ret = false; - DetailLog("{0},BSLinksetCompound.MakeStatic,call,IsRoot={1}", child.LocalID, IsRoot(child)); - if (!IsRoot(child)) - { - // The non-physical children can come back to life. - BulletSimAPI.RemoveFromCollisionFlags2(child.PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - // Don't force activation so setting of DISABLE_SIMULATION can stay. - BulletSimAPI.Activate2(child.PhysBody.ptr, false); - ret = true; - } - return ret; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) - { - // Nothing to do for constraints on property updates - } - - // The children move around in relationship to the root. - // Just grab the current values of wherever it is right now. - public override OMV.Vector3 Position(BSPhysObject member) - { - return BulletSimAPI.GetPosition2(member.PhysBody.ptr); - } - - public override OMV.Quaternion Orientation(BSPhysObject member) - { - return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); - } - - // Routine called when rebuilding the body of some member of the linkset. - // Since we don't keep in world relationships, do nothing unless it's a child changing. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetCompound.RemoveBodyDependencies,refreshIfChild,rID={1},rBody={2},isRoot={3}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), IsRoot(child)); - - if (!IsRoot(child)) - { - // Cause the current shape to be freed and the new one to be built. - InternalRefresh(LinksetRoot); - ret = true; - } - - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetCompound.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - InternalRefresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - DetailLog("{0},BSLinksetCompound.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - child.LocalID, - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), - child.LocalID, child.PhysBody.ptr.ToString("X")); - - // Cause the child's body to be rebuilt and thus restored to normal operation - child.ForceBodyShapeRebuild(false); - - if (!HasAnyChildren) - { - // The linkset is now empty. The root needs rebuilding. - LinksetRoot.ForceBodyShapeRebuild(false); - } - else - { - // Schedule a rebuild of the linkset before the next simulation tick. - InternalRefresh(LinksetRoot); - } - } - return; - } - - // Called before the simulation step to make sure the compound based linkset - // is all initialized. - // Constraint linksets are rebuilt every time. - // Note that this works for rebuilding just the root after a linkset is taken apart. - // Called at taint time!! - private void RecomputeLinksetCompound() - { - // Cause the root shape to be rebuilt as a compound object with just the root in it - LinksetRoot.ForceBodyShapeRebuild(true); - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,start,rBody={1},rShape={2},numChildren={3}", - LinksetRoot.LocalID, LinksetRoot.PhysBody, LinksetRoot.PhysShape, NumberOfChildren); - - // Add a shape for each of the other children in the linkset - ForEachMember(delegate(BSPhysObject cPrim) - { - if (!IsRoot(cPrim)) - { - // Each child position and rotation is given relative to the root. - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); - OMV.Vector3 displacementPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation; - OMV.Quaternion displacementRot = cPrim.RawOrientation * invRootOrientation; - - DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addMemberToShape,mID={1},mShape={2},dispPos={3},dispRot={4}", - LinksetRoot.LocalID, cPrim.LocalID, cPrim.PhysShape, displacementPos, displacementRot); - - if (cPrim.PhysShape.isNativeShape) - { - // Native shapes are not shared so we need to create a new one. - // A mesh or hull is created because scale is not available on a native shape. - // (TODO: Bullet does have a btScaledCollisionShape. Can that be used?) - BulletShape saveShape = cPrim.PhysShape; - cPrim.PhysShape.ptr = IntPtr.Zero; // Don't let the create free the child's shape - PhysicsScene.Shapes.CreateGeomMeshOrHull(cPrim, null); - BulletShape newShape = cPrim.PhysShape; - cPrim.PhysShape = saveShape; - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, newShape.ptr, displacementPos, displacementRot); - } - else - { - // For the shared shapes (meshes and hulls), just use the shape in the child. - if (PhysicsScene.Shapes.ReferenceShape(cPrim.PhysShape)) - { - PhysicsScene.Logger.ErrorFormat("{0} Rebuilt sharable shape when building linkset! Region={1}, primID={2}, shape={3}", - LogHeader, PhysicsScene.RegionName, cPrim.LocalID, cPrim.PhysShape); - } - BulletSimAPI.AddChildShapeToCompoundShape2(LinksetRoot.PhysShape.ptr, cPrim.PhysShape.ptr, displacementPos, displacementRot); - } - } - return false; // 'false' says to move onto the next child in the list - }); - - // With all of the linkset packed into the root prim, it has the mass of everyone. - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems for constraint linksets. - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - - } -} -} \ No newline at end of file diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs deleted file mode 100755 index d2387fbe4f..0000000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetConstraints.cs +++ /dev/null @@ -1,327 +0,0 @@ -/* - * 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 copyrightD - * 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.Text; - -using OMV = OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSLinksetConstraints : BSLinkset -{ - // private static string LogHeader = "[BULLETSIM LINKSET CONSTRAINTS]"; - - public BSLinksetConstraints(BSScene scene, BSPhysObject parent) - { - base.Initialize(scene, parent); - } - - // When physical properties are changed the linkset needs to recalculate - // its internal properties. - // This is queued in the 'post taint' queue so the - // refresh will happen once after all the other taints are applied. - public override void Refresh(BSPhysObject requestor) - { - // Queue to happen after all the other taint processing - PhysicsScene.PostTaintObject("BSLinksetContraints.Refresh", requestor.LocalID, delegate() - { - if (HasAnyChildren && IsRoot(requestor)) - RecomputeLinksetConstraints(); - }); - } - - // The object is going dynamic (physical). Do any setup necessary - // for a dynamic linkset. - // Only the state of the passed object can be modified. The rest of the linkset - // has not yet been fully constructed. - // Return 'true' if any properties updated on the passed object. - // Called at taint-time! - public override bool MakeDynamic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // The object is going static (non-physical). Do any setup necessary for a static linkset. - // Return 'true' if any properties updated on the passed object. - // This doesn't normally happen -- OpenSim removes the objects from the physical - // world if it is a static linkset. - // Called at taint-time! - public override bool MakeStatic(BSPhysObject child) - { - // What is done for each object in BSPrim is what we want. - return false; - } - - // Called at taint-time!! - public override void UpdateProperties(BSPhysObject updated) - { - // Nothing to do for constraints on property updates - } - - // The children of the linkset are moved around by the constraints. - // Just grab the current values of wherever it is right now. - public override OMV.Vector3 Position(BSPhysObject member) - { - return BulletSimAPI.GetPosition2(member.PhysBody.ptr); - } - - public override OMV.Quaternion Orientation(BSPhysObject member) - { - return BulletSimAPI.GetOrientation2(member.PhysBody.ptr); - } - - // Routine called when rebuilding the body of some member of the linkset. - // Destroy all the constraints have have been made to root and set - // up to rebuild the constraints before the next simulation step. - // Returns 'true' of something was actually removed and would need restoring - // Called at taint-time!! - public override bool RemoveBodyDependencies(BSPrim child) - { - bool ret = false; - - DetailLog("{0},BSLinksetConstraint.RemoveBodyDependencies,removeChildrenForRoot,rID={1},rBody={2}", - child.LocalID, LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X")); - - lock (m_linksetActivityLock) - { - // Just undo all the constraints for this linkset. Rebuild at the end of the step. - ret = PhysicallyUnlinkAllChildrenFromRoot(LinksetRoot); - // Cause the constraints, et al to be rebuilt before the next simulation step. - Refresh(LinksetRoot); - } - return ret; - } - - // Companion to RemoveBodyDependencies(). If RemoveBodyDependencies() returns 'true', - // this routine will restore the removed constraints. - // Called at taint-time!! - public override void RestoreBodyDependencies(BSPrim child) - { - // The Refresh operation queued by RemoveBodyDependencies() will build any missing constraints. - } - - // ================================================================ - - // Add a new child to the linkset. - // Called while LinkActivity is locked. - protected override void AddChildToLinkset(BSPhysObject child) - { - if (!HasChild(child)) - { - m_children.Add(child); - - DetailLog("{0},BSLinksetConstraints.AddChildToLinkset,call,child={1}", LinksetRoot.LocalID, child.LocalID); - - // Cause constraints and assorted properties to be recomputed before the next simulation step. - Refresh(LinksetRoot); - } - return; - } - - // Remove the specified child from the linkset. - // Safe to call even if the child is not really in my linkset. - protected override void RemoveChildFromLinkset(BSPhysObject child) - { - if (m_children.Remove(child)) - { - BSPhysObject rootx = LinksetRoot; // capture the root and body as of now - BSPhysObject childx = child; - - DetailLog("{0},BSLinksetConstraints.RemoveChildFromLinkset,call,rID={1},rBody={2},cID={3},cBody={4}", - childx.LocalID, - rootx.LocalID, rootx.PhysBody.ptr.ToString("X"), - childx.LocalID, childx.PhysBody.ptr.ToString("X")); - - PhysicsScene.TaintedObject("BSLinksetConstraints.RemoveChildFromLinkset", delegate() - { - PhysicallyUnlinkAChildFromRoot(rootx, childx); - }); - // See that the linkset parameters are recomputed at the end of the taint time. - Refresh(LinksetRoot); - } - else - { - // Non-fatal occurance. - // PhysicsScene.Logger.ErrorFormat("{0}: Asked to remove child from linkset that was not in linkset", LogHeader); - } - return; - } - - // Create a constraint between me (root of linkset) and the passed prim (the child). - // Called at taint time! - private void PhysicallyLinkAChildToRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Don't build the constraint when asked. Put it off until just before the simulation step. - Refresh(rootPrim); - } - - private BSConstraint BuildConstraint(BSPhysObject rootPrim, BSPhysObject childPrim) - { - // Zero motion for children so they don't interpolate - childPrim.ZeroMotion(); - - // Relative position normalized to the root prim - // Essentually a vector pointing from center of rootPrim to center of childPrim - OMV.Vector3 childRelativePosition = childPrim.Position - rootPrim.Position; - - // real world coordinate of midpoint between the two objects - OMV.Vector3 midPoint = rootPrim.Position + (childRelativePosition / 2); - - DetailLog("{0},BSLinksetConstraint.BuildConstraint,taint,root={1},rBody={2},child={3},cBody={4},rLoc={5},cLoc={6},midLoc={7}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X"), - rootPrim.Position, childPrim.Position, midPoint); - - // create a constraint that allows no freedom of movement between the two objects - // http://bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=4818 - - BSConstraint6Dof constrain = new BSConstraint6Dof( - PhysicsScene.World, rootPrim.PhysBody, childPrim.PhysBody, midPoint, true, true ); - // PhysicsScene.World, childPrim.BSBody, rootPrim.BSBody, midPoint, true, true ); - - /* NOTE: below is an attempt to build constraint with full frame computation, etc. - * Using the midpoint is easier since it lets the Bullet code manipulate the transforms - * of the objects. - * Code left for future programmers. - // ================================================================================== - // relative position normalized to the root prim - OMV.Quaternion invThisOrientation = OMV.Quaternion.Inverse(rootPrim.Orientation); - OMV.Vector3 childRelativePosition = (childPrim.Position - rootPrim.Position) * invThisOrientation; - - // relative rotation of the child to the parent - OMV.Quaternion childRelativeRotation = invThisOrientation * childPrim.Orientation; - OMV.Quaternion inverseChildRelativeRotation = OMV.Quaternion.Inverse(childRelativeRotation); - - DetailLog("{0},BSLinksetConstraint.PhysicallyLinkAChildToRoot,taint,root={1},child={2}", rootPrim.LocalID, rootPrim.LocalID, childPrim.LocalID); - BS6DofConstraint constrain = new BS6DofConstraint( - PhysicsScene.World, rootPrim.Body, childPrim.Body, - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(rootPrim.Orientation), - OMV.Vector3.Zero, - OMV.Quaternion.Inverse(childPrim.Orientation), - true, - true - ); - // ================================================================================== - */ - - PhysicsScene.Constraints.AddConstraint(constrain); - - // zero linear and angular limits makes the objects unable to move in relation to each other - constrain.SetLinearLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - constrain.SetAngularLimits(OMV.Vector3.Zero, OMV.Vector3.Zero); - - // tweek the constraint to increase stability - constrain.UseFrameOffset(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintUseFrameOffset)); - constrain.TranslationalLimitMotor(PhysicsScene.BoolNumeric(PhysicsScene.Params.linkConstraintEnableTransMotor), - PhysicsScene.Params.linkConstraintTransMotorMaxVel, - PhysicsScene.Params.linkConstraintTransMotorMaxForce); - constrain.SetCFMAndERP(PhysicsScene.Params.linkConstraintCFM, PhysicsScene.Params.linkConstraintERP); - if (PhysicsScene.Params.linkConstraintSolverIterations != 0f) - { - constrain.SetSolverIterations(PhysicsScene.Params.linkConstraintSolverIterations); - } - return constrain; - } - - // Remove linkage between the linkset root and a particular child - // The root and child bodies are passed in because we need to remove the constraint between - // the bodies that were present at unlink time. - // Called at taint time! - private bool PhysicallyUnlinkAChildFromRoot(BSPhysObject rootPrim, BSPhysObject childPrim) - { - bool ret = false; - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAChildFromRoot,taint,root={1},rBody={2},child={3},cBody={4}", - rootPrim.LocalID, - rootPrim.LocalID, rootPrim.PhysBody.ptr.ToString("X"), - childPrim.LocalID, childPrim.PhysBody.ptr.ToString("X")); - - // Find the constraint for this link and get rid of it from the overall collection and from my list - if (PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody, childPrim.PhysBody)) - { - // Make the child refresh its location - BulletSimAPI.PushUpdate2(childPrim.PhysBody.ptr); - ret = true; - } - - return ret; - } - - // Remove linkage between myself and any possible children I might have. - // Returns 'true' of any constraints were destroyed. - // Called at taint time! - private bool PhysicallyUnlinkAllChildrenFromRoot(BSPhysObject rootPrim) - { - DetailLog("{0},BSLinksetConstraint.PhysicallyUnlinkAllChildren,taint", rootPrim.LocalID); - - return PhysicsScene.Constraints.RemoveAndDestroyConstraint(rootPrim.PhysBody); - } - - // Call each of the constraints that make up this linkset and recompute the - // various transforms and variables. Create constraints of not created yet. - // Called before the simulation step to make sure the constraint based linkset - // is all initialized. - // Called at taint time!! - private void RecomputeLinksetConstraints() - { - float linksetMass = LinksetMass; - LinksetRoot.UpdatePhysicalMassProperties(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(LinksetRoot.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - DetailLog("{0},BSLinksetConstraint.RecomputeLinksetConstraints,set,rBody={1},linksetMass={2}", - LinksetRoot.LocalID, LinksetRoot.PhysBody.ptr.ToString("X"), linksetMass); - - foreach (BSPhysObject child in m_children) - { - // A child in the linkset physically shows the mass of the whole linkset. - // This allows Bullet to apply enough force on the child to move the whole linkset. - // (Also do the mass stuff before recomputing the constraint so mass is not zero.) - child.UpdatePhysicalMassProperties(linksetMass); - - BSConstraint constrain; - if (!PhysicsScene.Constraints.TryGetConstraint(LinksetRoot.PhysBody, child.PhysBody, out constrain)) - { - // If constraint doesn't exist yet, create it. - constrain = BuildConstraint(LinksetRoot, child); - } - constrain.RecomputeConstraintVariables(linksetMass); - - // DEBUG: see of inter-linkset collisions are causing problems - // BulletSimAPI.SetCollisionFilterMask2(child.BSBody.ptr, - // (uint)CollisionFilterGroups.LinksetFilter, (uint)CollisionFilterGroups.LinksetMask); - - // BulletSimAPI.DumpConstraint2(PhysicsScene.World.ptr, constrain.Constraint.ptr); // DEBUG DEBUG - } - - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs deleted file mode 100755 index 7127aaf194..0000000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPhysObject.cs +++ /dev/null @@ -1,248 +0,0 @@ -/* - * 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 copyrightD - * 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.Text; - -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -// Class to wrap all objects. -// The rest of BulletSim doesn't need to keep checking for avatars or prims -// unless the difference is significant. -public abstract class BSPhysObject : PhysicsActor -{ - protected void BaseInitialize(BSScene parentScene, uint localID, string name, string typeName) - { - PhysicsScene = parentScene; - LocalID = localID; - PhysObjectName = name; - TypeName = typeName; - - Linkset = BSLinkset.Factory(PhysicsScene, this); - LastAssetBuildFailed = false; - - CollisionCollection = new CollisionEventUpdate(); - SubscribedEventsMs = 0; - CollidingStep = 0; - CollidingGroundStep = 0; - } - - public BSScene PhysicsScene { get; protected set; } - // public override uint LocalID { get; set; } // Use the LocalID definition in PhysicsActor - public string PhysObjectName { get; protected set; } - public string TypeName { get; protected set; } - - public BSLinkset Linkset { get; set; } - - // Return the object mass without calculating it or having side effects - public abstract float RawMass { get; } - // Set the raw mass but also update physical mass properties (inertia, ...) - public abstract void UpdatePhysicalMassProperties(float mass); - - // Reference to the physical body (btCollisionObject) of this object - public BulletBody PhysBody; - // Reference to the physical shape (btCollisionShape) of this object - public BulletShape PhysShape; - - // 'true' if the mesh's underlying asset failed to build. - // This will keep us from looping after the first time the build failed. - public bool LastAssetBuildFailed { get; set; } - - // The objects base shape information. Null if not a prim type shape. - public PrimitiveBaseShape BaseShape { get; protected set; } - // Some types of objects have preferred physical representations. - // Returns SHAPE_UNKNOWN if there is no preference. - public virtual ShapeData.PhysicsShapeType PreferredPhysicalShape - { - get { return ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; } - } - - // When the physical properties are updated, an EntityProperty holds the update values. - // Keep the current and last EntityProperties to enable computation of differences - // between the current update and the previous values. - public EntityProperties CurrentEntityProperties { get; set; } - public EntityProperties LastEntityProperties { get; set; } - - public abstract OMV.Vector3 Scale { get; set; } - public abstract bool IsSolid { get; } - public abstract bool IsStatic { get; } - - // Stop all physical motion. - public abstract void ZeroMotion(); - - // Step the vehicle simulation for this object. A NOOP if the vehicle was not configured. - public virtual void StepVehicle(float timeStep) { } - - // Update the physical location and motion of the object. Called with data from Bullet. - public abstract void UpdateProperties(EntityProperties entprop); - - // Tell the object to clean up. - public abstract void Destroy(); - - public abstract OMV.Vector3 RawPosition { get; set; } - public abstract OMV.Vector3 ForcePosition { get; set; } - - public abstract OMV.Quaternion RawOrientation { get; set; } - public abstract OMV.Quaternion ForceOrientation { get; set; } - - public abstract OMV.Vector3 ForceVelocity { get; set; } - - public abstract OMV.Vector3 ForceRotationalVelocity { get; set; } - - public abstract float ForceBuoyancy { get; set; } - - public virtual bool ForceBodyShapeRebuild(bool inTaintTime) { return false; } - - #region Collisions - - // Requested number of milliseconds between collision events. Zero means disabled. - protected int SubscribedEventsMs { get; set; } - // Given subscription, the time that a collision may be passed up - protected int NextCollisionOkTime { get; set; } - // The simulation step that last had a collision - protected long CollidingStep { get; set; } - // The simulation step that last had a collision with the ground - protected long CollidingGroundStep { get; set; } - // The collision flags we think are set in Bullet - protected CollisionFlags CurrentCollisionFlags { get; set; } - - // The collisions that have been collected this tick - protected CollisionEventUpdate CollisionCollection; - - // The simulation step is telling this object about a collision. - // Return 'true' if a collision was processed and should be sent up. - // Called at taint time from within the Step() function - public virtual bool Collide(uint collidingWith, BSPhysObject collidee, - OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) - { - bool ret = false; - - // The following lines make IsColliding() and IsCollidingGround() work - CollidingStep = PhysicsScene.SimulationStep; - if (collidingWith <= PhysicsScene.TerrainManager.HighestTerrainID) - { - CollidingGroundStep = PhysicsScene.SimulationStep; - } - - // prims in the same linkset cannot collide with each other - if (collidee != null && (this.Linkset.LinksetID == collidee.Linkset.LinksetID)) - { - return ret; - } - - // if someone has subscribed for collision events.... - if (SubscribedEvents()) { - CollisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); - DetailLog("{0},{1}.Collison.AddCollider,call,with={2},point={3},normal={4},depth={5}", - LocalID, TypeName, collidingWith, contactPoint, contactNormal, pentrationDepth); - - ret = true; - } - return ret; - } - - // Send the collected collisions into the simulator. - // Called at taint time from within the Step() function thus no locking problems - // with CollisionCollection and ObjectsWithNoMoreCollisions. - // Return 'true' if there were some actual collisions passed up - public virtual bool SendCollisions() - { - bool ret = true; - // If the 'no collision' call, force it to happen right now so quick collision_end - bool force = CollisionCollection.Count == 0; - - // throttle the collisions to the number of milliseconds specified in the subscription - if (force || (PhysicsScene.SimulationNowTime >= NextCollisionOkTime)) - { - NextCollisionOkTime = PhysicsScene.SimulationNowTime + SubscribedEventsMs; - - // We are called if we previously had collisions. If there are no collisions - // this time, send up one last empty event so OpenSim can sense collision end. - if (CollisionCollection.Count == 0) - { - // If I have no collisions this time, remove me from the list of objects with collisions. - ret = false; - } - - // DetailLog("{0},{1}.SendCollisionUpdate,call,numCollisions={2}", LocalID, TypeName, CollisionCollection.Count); - base.SendCollisionUpdate(CollisionCollection); - - // The collisionCollection structure is passed around in the simulator. - // Make sure we don't have a handle to that one and that a new one is used for next time. - CollisionCollection = new CollisionEventUpdate(); - } - return ret; - } - - // Subscribe for collision events. - // Parameter is the millisecond rate the caller wishes collision events to occur. - public override void SubscribeEvents(int ms) { - // DetailLog("{0},{1}.SubscribeEvents,subscribing,ms={2}", LocalID, TypeName, ms); - SubscribedEventsMs = ms; - if (ms > 0) - { - // make sure first collision happens - NextCollisionOkTime = Util.EnvironmentTickCountSubtract(SubscribedEventsMs); - - PhysicsScene.TaintedObject(TypeName+".SubscribeEvents", delegate() - { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - else - { - // Subscribing for zero or less is the same as unsubscribing - UnSubscribeEvents(); - } - } - public override void UnSubscribeEvents() { - // DetailLog("{0},{1}.UnSubscribeEvents,unsubscribing", LocalID, TypeName); - SubscribedEventsMs = 0; - PhysicsScene.TaintedObject(TypeName+".UnSubscribeEvents", delegate() - { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - }); - } - // Return 'true' if the simulator wants collision events - public override bool SubscribedEvents() { - return (SubscribedEventsMs > 0); - } - - #endregion // Collisions - - // High performance detailed logging routine used by the physical objects. - protected void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs index 20f5180551..0f027b8d6a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPlugin.cs @@ -33,7 +33,7 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { /// - /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. + /// Entry for a port of Bullet (http://bulletphysics.org/) to OpenSim. /// This module interfaces to an unmanaged C++ library which makes the /// actual calls into the Bullet physics engine. /// The unmanaged library is found in opensim-libs::trunk/unmanaged/BulletSim/. @@ -62,7 +62,7 @@ public class BSPlugin : IPhysicsPlugin if (Util.IsWindows()) Util.LoadArchSpecificWindowsDll("BulletSim.dll"); // If not Windows, loading is performed by the - // Mono loader as specified in + // Mono loader as specified in // "bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config". _mScene = new BSScene(sceneIdentifier); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs index aaa0d93c77..9c20004deb 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSPrim.cs @@ -24,9 +24,6 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ - -// Uncomment this it enable code to do all shape an body memory management -// in the C# code. using System; using System.Reflection; using System.Collections.Generic; @@ -39,18 +36,32 @@ using OpenSim.Region.Physics.ConvexDecompositionDotNet; namespace OpenSim.Region.Physics.BulletSPlugin { - [Serializable] -public sealed class BSPrim : BSPhysObject +public sealed class BSPrim : PhysicsActor { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS PRIM]"; - // _size is what the user passed. Scale is what we pass to the physics engine with the mesh. - // Often Scale is unity because the meshmerizer will apply _size when creating the mesh. - private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user - // private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer + private void DebugLog(string mm, params Object[] xx) { if (_scene.ShouldDebugLog) m_log.DebugFormat(mm, xx); } + private IMesh _mesh; + private PrimitiveBaseShape _pbs; + private ShapeData.PhysicsShapeType _shapeType; + private ulong _meshKey; + private ulong _hullKey; + private List _hulls; + + private BSScene _scene; + public BSScene Scene { get { return _scene; } } + private String _avName; + private uint _localID = 0; + + // _size is what the user passed. _scale is what we pass to the physics engine with the mesh. + // Often _scale is unity because the meshmerizer will apply _size when creating the mesh. + private OMV.Vector3 _size; // the multiplier for each mesh dimension as passed by the user + private OMV.Vector3 _scale; // the multiplier for each mesh dimension for the mesh as created by the meshmerizer + + private bool _stopped; private bool _grabbed; private bool _isSelected; private bool _isVolumeDetect; @@ -78,6 +89,25 @@ public sealed class BSPrim : BSPhysObject private bool _kinematic; private float _buoyancy; + // Membership in a linkset is controlled by this class. + private BSLinkset _linkset; + public BSLinkset Linkset + { + get { return _linkset; } + set { _linkset = value; } + } + + private int _subscribedEventsMs = 0; + private int _nextCollisionOkTime = 0; + long _collidingStep; + long _collidingGroundStep; + + private BulletBody m_body; + public BulletBody Body { + get { return m_body; } + set { m_body = value; } + } + private BSDynamics _vehicle; private OMV.Vector3 _PIDTarget; @@ -92,112 +122,108 @@ public sealed class BSPrim : BSPhysObject OMV.Quaternion rotation, PrimitiveBaseShape pbs, bool pisPhysical) { // m_log.DebugFormat("{0}: BSPrim creation of {1}, id={2}", LogHeader, primName, localID); - base.BaseInitialize(parent_scene, localID, primName, "BSPrim"); - _physicsActorType = (int)ActorTypes.Prim; + _localID = localID; + _avName = primName; + _scene = parent_scene; _position = pos; _size = size; - Scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type + _scale = new OMV.Vector3(1f, 1f, 1f); // the scale will be set by CreateGeom depending on object type _orientation = rotation; _buoyancy = 1f; _velocity = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - BaseShape = pbs; + _hullKey = 0; + _meshKey = 0; + _pbs = pbs; _isPhysical = pisPhysical; _isVolumeDetect = false; - _friction = PhysicsScene.Params.defaultFriction; // TODO: compute based on object material - _density = PhysicsScene.Params.defaultDensity; // TODO: compute based on object material - _restitution = PhysicsScene.Params.defaultRestitution; - _vehicle = new BSDynamics(PhysicsScene, this); // add vehicleness + _subscribedEventsMs = 0; + _friction = _scene.Params.defaultFriction; // TODO: compute based on object material + _density = _scene.Params.defaultDensity; // TODO: compute based on object material + _restitution = _scene.Params.defaultRestitution; + _linkset = new BSLinkset(_scene, this); // a linkset of one + _vehicle = new BSDynamics(this); // add vehicleness _mass = CalculateMass(); - - // No body or shape yet - PhysBody = new BulletBody(LocalID, IntPtr.Zero); - PhysShape = new BulletShape(IntPtr.Zero); - - DetailLog("{0},BSPrim.constructor,call", LocalID); // do the actual object creation at taint time - PhysicsScene.TaintedObject("BSPrim.create", delegate() + DetailLog("{0},BSPrim.constructor,call", LocalID); + _scene.TaintedObject("BSPrim.create", delegate() { - CreateGeomAndObject(true); + RecreateGeomAndObject(); - CurrentCollisionFlags = BulletSimAPI.GetCollisionFlags2(PhysBody.ptr); + // Get the pointer to the physical body for this object. + // At the moment, we're still letting BulletSim manage the creation and destruction + // of the object. Someday we'll move that into the C# code. + m_body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); }); } // called when this prim is being destroyed and we should free all the resources - public override void Destroy() + public void Destroy() { // m_log.DebugFormat("{0}: Destroy, id={1}", LogHeader, LocalID); // Undo any links between me and any other object - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; + BSPrim parentBefore = _linkset.LinksetRoot; + int childrenBefore = _linkset.NumberOfChildren; - Linkset = Linkset.RemoveMeFromLinkset(this); + _linkset = _linkset.RemoveMeFromLinkset(this); DetailLog("{0},BSPrim.Destroy,call,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); // Undo any vehicle properties this.VehicleType = (int)Vehicle.TYPE_NONE; - PhysicsScene.TaintedObject("BSPrim.destroy", delegate() + _scene.TaintedObject("BSPrim.destroy", delegate() { DetailLog("{0},BSPrim.Destroy,taint,", LocalID); - // If there are physical body and shape, release my use of same. - PhysicsScene.Shapes.DereferenceBody(PhysBody, true, null); - PhysicsScene.Shapes.DereferenceShape(PhysShape, true, null); + // everything in the C# world will get garbage collected. Tell the C++ world to free stuff. + BulletSimAPI.DestroyObject(_scene.WorldID, LocalID); }); } - - // No one uses this property. - public override bool Stopped { - get { return false; } + + public override bool Stopped { + get { return _stopped; } } - public override OMV.Vector3 Size { - get { return _size; } + public override OMV.Vector3 Size { + get { return _size; } set { _size = value; - ForceBodyShapeRebuild(false); - } + _scene.TaintedObject("BSPrim.setSize", delegate() + { + _mass = CalculateMass(); // changing size changes the mass + BulletSimAPI.SetObjectScaleMass(_scene.WorldID, _localID, _scale, (IsPhysical ? _mass : 0f), IsPhysical); + // DetailLog("{0}: BSPrim.setSize: size={1}, mass={2}, physical={3}", LocalID, _size, _mass, IsPhysical); + RecreateGeomAndObject(); + }); + } } - // Scale is what we set in the physics engine. It is different than 'size' in that - // 'size' can be encorporated into the mesh. In that case, the scale is <1,1,1>. - public override OMV.Vector3 Scale { get; set; } - - public override PrimitiveBaseShape Shape { + public override PrimitiveBaseShape Shape { set { - BaseShape = value; - ForceBodyShapeRebuild(false); - } + _pbs = value; + _scene.TaintedObject("BSPrim.setShape", delegate() + { + _mass = CalculateMass(); // changing the shape changes the mass + RecreateGeomAndObject(); + }); + } } - // Whatever the linkset wants is what I want. - public override ShapeData.PhysicsShapeType PreferredPhysicalShape - { get { return Linkset.PreferredPhysicalShape(this); } } - - public override bool ForceBodyShapeRebuild(bool inTaintTime) - { - LastAssetBuildFailed = false; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ForceBodyShapeRebuild", delegate() - { - _mass = CalculateMass(); // changing the shape changes the mass - CreateGeomAndObject(true); - }); - return true; + public override uint LocalID { + set { _localID = value; } + get { return _localID; } } - public override bool Grabbed { - set { _grabbed = value; - } + public override bool Grabbed { + set { _grabbed = value; + } } - public override bool Selected { + public override bool Selected { set { _isSelected = value; - PhysicsScene.TaintedObject("BSPrim.setSelected", delegate() + _scene.TaintedObject("BSPrim.setSelected", delegate() { - DetailLog("{0},BSPrim.selected,taint,selected={1}", LocalID, _isSelected); - SetObjectDynamic(false); + SetObjectDynamic(); }); - } + } } public override void CrossingFailure() { return; } @@ -206,255 +232,158 @@ public sealed class BSPrim : BSPhysObject BSPrim parent = obj as BSPrim; if (parent != null) { - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; + DebugLog("{0}: link {1}/{2} to {3}", LogHeader, _avName, _localID, parent.LocalID); + BSPrim parentBefore = _linkset.LinksetRoot; + int childrenBefore = _linkset.NumberOfChildren; - Linkset = parent.Linkset.AddMeToLinkset(this); + _linkset = parent.Linkset.AddMeToLinkset(this); - DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); + DetailLog("{0},BSPrim.link,call,parentBefore={1}, childrenBefore=={2}, parentAfter={3}, childrenAfter={4}", + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); } - return; + return; } // delink me from my linkset public override void delink() { // TODO: decide if this parent checking needs to happen at taint time // Race condition here: if link() and delink() in same simulation tick, the delink will not happen + DebugLog("{0}: delink {1}/{2}. Parent={3}", LogHeader, _avName, _localID, + _linkset.LinksetRoot._avName+"/"+_linkset.LinksetRoot.LocalID.ToString()); - BSPhysObject parentBefore = Linkset.LinksetRoot; - int childrenBefore = Linkset.NumberOfChildren; + BSPrim parentBefore = _linkset.LinksetRoot; + int childrenBefore = _linkset.NumberOfChildren; + + _linkset = _linkset.RemoveMeFromLinkset(this); - Linkset = Linkset.RemoveMeFromLinkset(this); - - DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", - LocalID, parentBefore.LocalID, childrenBefore, Linkset.LinksetRoot.LocalID, Linkset.NumberOfChildren); - return; + DetailLog("{0},BSPrim.delink,parentBefore={1},childrenBefore={2},parentAfter={3},childrenAfter={4}, ", + LocalID, parentBefore.LocalID, childrenBefore, _linkset.LinksetRoot.LocalID, _linkset.NumberOfChildren); + return; } // Set motion values to zero. // Do it to the properties so the values get set in the physics engine. // Push the setting of the values to the viewer. // Called at taint time! - public override void ZeroMotion() + public void ZeroMotion() { _velocity = OMV.Vector3.Zero; _acceleration = OMV.Vector3.Zero; _rotationalVelocity = OMV.Vector3.Zero; - // Zero some other properties in the physics engine - BulletSimAPI.ClearAllForces2(PhysBody.ptr); + // Zero some other properties directly into the physics engine + BulletSimAPI.SetVelocity2(Body.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetAngularVelocity2(Body.Ptr, OMV.Vector3.Zero); + BulletSimAPI.SetInterpolation2(Body.Ptr, OMV.Vector3.Zero, OMV.Vector3.Zero); + BulletSimAPI.ClearForces2(Body.Ptr); } public override void LockAngularMotion(OMV.Vector3 axis) - { - DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); + { + // DetailLog("{0},BSPrim.LockAngularMotion,call,axis={1}", LocalID, axis); return; } - public override OMV.Vector3 RawPosition - { - get { return _position; } - set { _position = value; } - } - public override OMV.Vector3 Position { - get { - // child prims move around based on their parent. Need to get the latest location - if (!Linkset.IsRoot(this)) - _position = Linkset.Position(this); + public override OMV.Vector3 Position { + get { + if (!_linkset.IsRoot(this)) + // child prims move around based on their parent. Need to get the latest location + _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); // don't do the GetObjectPosition for root elements because this function is called a zillion times - // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); - return _position; - } + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); + return _position; + } set { - // If you must push the position into the physics engine, use ForcePosition. - if (_position == value) - { - return; - } _position = value; // TODO: what does it mean to set the position of a child prim?? Rebuild the constraint? - PositionSanityCheck(); - PhysicsScene.TaintedObject("BSPrim.setPosition", delegate() + _scene.TaintedObject("BSPrim.setPosition", delegate() { // DetailLog("{0},BSPrim.SetPosition,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - ActivateIfPhysical(false); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } - } - public override OMV.Vector3 ForcePosition { - get { - _position = BulletSimAPI.GetPosition2(PhysBody.ptr); - return _position; - } - set { - _position = value; - PositionSanityCheck(); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - ActivateIfPhysical(false); - } - } - - // Check that the current position is sane and, if not, modify the position to make it so. - // Check for being below terrain and being out of bounds. - // Returns 'true' of the position was made sane by some action. - private bool PositionSanityCheck() - { - bool ret = false; - - // If totally below the ground, move the prim up - // TODO: figure out the right solution for this... only for dynamic objects? - /* - float terrainHeight = PhysicsScene.TerrainManager.GetTerrainHeightAtXYZ(_position); - if (Position.Z < terrainHeight) - { - DetailLog("{0},BSPrim.PositionAdjustUnderGround,call,pos={1},terrain={2}", LocalID, _position, terrainHeight); - _position.Z = terrainHeight + 2.0f; - ret = true; - } - */ - if ((CurrentCollisionFlags & CollisionFlags.BS_FLOATS_ON_WATER) != 0) - { - float waterHeight = PhysicsScene.GetWaterLevelAtXYZ(_position); - // TODO: a floating motor so object will bob in the water - if (Position.Z < waterHeight) - { - _position.Z = waterHeight; - ret = true; - } - } - - // TODO: check for out of bounds - return ret; - } - - // A version of the sanity check that also makes sure a new position value is - // pushed to the physics engine. This routine would be used by anyone - // who is not already pushing the value. - private bool PositionSanityCheck(bool inTaintTime) - { - bool ret = false; - if (PositionSanityCheck()) - { - // The new position value must be pushed into the physics engine but we can't - // just assign to "Position" because of potential call loops. - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.PositionSanityCheck", delegate() - { - DetailLog("{0},BSPrim.PositionSanityCheck,taint,pos={1},orient={2}", LocalID, _position, _orientation); - ForcePosition = _position; - }); - ret = true; - } - return ret; + } } // Return the effective mass of the object. // If there are multiple items in the linkset, add them together for the root public override float Mass - { + { get { - return Linkset.LinksetMass; - // return _mass; + return _linkset.LinksetMass; } } // used when we only want this prim's mass and not the linkset thing - public override float RawMass { - get { return _mass; } - } - // Set the physical mass to the passed mass. - // Note that this does not change _mass! - public override void UpdatePhysicalMassProperties(float physMass) - { - if (IsStatic) - { - BulletSimAPI.SetMassProps2(PhysBody.ptr, 0f, OMV.Vector3.Zero); - BulletSimAPI.UpdateInertiaTensor2(PhysBody.ptr); - } - else - { - OMV.Vector3 localInertia = BulletSimAPI.CalculateLocalInertia2(PhysShape.ptr, physMass); - BulletSimAPI.SetMassProps2(PhysBody.ptr, physMass, localInertia); - // center of mass is at the zero of the object - BulletSimAPI.SetCenterOfMassByPosRot2(PhysBody.ptr, ForcePosition, ForceOrientation); - // BulletSimAPI.UpdateInertiaTensor2(BSBody.ptr); - DetailLog("{0},BSPrim.UpdateMassProperties,mass={1},localInertia={2}", LocalID, physMass, localInertia); - } - } + public float MassRaw { get { return _mass; } } // Is this used? public override OMV.Vector3 CenterOfMass { - get { return Linkset.CenterOfMass; } + get { return _linkset.CenterOfMass; } } // Is this used? public override OMV.Vector3 GeometricCenter { - get { return Linkset.GeometricCenter; } + get { return _linkset.GeometricCenter; } } - public override OMV.Vector3 Force { - get { return _force; } + public override OMV.Vector3 Force { + get { return _force; } set { _force = value; - PhysicsScene.TaintedObject("BSPrim.setForce", delegate() + _scene.TaintedObject("BSPrim.setForce", delegate() { // DetailLog("{0},BSPrim.setForce,taint,force={1}", LocalID, _force); - BulletSimAPI.SetObjectForce2(PhysBody.ptr, _force); + // BulletSimAPI.SetObjectForce(_scene.WorldID, _localID, _force); + BulletSimAPI.SetObjectForce2(Body.Ptr, _force); }); - } + } } - public override int VehicleType { + public override int VehicleType { get { return (int)_vehicle.Type; // if we are a vehicle, return that type - } + } set { Vehicle type = (Vehicle)value; - - // Tell the scene about the vehicle so it will get processing each frame. - PhysicsScene.VehicleInSceneTypeChanged(this, type); - - PhysicsScene.TaintedObject("setVehicleType", delegate() + BSPrim vehiclePrim = this; + _scene.TaintedObject("setVehicleType", delegate() { // Done at taint time so we're sure the physics engine is not using the variables // Vehicle code changes the parameters for this vehicle type. _vehicle.ProcessTypeChange(type); - ActivateIfPhysical(false); + // Tell the scene about the vehicle so it will get processing each frame. + _scene.VehicleInSceneTypeChanged(this, type); }); - } + } } - public override void VehicleFloatParam(int param, float value) + public override void VehicleFloatParam(int param, float value) { - PhysicsScene.TaintedObject("BSPrim.VehicleFloatParam", delegate() + _scene.TaintedObject("BSPrim.VehicleFloatParam", delegate() { - _vehicle.ProcessFloatVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); + _vehicle.ProcessFloatVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); }); } - public override void VehicleVectorParam(int param, OMV.Vector3 value) + public override void VehicleVectorParam(int param, OMV.Vector3 value) { - PhysicsScene.TaintedObject("BSPrim.VehicleVectorParam", delegate() + _scene.TaintedObject("BSPrim.VehicleVectorParam", delegate() { - _vehicle.ProcessVectorVehicleParam((Vehicle)param, value); - ActivateIfPhysical(false); + _vehicle.ProcessVectorVehicleParam((Vehicle)param, value, _scene.LastSimulatedTimestep); }); } - public override void VehicleRotationParam(int param, OMV.Quaternion rotation) + public override void VehicleRotationParam(int param, OMV.Quaternion rotation) { - PhysicsScene.TaintedObject("BSPrim.VehicleRotationParam", delegate() + _scene.TaintedObject("BSPrim.VehicleRotationParam", delegate() { _vehicle.ProcessRotationVehicleParam((Vehicle)param, rotation); - ActivateIfPhysical(false); }); } - public override void VehicleFlags(int param, bool remove) + public override void VehicleFlags(int param, bool remove) { - PhysicsScene.TaintedObject("BSPrim.VehicleFlags", delegate() + _scene.TaintedObject("BSPrim.VehicleFlags", delegate() { _vehicle.ProcessVehicleFlags(param, remove); }); @@ -462,355 +391,143 @@ public sealed class BSPrim : BSPhysObject // Called each simulation step to advance vehicle characteristics. // Called from Scene when doing simulation step so we're in taint processing time. - public override void StepVehicle(float timeStep) + public void StepVehicle(float timeStep) { - if (IsPhysical && _vehicle.IsActive) - { + if (IsPhysical) _vehicle.Step(timeStep); - /* // TEST TEST DEBUG DEBUG -- trying to reduce the extra action of Bullet simulation step - PhysicsScene.PostTaintObject("BSPrim.StepVehicles", LocalID, delegate() - { - // This resets the interpolation values and recomputes the tensor variables - BulletSimAPI.SetCenterOfMassByPosRot2(BSBody.ptr, ForcePosition, ForceOrientation); - }); - */ - } } // Allows the detection of collisions with inherently non-physical prims. see llVolumeDetect for more public override void SetVolumeDetect(int param) { bool newValue = (param != 0); - if (_isVolumeDetect != newValue) + _isVolumeDetect = newValue; + _scene.TaintedObject("BSPrim.SetVolumeDetect", delegate() { - _isVolumeDetect = newValue; - PhysicsScene.TaintedObject("BSPrim.SetVolumeDetect", delegate() - { - // DetailLog("{0},setVolumeDetect,taint,volDetect={1}", LocalID, _isVolumeDetect); - SetObjectDynamic(true); - }); - } - return; + SetObjectDynamic(); + }); + return; } - public override OMV.Vector3 Velocity { - get { return _velocity; } + + public override OMV.Vector3 Velocity { + get { return _velocity; } set { _velocity = value; - PhysicsScene.TaintedObject("BSPrim.setVelocity", delegate() + _scene.TaintedObject("BSPrim.setVelocity", delegate() { // DetailLog("{0},BSPrim.SetVelocity,taint,vel={1}", LocalID, _velocity); - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); + BulletSimAPI.SetObjectVelocity(_scene.WorldID, LocalID, _velocity); }); - } + } } - public override OMV.Vector3 ForceVelocity { - get { return _velocity; } - set { - _velocity = value; - BulletSimAPI.SetLinearVelocity2(PhysBody.ptr, _velocity); - } - } - public override OMV.Vector3 Torque { - get { return _torque; } - set { - _torque = value; - AddAngularForce(_torque, false, false); + public override OMV.Vector3 Torque { + get { return _torque; } + set { _torque = value; // DetailLog("{0},BSPrim.SetTorque,call,torque={1}", LocalID, _torque); - } + } } - public override float CollisionScore { - get { return _collisionScore; } - set { _collisionScore = value; - } + public override float CollisionScore { + get { return _collisionScore; } + set { _collisionScore = value; + } } - public override OMV.Vector3 Acceleration { + public override OMV.Vector3 Acceleration { get { return _acceleration; } set { _acceleration = value; } } - public override OMV.Quaternion RawOrientation - { - get { return _orientation; } - set { _orientation = value; } - } - public override OMV.Quaternion Orientation { + public override OMV.Quaternion Orientation { get { - // Children move around because tied to parent. Get a fresh value. - if (!Linkset.IsRoot(this)) + if (!_linkset.IsRoot(this)) { - _orientation = Linkset.Orientation(this); + // Children move around because tied to parent. Get a fresh value. + _orientation = BulletSimAPI.GetObjectOrientation(_scene.WorldID, LocalID); } return _orientation; - } + } set { - if (_orientation == value) - return; _orientation = value; // TODO: what does it mean if a child in a linkset changes its orientation? Rebuild the constraint? - PhysicsScene.TaintedObject("BSPrim.setOrientation", delegate() + _scene.TaintedObject("BSPrim.setOrientation", delegate() { - // _position = BulletSimAPI.GetObjectPosition2(PhysicsScene.World.ptr, BSBody.ptr); + // _position = BulletSimAPI.GetObjectPosition(_scene.WorldID, _localID); // DetailLog("{0},BSPrim.setOrientation,taint,pos={1},orient={2}", LocalID, _position, _orientation); - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); + BulletSimAPI.SetObjectTranslation(_scene.WorldID, _localID, _position, _orientation); }); - } + } } - // Go directly to Bullet to get/set the value. - public override OMV.Quaternion ForceOrientation - { - get - { - _orientation = BulletSimAPI.GetOrientation2(PhysBody.ptr); - return _orientation; - } - set - { - _orientation = value; - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - } + public override int PhysicsActorType { + get { return _physicsActorType; } + set { _physicsActorType = value; + } } - public override int PhysicsActorType { - get { return _physicsActorType; } - set { _physicsActorType = value; } - } - public override bool IsPhysical { - get { return _isPhysical; } + public override bool IsPhysical { + get { return _isPhysical; } set { - if (_isPhysical != value) + _isPhysical = value; + _scene.TaintedObject("BSPrim.setIsPhysical", delegate() { - _isPhysical = value; - PhysicsScene.TaintedObject("BSPrim.setIsPhysical", delegate() - { - // DetailLog("{0},setIsPhysical,taint,isPhys={1}", LocalID, _isPhysical); - SetObjectDynamic(true); - // whether phys-to-static or static-to-phys, the object is not moving. - ZeroMotion(); - }); - } - } + SetObjectDynamic(); + }); + } } // An object is static (does not move) if selected or not physical - public override bool IsStatic + private bool IsStatic { get { return _isSelected || !IsPhysical; } } // An object is solid if it's not phantom and if it's not doing VolumeDetect - public override bool IsSolid + private bool IsSolid { get { return !IsPhantom && !_isVolumeDetect; } } // Make gravity work if the object is physical and not selected - // Called at taint-time!! - private void SetObjectDynamic(bool forceRebuild) + // No locking here because only called when it is safe + private void SetObjectDynamic() { - // Recreate the physical object if necessary - CreateGeomAndObject(forceRebuild); - } + // RA: remove this for the moment. + // The problem is that dynamic objects are hulls so if we are becoming physical + // the shape has to be checked and possibly built. + // Maybe a VerifyCorrectPhysicalShape() routine? + // RecreateGeomAndObject(); - // Convert the simulator's physical properties into settings on BulletSim objects. - // There are four flags we're interested in: - // IsStatic: Object does not move, otherwise the object has mass and moves - // isSolid: other objects bounce off of this object - // isVolumeDetect: other objects pass through but can generate collisions - // collisionEvents: whether this object returns collision events - private void UpdatePhysicalParameters() - { - // DetailLog("{0},BSPrim.UpdatePhysicalParameters,entry,body={1},shape={2}", LocalID, BSBody, BSShape); + // Bullet wants static objects to have a mass of zero + float mass = IsStatic ? 0f : _mass; - // Mangling all the physical properties requires the object not be in the physical world. - // This is a NOOP if the object is not in the world (BulletSim and Bullet ignore objects not found). - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, PhysBody.ptr); + BulletSimAPI.SetObjectProperties(_scene.WorldID, LocalID, IsStatic, IsSolid, SubscribedEvents(), mass); - // Set up the object physicalness (does gravity and collisions move this object) - MakeDynamic(IsStatic); + // recompute any linkset parameters + _linkset.Refresh(this); - // Update vehicle specific parameters (after MakeDynamic() so can change physical parameters) - _vehicle.Refresh(); - - // Arrange for collision events if the simulator wants them - EnableCollisions(SubscribedEvents()); - - // Make solid or not (do things bounce off or pass through this object). - MakeSolid(IsSolid); - - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Rebuild its shape - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, PhysBody.ptr); - - // Collision filter can be set only when the object is in the world - if (PhysBody.collisionFilter != 0 || PhysBody.collisionMask != 0) - { - BulletSimAPI.SetCollisionFilterMask2(PhysBody.ptr, (uint)PhysBody.collisionFilter, (uint)PhysBody.collisionMask); - } - - // Recompute any linkset parameters. - // When going from non-physical to physical, this re-enables the constraints that - // had been automatically disabled when the mass was set to zero. - Linkset.Refresh(this); - - DetailLog("{0},BSPrim.UpdatePhysicalParameters,taintExit,static={1},solid={2},mass={3},collide={4},cf={5:X},body={6},shape={7}", - LocalID, IsStatic, IsSolid, _mass, SubscribedEvents(), CurrentCollisionFlags, PhysBody, PhysShape); - } - - // "Making dynamic" means changing to and from static. - // When static, gravity does not effect the object and it is fixed in space. - // When dynamic, the object can fall and be pushed by others. - // This is independent of its 'solidness' which controls what passes through - // this object and what interacts with it. - private void MakeDynamic(bool makeStatic) - { - if (makeStatic) - { - // Become a Bullet 'static' object type - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - // Stop all movement - ZeroMotion(); - // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); - // Mass is zero which disables a bunch of physics stuff in Bullet - UpdatePhysicalMassProperties(0f); - // Set collision detection parameters - if (PhysicsScene.Params.ccdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - // There can be special things needed for implementing linksets - Linkset.MakeStatic(this); - // The activation state is 'disabled' so Bullet will not try to act on it. - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.DISABLE_SIMULATION); - // Start it out sleeping and physical actions could wake it up. - // BulletSimAPI.ForceActivationState2(BSBody.ptr, ActivationState.ISLAND_SLEEPING); - - PhysBody.collisionFilter = CollisionFilterGroups.StaticObjectFilter; - PhysBody.collisionMask = CollisionFilterGroups.StaticObjectMask; - } - else - { - // Not a Bullet static object - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Set various physical properties so internal dynamic properties will get computed correctly as they are set - BulletSimAPI.SetFriction2(PhysBody.ptr, PhysicsScene.Params.defaultFriction); - BulletSimAPI.SetRestitution2(PhysBody.ptr, PhysicsScene.Params.defaultRestitution); - - // per http://www.bulletphysics.org/Bullet/phpBB3/viewtopic.php?t=3382 - // Since this can be called multiple times, only zero forces when becoming physical - // BulletSimAPI.ClearAllForces2(BSBody.ptr); - - // For good measure, make sure the transform is set through to the motion state - BulletSimAPI.SetTranslation2(PhysBody.ptr, _position, _orientation); - - // Center of mass is at the center of the object - BulletSimAPI.SetCenterOfMassByPosRot2(Linkset.LinksetRoot.PhysBody.ptr, _position, _orientation); - - // A dynamic object has mass - UpdatePhysicalMassProperties(RawMass); - - // Set collision detection parameters - if (PhysicsScene.Params.ccdMotionThreshold > 0f) - { - BulletSimAPI.SetCcdMotionThreshold2(PhysBody.ptr, PhysicsScene.Params.ccdMotionThreshold); - BulletSimAPI.SetCcdSweptSphereRadius2(PhysBody.ptr, PhysicsScene.Params.ccdSweptSphereRadius); - } - - // Various values for simulation limits - BulletSimAPI.SetDamping2(PhysBody.ptr, PhysicsScene.Params.linearDamping, PhysicsScene.Params.angularDamping); - BulletSimAPI.SetDeactivationTime2(PhysBody.ptr, PhysicsScene.Params.deactivationTime); - BulletSimAPI.SetSleepingThresholds2(PhysBody.ptr, PhysicsScene.Params.linearSleepingThreshold, PhysicsScene.Params.angularSleepingThreshold); - BulletSimAPI.SetContactProcessingThreshold2(PhysBody.ptr, PhysicsScene.Params.contactProcessingThreshold); - - // There might be special things needed for implementing linksets. - Linkset.MakeDynamic(this); - - // Force activation of the object so Bullet will act on it. - // Must do the ForceActivationState2() to overcome the DISABLE_SIMULATION from static objects. - BulletSimAPI.ForceActivationState2(PhysBody.ptr, ActivationState.ACTIVE_TAG); - // BulletSimAPI.Activate2(BSBody.ptr, true); - - PhysBody.collisionFilter = CollisionFilterGroups.ObjectFilter; - PhysBody.collisionMask = CollisionFilterGroups.ObjectMask; - } - } - - // "Making solid" means that other object will not pass through this object. - // To make transparent, we create a Bullet ghost object. - // Note: This expects to be called from the UpdatePhysicalParameters() routine as - // the functions after this one set up the state of a possibly newly created collision body. - private void MakeSolid(bool makeSolid) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(PhysBody.ptr); - if (makeSolid) - { - // Verify the previous code created the correct shape for this type of thing. - if ((bodyType & CollisionObjectTypes.CO_RIGID_BODY) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for solidity. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - } - else - { - if ((bodyType & CollisionObjectTypes.CO_GHOST_OBJECT) == 0) - { - m_log.ErrorFormat("{0} MakeSolid: physical body of wrong type for non-solidness. id={1}, type={2}", LogHeader, LocalID, bodyType); - } - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.CF_NO_CONTACT_RESPONSE); - PhysBody.collisionFilter = CollisionFilterGroups.VolumeDetectFilter; - PhysBody.collisionMask = CollisionFilterGroups.VolumeDetectMask; - } - } - - // Enable physical actions. Bullet will keep sleeping non-moving physical objects so - // they need waking up when parameters are changed. - // Called in taint-time!! - private void ActivateIfPhysical(bool forceIt) - { - if (IsPhysical) - BulletSimAPI.Activate2(PhysBody.ptr, forceIt); - } - - // Turn on or off the flag controlling whether collision events are returned to the simulator. - private void EnableCollisions(bool wantsCollisionEvents) - { - if (wantsCollisionEvents) - { - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } - else - { - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); - } + CollisionFlags cf = BulletSimAPI.GetCollisionFlags2(Body.Ptr); + // DetailLog("{0},BSPrim.SetObjectDynamic,taint,static={1},solid={2},mass={3}, cf={4}", LocalID, IsStatic, IsSolid, mass, cf); } // prims don't fly - public override bool Flying { - get { return _flying; } - set { - _flying = value; - } + public override bool Flying { + get { return _flying; } + set { _flying = value; } } - public override bool SetAlwaysRun { - get { return _setAlwaysRun; } - set { _setAlwaysRun = value; } + public override bool SetAlwaysRun { + get { return _setAlwaysRun; } + set { _setAlwaysRun = value; } } - public override bool ThrottleUpdates { - get { return _throttleUpdates; } - set { _throttleUpdates = value; } + public override bool ThrottleUpdates { + get { return _throttleUpdates; } + set { _throttleUpdates = value; } } public override bool IsColliding { - get { return (CollidingStep == PhysicsScene.SimulationStep); } - set { _isColliding = value; } + get { return (_collidingStep == _scene.SimulationStep); } + set { _isColliding = value; } } public override bool CollidingGround { - get { return (CollidingGroundStep == PhysicsScene.SimulationStep); } - set { _collidingGround = value; } + get { return (_collidingGroundStep == _scene.SimulationStep); } + set { _collidingGround = value; } } - public override bool CollidingObj { - get { return _collidingObj; } - set { _collidingObj = value; } + public override bool CollidingObj { + get { return _collidingObj; } + set { _collidingObj = value; } } public bool IsPhantom { get { @@ -820,19 +537,10 @@ public sealed class BSPrim : BSPhysObject return false; } } - public override bool FloatOnWater { - set { - _floatOnWater = value; - PhysicsScene.TaintedObject("BSPrim.setFloatOnWater", delegate() - { - if (_floatOnWater) - CurrentCollisionFlags = BulletSimAPI.AddToCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - else - CurrentCollisionFlags = BulletSimAPI.RemoveFromCollisionFlags2(PhysBody.ptr, CollisionFlags.BS_FLOATS_ON_WATER); - }); - } + public override bool FloatOnWater { + set { _floatOnWater = value; } } - public override OMV.Vector3 RotationalVelocity { + public override OMV.Vector3 RotationalVelocity { get { /* OMV.Vector3 pv = OMV.Vector3.Zero; @@ -844,76 +552,58 @@ public sealed class BSPrim : BSPhysObject */ return _rotationalVelocity; - } + } set { _rotationalVelocity = value; // m_log.DebugFormat("{0}: RotationalVelocity={1}", LogHeader, _rotationalVelocity); - PhysicsScene.TaintedObject("BSPrim.setRotationalVelocity", delegate() + _scene.TaintedObject("BSPrim.setRotationalVelocity", delegate() { - DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); + // DetailLog("{0},BSPrim.SetRotationalVel,taint,rotvel={1}", LocalID, _rotationalVelocity); + BulletSimAPI.SetObjectAngularVelocity(_scene.WorldID, LocalID, _rotationalVelocity); }); - } + } } - public override OMV.Vector3 ForceRotationalVelocity { - get { - return _rotationalVelocity; - } - set { - _rotationalVelocity = value; - BulletSimAPI.SetAngularVelocity2(PhysBody.ptr, _rotationalVelocity); - } - } - public override bool Kinematic { - get { return _kinematic; } - set { _kinematic = value; + public override bool Kinematic { + get { return _kinematic; } + set { _kinematic = value; // m_log.DebugFormat("{0}: Kinematic={1}", LogHeader, _kinematic); - } + } } - public override float Buoyancy { - get { return _buoyancy; } + public override float Buoyancy { + get { return _buoyancy; } set { _buoyancy = value; - PhysicsScene.TaintedObject("BSPrim.setBuoyancy", delegate() + _scene.TaintedObject("BSPrim.setBuoyancy", delegate() { - ForceBuoyancy = _buoyancy; + // DetailLog("{0},BSPrim.SetBuoyancy,taint,buoy={1}", LocalID, _buoyancy); + BulletSimAPI.SetObjectBuoyancy(_scene.WorldID, _localID, _buoyancy); }); - } - } - public override float ForceBuoyancy { - get { return _buoyancy; } - set { - _buoyancy = value; - // DetailLog("{0},BSPrim.setForceBuoyancy,taint,buoy={1}", LocalID, _buoyancy); - // Buoyancy is faked by changing the gravity applied to the object - float grav = PhysicsScene.Params.gravity * (1f - _buoyancy); - BulletSimAPI.SetGravity2(PhysBody.ptr, new OMV.Vector3(0f, 0f, grav)); - } + } } // Used for MoveTo - public override OMV.Vector3 PIDTarget { - set { _PIDTarget = value; } + public override OMV.Vector3 PIDTarget { + set { _PIDTarget = value; } } - public override bool PIDActive { - set { _usePID = value; } + public override bool PIDActive { + set { _usePID = value; } } - public override float PIDTau { - set { _PIDTau = value; } + public override float PIDTau { + set { _PIDTau = value; } } // Used for llSetHoverHeight and maybe vehicle height // Hover Height will override MoveTo target's Z - public override bool PIDHoverActive { + public override bool PIDHoverActive { set { _useHoverPID = value; } } - public override float PIDHoverHeight { + public override float PIDHoverHeight { set { _PIDHoverHeight = value; } } - public override PIDHoverType PIDHoverType { + public override PIDHoverType PIDHoverType { set { _PIDHoverType = value; } } - public override float PIDHoverTau { + public override float PIDHoverTau { set { _PIDHoverTao = value; } } @@ -925,9 +615,6 @@ public sealed class BSPrim : BSPhysObject private List m_accumulatedForces = new List(); public override void AddForce(OMV.Vector3 force, bool pushforce) { - AddForce(force, pushforce, false); - } - public void AddForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) { // for an object, doesn't matter if force is a pushforce or not if (force.IsFinite()) { @@ -937,78 +624,56 @@ public sealed class BSPrim : BSPhysObject } else { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); + m_log.WarnFormat("{0}: Got a NaN force applied to a Character", LogHeader); return; } - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddForce", delegate() + _scene.TaintedObject("BSPrim.AddForce", delegate() { OMV.Vector3 fSum = OMV.Vector3.Zero; lock (m_accumulatedForces) { - // Sum the accumulated additional forces for one big force to apply once. foreach (OMV.Vector3 v in m_accumulatedForces) { fSum += v; } m_accumulatedForces.Clear(); } - DetailLog("{0},BSPrim.AddForce,taint,force={1}", LocalID, fSum); - if (fSum != OMV.Vector3.Zero) - BulletSimAPI.ApplyCentralForce2(PhysBody.ptr, fSum); + // DetailLog("{0},BSPrim.AddObjectForce,taint,force={1}", LocalID, _force); + BulletSimAPI.AddObjectForce2(Body.Ptr, fSum); }); } - private List m_accumulatedAngularForces = new List(); - public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { - AddAngularForce(force, pushforce, false); + public override void AddAngularForce(OMV.Vector3 force, bool pushforce) { + // DetailLog("{0},BSPrim.AddAngularForce,call,angForce={1},push={2}", LocalID, force, pushforce); + // m_log.DebugFormat("{0}: AddAngularForce. f={1}, push={2}", LogHeader, force, pushforce); } - public void AddAngularForce(OMV.Vector3 force, bool pushforce, bool inTaintTime) - { - if (force.IsFinite()) - { - // _force += force; - lock (m_accumulatedAngularForces) - m_accumulatedAngularForces.Add(new OMV.Vector3(force)); - } - else - { - m_log.WarnFormat("{0}: Got a NaN force applied to a prim. LocalID={1}", LogHeader, LocalID); - return; - } - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.AddAngularForce", delegate() - { - OMV.Vector3 fSum = OMV.Vector3.Zero; - lock (m_accumulatedAngularForces) - { - // Sum the accumulated additional forces for one big force to apply once. - foreach (OMV.Vector3 v in m_accumulatedAngularForces) - { - fSum += v; - } - m_accumulatedAngularForces.Clear(); - } - DetailLog("{0},BSPrim.AddAngularForce,taint,aForce={1}", LocalID, fSum); - if (fSum != OMV.Vector3.Zero) - { - BulletSimAPI.ApplyTorque2(PhysBody.ptr, fSum); - _torque = fSum; - } - }); - } - // A torque impulse. - public void ApplyTorqueImpulse(OMV.Vector3 impulse, bool inTaintTime) - { - OMV.Vector3 applyImpulse = impulse; - PhysicsScene.TaintedObject(inTaintTime, "BSPrim.ApplyTorqueImpulse", delegate() - { - DetailLog("{0},BSPrim.ApplyTorqueImpulse,taint,tImpulse={1}", LocalID, applyImpulse); - BulletSimAPI.ApplyTorqueImpulse2(PhysBody.ptr, applyImpulse); - }); - } - - public override void SetMomentum(OMV.Vector3 momentum) { + public override void SetMomentum(OMV.Vector3 momentum) { // DetailLog("{0},BSPrim.SetMomentum,call,mom={1}", LocalID, momentum); } + public override void SubscribeEvents(int ms) { + _subscribedEventsMs = ms; + if (ms > 0) + { + // make sure first collision happens + _nextCollisionOkTime = Util.EnvironmentTickCount() - _subscribedEventsMs; + + Scene.TaintedObject("BSPrim.SubscribeEvents", delegate() + { + BulletSimAPI.AddToCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } + } + public override void UnSubscribeEvents() { + _subscribedEventsMs = 0; + Scene.TaintedObject("BSPrim.UnSubscribeEvents", delegate() + { + BulletSimAPI.RemoveFromCollisionFlags2(Body.Ptr, CollisionFlags.BS_SUBSCRIBE_COLLISION_EVENTS); + }); + } + public override bool SubscribedEvents() { + return (_subscribedEventsMs > 0); + } + #region Mass Calculation private float CalculateMass() @@ -1017,19 +682,19 @@ public sealed class BSPrim : BSPhysObject float tmp; float returnMass = 0; - float hollowAmount = (float)BaseShape.ProfileHollow * 2.0e-5f; - float hollowVolume = hollowAmount * hollowAmount; - - switch (BaseShape.ProfileShape) + float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; + float hollowVolume = hollowAmount * hollowAmount; + + switch (_pbs.ProfileShape) { case ProfileShape.Square: // default box - if (BaseShape.PathCurve == (byte)Extrusion.Straight) + if (_pbs.PathCurve == (byte)Extrusion.Straight) { if (hollowAmount > 0.0) { - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -1053,19 +718,19 @@ public sealed class BSPrim : BSPhysObject } } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - //a tube + //a tube - volume *= 0.78539816339e-2f * (float)(200 - BaseShape.PathScaleX); - tmp= 1.0f -2.0e-2f * (float)(200 - BaseShape.PathScaleY); + volume *= 0.78539816339e-2f * (float)(200 - _pbs.PathScaleX); + tmp= 1.0f -2.0e-2f * (float)(200 - _pbs.PathScaleY); volume -= volume*tmp*tmp; - + if (hollowAmount > 0.0) { hollowVolume *= hollowAmount; - - switch (BaseShape.HollowShape) + + switch (_pbs.HollowShape) { case HollowShape.Square: case HollowShape.Same: @@ -1090,13 +755,13 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.Circle: - if (BaseShape.PathCurve == (byte)Extrusion.Straight) + if (_pbs.PathCurve == (byte)Extrusion.Straight) { volume *= 0.78539816339f; // elipse base if (hollowAmount > 0.0) { - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1118,19 +783,19 @@ public sealed class BSPrim : BSPhysObject } } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { - volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); + volume *= 0.61685027506808491367715568749226e-2f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); volume *= (1.0f - tmp * tmp); - + if (hollowAmount > 0.0) { // calculate the hollow volume by it's shape compared to the prim shape hollowVolume *= hollowAmount; - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Circle: @@ -1154,7 +819,7 @@ public sealed class BSPrim : BSPhysObject break; case ProfileShape.HalfCircle: - if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + if (_pbs.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.52359877559829887307710723054658f; } @@ -1162,7 +827,7 @@ public sealed class BSPrim : BSPhysObject case ProfileShape.EquilateralTriangle: - if (BaseShape.PathCurve == (byte)Extrusion.Straight) + if (_pbs.PathCurve == (byte)Extrusion.Straight) { volume *= 0.32475953f; @@ -1170,7 +835,7 @@ public sealed class BSPrim : BSPhysObject { // calculate the hollow volume by it's shape compared to the prim shape - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1195,11 +860,11 @@ public sealed class BSPrim : BSPhysObject volume *= (1.0f - hollowVolume); } } - else if (BaseShape.PathCurve == (byte)Extrusion.Curve1) + else if (_pbs.PathCurve == (byte)Extrusion.Curve1) { volume *= 0.32475953f; - volume *= 0.01f * (float)(200 - BaseShape.PathScaleX); - tmp = 1.0f - .02f * (float)(200 - BaseShape.PathScaleY); + volume *= 0.01f * (float)(200 - _pbs.PathScaleX); + tmp = 1.0f - .02f * (float)(200 - _pbs.PathScaleY); volume *= (1.0f - tmp * tmp); if (hollowAmount > 0.0) @@ -1207,7 +872,7 @@ public sealed class BSPrim : BSPhysObject hollowVolume *= hollowAmount; - switch (BaseShape.HollowShape) + switch (_pbs.HollowShape) { case HollowShape.Same: case HollowShape.Triangle: @@ -1247,26 +912,26 @@ public sealed class BSPrim : BSPhysObject float profileBegin; float profileEnd; - if (BaseShape.PathCurve == (byte)Extrusion.Straight || BaseShape.PathCurve == (byte)Extrusion.Flexible) + if (_pbs.PathCurve == (byte)Extrusion.Straight || _pbs.PathCurve == (byte)Extrusion.Flexible) { - taperX1 = BaseShape.PathScaleX * 0.01f; + taperX1 = _pbs.PathScaleX * 0.01f; if (taperX1 > 1.0f) taperX1 = 2.0f - taperX1; taperX = 1.0f - taperX1; - taperY1 = BaseShape.PathScaleY * 0.01f; + taperY1 = _pbs.PathScaleY * 0.01f; if (taperY1 > 1.0f) taperY1 = 2.0f - taperY1; taperY = 1.0f - taperY1; } else { - taperX = BaseShape.PathTaperX * 0.01f; + taperX = _pbs.PathTaperX * 0.01f; if (taperX < 0.0f) taperX = -taperX; taperX1 = 1.0f - taperX; - taperY = BaseShape.PathTaperY * 0.01f; + taperY = _pbs.PathTaperY * 0.01f; if (taperY < 0.0f) taperY = -taperY; taperY1 = 1.0f - taperY; @@ -1276,18 +941,20 @@ public sealed class BSPrim : BSPhysObject volume *= (taperX1 * taperY1 + 0.5f * (taperX1 * taperY + taperX * taperY1) + 0.3333333333f * taperX * taperY); - pathBegin = (float)BaseShape.PathBegin * 2.0e-5f; - pathEnd = 1.0f - (float)BaseShape.PathEnd * 2.0e-5f; + pathBegin = (float)_pbs.PathBegin * 2.0e-5f; + pathEnd = 1.0f - (float)_pbs.PathEnd * 2.0e-5f; volume *= (pathEnd - pathBegin); // this is crude aproximation - profileBegin = (float)BaseShape.ProfileBegin * 2.0e-5f; - profileEnd = 1.0f - (float)BaseShape.ProfileEnd * 2.0e-5f; + profileBegin = (float)_pbs.ProfileBegin * 2.0e-5f; + profileEnd = 1.0f - (float)_pbs.ProfileEnd * 2.0e-5f; volume *= (profileEnd - profileBegin); returnMass = _density * volume; - /* Comment out code that computes the mass of the linkset. That is done in the Linkset class. + /* + * This change means each object keeps its own mass and the Mass property + * will return the sum if we're part of a linkset. if (IsRootOfLinkset) { foreach (BSPrim prim in _childrenPrims) @@ -1300,42 +967,296 @@ public sealed class BSPrim : BSPhysObject if (returnMass <= 0) returnMass = 0.0001f; - if (returnMass > PhysicsScene.MaximumObjectMass) - returnMass = PhysicsScene.MaximumObjectMass; + if (returnMass > _scene.MaximumObjectMass) + returnMass = _scene.MaximumObjectMass; return returnMass; }// end CalculateMass #endregion Mass Calculation - // Rebuild the geometry and object. - // This is called when the shape changes so we need to recreate the mesh/hull. - // Called at taint-time!!! - private void CreateGeomAndObject(bool forceRebuild) + // Create the geometry information in Bullet for later use + // The objects needs a hull if it's physical otherwise a mesh is enough + // No locking here because this is done when we know physics is not simulating + // if 'forceRebuild' is true, the geometry is rebuilt. Otherwise a previously built version is used + // Returns 'true' if the geometry was rebuilt + private bool CreateGeom(bool forceRebuild) { - // If this prim is part of a linkset, we must remove and restore the physical - // links if the body is rebuilt. - bool needToRestoreLinkset = false; - - // Create the correct physical representation for this type of object. - // Updates BSBody and BSShape with the new information. - // Ignore 'forceRebuild'. This routine makes the right choices and changes of necessary. - // Returns 'true' if either the body or the shape was changed. - PhysicsScene.Shapes.GetBodyAndShape(false, PhysicsScene.World, this, null, delegate(BulletBody dBody) + // the mesher thought this was too simple to mesh. Use a native Bullet collision shape. + bool ret = false; + if (!_scene.NeedsMeshing(_pbs)) { - // Called if the current prim body is about to be destroyed. - // Remove all the physical dependencies on the old body. - // (Maybe someday make the changing of BSShape an event handled by BSLinkset.) - needToRestoreLinkset = Linkset.RemoveBodyDependencies(this); - }); - - if (needToRestoreLinkset) + if (_pbs.ProfileShape == ProfileShape.HalfCircle && _pbs.PathCurve == (byte)Extrusion.Curve1) + { + // if (_size.X == _size.Y && _size.Y == _size.Z && _size.X == _size.Z) + // { + // m_log.DebugFormat("{0}: CreateGeom: Defaulting to sphere of size {1}", LogHeader, _size); + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_SPHERE)) + { + // DetailLog("{0},BSPrim.CreateGeom,sphere (force={1}", LocalID, forceRebuild); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_SPHERE; + // Bullet native objects are scaled by the Bullet engine so pass the size in + _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; + } + // } + } + else + { + // m_log.DebugFormat("{0}: CreateGeom: Defaulting to box. lid={1}, type={2}, size={3}", LogHeader, LocalID, _shapeType, _size); + if (forceRebuild || (_shapeType != ShapeData.PhysicsShapeType.SHAPE_BOX)) + { + // DetailLog("{0},BSPrim.CreateGeom,box (force={1})", LocalID, forceRebuild); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_BOX; + _scale = _size; + // TODO: do we need to check for and destroy a mesh or hull that might have been left from before? + ret = true; + } + } + } + else { - // If physical body dependencies were removed, restore them - Linkset.RestoreBodyDependencies(this); + if (IsPhysical) + { + if (forceRebuild || _hullKey == 0) + { + // physical objects require a hull for interaction. + // This will create the mesh if it doesn't already exist + CreateGeomHull(); + ret = true; + } + } + else + { + if (forceRebuild || _meshKey == 0) + { + // Static (non-physical) objects only need a mesh for bumping into + CreateGeomMesh(); + ret = true; + } + } + } + return ret; + } + + // No locking here because this is done when we know physics is not simulating + private void CreateGeomMesh() + { + float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; + ulong newMeshKey = (ulong)_pbs.GetMeshKey(_size, lod); + // m_log.DebugFormat("{0}: CreateGeomMesh: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _meshKey, newMeshKey); + + // if this new shape is the same as last time, don't recreate the mesh + if (_meshKey == newMeshKey) return; + + // DetailLog("{0},BSPrim.CreateGeomMesh,create,key={1}", LocalID, newMeshKey); + // Since we're recreating new, get rid of any previously generated shape + if (_meshKey != 0) + { + // m_log.DebugFormat("{0}: CreateGeom: deleting old mesh. lID={1}, Key={2}", LogHeader, _localID, _meshKey); + // DetailLog("{0},BSPrim.CreateGeomMesh,deleteOld,key={1}", LocalID, _meshKey); + BulletSimAPI.DestroyMesh(_scene.WorldID, _meshKey); + _mesh = null; + _meshKey = 0; } - // Make sure the properties are set on the new object - UpdatePhysicalParameters(); + _meshKey = newMeshKey; + // always pass false for physicalness as this creates some sort of bounding box which we don't need + _mesh = _scene.mesher.CreateMesh(_avName, _pbs, _size, lod, false); + + int[] indices = _mesh.getIndexListAsInt(); + List vertices = _mesh.getVertexList(); + + float[] verticesAsFloats = new float[vertices.Count * 3]; + int vi = 0; + foreach (OMV.Vector3 vv in vertices) + { + verticesAsFloats[vi++] = vv.X; + verticesAsFloats[vi++] = vv.Y; + verticesAsFloats[vi++] = vv.Z; + } + + // m_log.DebugFormat("{0}: CreateGeomMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", + // LogHeader, _localID, _meshKey, indices.Length, vertices.Count); + BulletSimAPI.CreateMesh(_scene.WorldID, _meshKey, indices.GetLength(0), indices, + vertices.Count, verticesAsFloats); + + _shapeType = ShapeData.PhysicsShapeType.SHAPE_MESH; + // meshes are already scaled by the meshmerizer + _scale = new OMV.Vector3(1f, 1f, 1f); + // DetailLog("{0},BSPrim.CreateGeomMesh,done", LocalID); + return; + } + + // No locking here because this is done when we know physics is not simulating + private void CreateGeomHull() + { + float lod = _pbs.SculptEntry ? _scene.SculptLOD : _scene.MeshLOD; + ulong newHullKey = (ulong)_pbs.GetMeshKey(_size, lod); + // m_log.DebugFormat("{0}: CreateGeomHull: lID={1}, oldKey={2}, newKey={3}", LogHeader, _localID, _hullKey, newHullKey); + + // if the hull hasn't changed, don't rebuild it + if (newHullKey == _hullKey) return; + + // DetailLog("{0},BSPrim.CreateGeomHull,create,oldKey={1},newKey={2}", LocalID, _hullKey, newHullKey); + + // Since we're recreating new, get rid of any previously generated shape + if (_hullKey != 0) + { + // m_log.DebugFormat("{0}: CreateGeom: deleting old hull. Key={1}", LogHeader, _hullKey); + // DetailLog("{0},BSPrim.CreateGeomHull,deleteOldHull,key={1}", LocalID, _hullKey); + BulletSimAPI.DestroyHull(_scene.WorldID, _hullKey); + _hullKey = 0; + } + + _hullKey = newHullKey; + + // Make sure the underlying mesh exists and is correct + CreateGeomMesh(); + + int[] indices = _mesh.getIndexListAsInt(); + List vertices = _mesh.getVertexList(); + + //format conversion from IMesh format to DecompDesc format + List convIndices = new List(); + List convVertices = new List(); + for (int ii = 0; ii < indices.GetLength(0); ii++) + { + convIndices.Add(indices[ii]); + } + foreach (OMV.Vector3 vv in vertices) + { + convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); + } + + // setup and do convex hull conversion + _hulls = new List(); + DecompDesc dcomp = new DecompDesc(); + dcomp.mIndices = convIndices; + dcomp.mVertices = convVertices; + ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); + // create the hull into the _hulls variable + convexBuilder.process(dcomp); + + // Convert the vertices and indices for passing to unmanaged. + // The hull information is passed as a large floating point array. + // The format is: + // convHulls[0] = number of hulls + // convHulls[1] = number of vertices in first hull + // convHulls[2] = hull centroid X coordinate + // convHulls[3] = hull centroid Y coordinate + // convHulls[4] = hull centroid Z coordinate + // convHulls[5] = first hull vertex X + // convHulls[6] = first hull vertex Y + // convHulls[7] = first hull vertex Z + // convHulls[8] = second hull vertex X + // ... + // convHulls[n] = number of vertices in second hull + // convHulls[n+1] = second hull centroid X coordinate + // ... + // + // TODO: is is very inefficient. Someday change the convex hull generator to return + // data structures that do not need to be converted in order to pass to Bullet. + // And maybe put the values directly into pinned memory rather than marshaling. + int hullCount = _hulls.Count; + int totalVertices = 1; // include one for the count of the hulls + foreach (ConvexResult cr in _hulls) + { + totalVertices += 4; // add four for the vertex count and centroid + totalVertices += cr.HullIndices.Count * 3; // we pass just triangles + } + float[] convHulls = new float[totalVertices]; + + convHulls[0] = (float)hullCount; + int jj = 1; + foreach (ConvexResult cr in _hulls) + { + // copy vertices for index access + float3[] verts = new float3[cr.HullVertices.Count]; + int kk = 0; + foreach (float3 ff in cr.HullVertices) + { + verts[kk++] = ff; + } + + // add to the array one hull's worth of data + convHulls[jj++] = cr.HullIndices.Count; + convHulls[jj++] = 0f; // centroid x,y,z + convHulls[jj++] = 0f; + convHulls[jj++] = 0f; + foreach (int ind in cr.HullIndices) + { + convHulls[jj++] = verts[ind].x; + convHulls[jj++] = verts[ind].y; + convHulls[jj++] = verts[ind].z; + } + } + + // create the hull definition in Bullet + // m_log.DebugFormat("{0}: CreateGeom: calling CreateHull. lid={1}, key={2}, hulls={3}", LogHeader, _localID, _hullKey, hullCount); + BulletSimAPI.CreateHull(_scene.WorldID, _hullKey, hullCount, convHulls); + _shapeType = ShapeData.PhysicsShapeType.SHAPE_HULL; + // meshes are already scaled by the meshmerizer + _scale = new OMV.Vector3(1f, 1f, 1f); + // DetailLog("{0},BSPrim.CreateGeomHull,done", LocalID); + return; + } + + // Callback from convex hull creater with a newly created hull. + // Just add it to the collection of hulls for this shape. + private void HullReturn(ConvexResult result) + { + _hulls.Add(result); + return; + } + + // Create an object in Bullet if it has not already been created + // No locking here because this is done when the physics engine is not simulating + // Returns 'true' if an object was actually created. + private bool CreateObject() + { + // this routine is called when objects are rebuilt. + + // the mesh or hull must have already been created in Bullet + ShapeData shape; + FillShapeInfo(out shape); + // m_log.DebugFormat("{0}: CreateObject: lID={1}, shape={2}", LogHeader, _localID, shape.Type); + bool ret = BulletSimAPI.CreateObject(_scene.WorldID, shape); + + // the CreateObject() may have recreated the rigid body. Make sure we have the latest. + Body = new BulletBody(LocalID, BulletSimAPI.GetBodyHandle2(_scene.World.Ptr, LocalID)); + + return ret; + } + + // Copy prim's info into the BulletSim shape description structure + public void FillShapeInfo(out ShapeData shape) + { + shape.ID = _localID; + shape.Type = _shapeType; + shape.Position = _position; + shape.Rotation = _orientation; + shape.Velocity = _velocity; + shape.Scale = _scale; + shape.Mass = _isPhysical ? _mass : 0f; + shape.Buoyancy = _buoyancy; + shape.HullKey = _hullKey; + shape.MeshKey = _meshKey; + shape.Friction = _friction; + shape.Restitution = _restitution; + shape.Collidable = (!IsPhantom) ? ShapeData.numericTrue : ShapeData.numericFalse; + shape.Static = _isPhysical ? ShapeData.numericFalse : ShapeData.numericTrue; + } + + + // Rebuild the geometry and object. + // This is called when the shape changes so we need to recreate the mesh/hull. + // No locking here because this is done when the physics engine is not simulating + private void RecreateGeomAndObject() + { + // m_log.DebugFormat("{0}: RecreateGeomAndObject. lID={1}", LogHeader, _localID); + if (CreateGeom(true)) + CreateObject(); return; } @@ -1356,7 +1277,7 @@ public sealed class BSPrim : BSPhysObject const float ACCELERATION_TOLERANCE = 0.01f; const float ROTATIONAL_VELOCITY_TOLERANCE = 0.01f; - public override void UpdateProperties(EntityProperties entprop) + public void UpdateProperties(EntityProperties entprop) { /* UpdatedProperties changed = 0; @@ -1404,7 +1325,7 @@ public sealed class BSPrim : BSPhysObject // Don't check for damping here -- it's done in BulletSim and SceneObjectPart. // Updates only for individual prims and for the root object of a linkset. - if (Linkset.IsRoot(this)) + if (_linkset.IsRoot(this)) { // Assign to the local variables so the normal set action does not happen _position = entprop.Position; @@ -1413,32 +1334,69 @@ public sealed class BSPrim : BSPhysObject _acceleration = entprop.Acceleration; _rotationalVelocity = entprop.RotationalVelocity; - // remember the current and last set values - LastEntityProperties = CurrentEntityProperties; - CurrentEntityProperties = entprop; - - PositionSanityCheck(true); - - OMV.Vector3 direction = OMV.Vector3.UnitX * _orientation; - DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},dir={3},vel={4},rotVel={5}", - LocalID, _position, _orientation, direction, _velocity, _rotationalVelocity); - - // BulletSimAPI.DumpRigidBody2(PhysicsScene.World.ptr, BSBody.ptr); // DEBUG DEBUG DEBUG + // m_log.DebugFormat("{0}: RequestTerseUpdate. id={1}, ch={2}, pos={3}, rot={4}, vel={5}, acc={6}, rvel={7}", + // LogHeader, LocalID, changed, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); + // DetailLog("{0},BSPrim.UpdateProperties,call,pos={1},orient={2},vel={3},accel={4},rotVel={5}", + // LocalID, _position, _orientation, _velocity, _acceleration, _rotationalVelocity); base.RequestPhysicsterseUpdate(); } /* else { - // For debugging, report the movement of children + // For debugging, we also report the movement of children DetailLog("{0},BSPrim.UpdateProperties,child,pos={1},orient={2},vel={3},accel={4},rotVel={5}", - LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, + LocalID, entprop.Position, entprop.Rotation, entprop.Velocity, entprop.Acceleration, entprop.RotationalVelocity); } */ + } - // The linkset implimentation might want to know about this. - Linkset.UpdateProperties(this); + // I've collided with something + CollisionEventUpdate collisionCollection; + public void Collide(uint collidingWith, ActorTypes type, OMV.Vector3 contactPoint, OMV.Vector3 contactNormal, float pentrationDepth) + { + // m_log.DebugFormat("{0}: Collide: ms={1}, id={2}, with={3}", LogHeader, _subscribedEventsMs, LocalID, collidingWith); + + // The following lines make IsColliding() and IsCollidingGround() work + _collidingStep = _scene.SimulationStep; + if (collidingWith == BSScene.TERRAIN_ID || collidingWith == BSScene.GROUNDPLANE_ID) + { + _collidingGroundStep = _scene.SimulationStep; + } + + // DetailLog("{0},BSPrim.Collison,call,with={1}", LocalID, collidingWith); + + // if someone is subscribed to collision events.... + if (_subscribedEventsMs != 0) { + // throttle the collisions to the number of milliseconds specified in the subscription + int nowTime = _scene.SimulationNowTime; + if (nowTime >= _nextCollisionOkTime) { + _nextCollisionOkTime = nowTime + _subscribedEventsMs; + + if (collisionCollection == null) + collisionCollection = new CollisionEventUpdate(); + collisionCollection.AddCollider(collidingWith, new ContactPoint(contactPoint, contactNormal, pentrationDepth)); + } + } + } + + // The scene is telling us it's time to pass our collected collisions into the simulator + public void SendCollisions() + { + if (collisionCollection != null && collisionCollection.Count > 0) + { + base.SendCollisionUpdate(collisionCollection); + // The collisionCollection structure is passed around in the simulator. + // Make sure we don't have a handle to that one and that a new one is used next time. + collisionCollection = null; + } + } + + // Invoke the detailed logger and output something if it's enabled. + private void DetailLog(string msg, params Object[] args) + { + Scene.PhysicsLogging.Write(msg, args); } } } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs index 740f339241..a31c57846d 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSScene.cs @@ -39,88 +39,96 @@ using log4net; using OpenMetaverse; // TODOs for BulletSim (for BSScene, BSPrim, BSCharacter and BulletSim) -// Test sculpties (verified that they don't work) +// Debug linkset +// Test with multiple regions in one simulator +// Adjust character capsule size when height is adjusted (ScenePresence.SetHeight) +// Test sculpties // Compute physics FPS reasonably // Based on material, set density and friction -// Don't use constraints in linksets of non-physical objects. Means having to move children manually. +// More efficient memory usage when passing hull information from BSPrim to BulletSim +// Move all logic out of the C++ code and into the C# code for easier future modifications. // Four states of prim: Physical, regular, phantom and selected. Are we modeling these correctly? // In SL one can set both physical and phantom (gravity, does not effect others, makes collisions with ground) // At the moment, physical and phantom causes object to drop through the terrain // Physical phantom objects and related typing (collision options ) +// Use collision masks for collision with terrain and phantom objects // Check out llVolumeDetect. Must do something for that. -// Use collision masks for collision with terrain and phantom objects -// More efficient memory usage when passing hull information from BSPrim to BulletSim // Should prim.link() and prim.delink() membership checking happen at taint time? -// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once. +// changing the position and orientation of a linked prim must rebuild the constraint with the root. +// Mesh sharing. Use meshHash to tell if we already have a hull of that shape and only create once // Do attachments need to be handled separately? Need collision events. Do not collide with VolumeDetect +// Implement the genCollisions feature in BulletSim::SetObjectProperties (don't pass up unneeded collisions) // Implement LockAngularMotion // Decide if clearing forces is the right thing to do when setting position (BulletSim::SetObjectTranslation) +// Does NeedsMeshing() really need to exclude all the different shapes? // Remove mesh and Hull stuff. Use mesh passed to bullet and use convexdecom from bullet. // Add PID movement operations. What does ScenePresence.MoveToTarget do? // Check terrain size. 128 or 127? // Raycast -// +// namespace OpenSim.Region.Physics.BulletSPlugin { -public sealed class BSScene : PhysicsScene, IPhysicsParameters +public class BSScene : PhysicsScene, IPhysicsParameters { private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[BULLETS SCENE]"; - // The name of the region we're working for. - public string RegionName { get; private set; } + public void DebugLog(string mm, params Object[] xx) { if (ShouldDebugLog) m_log.DebugFormat(mm, xx); } public string BulletSimVersion = "?"; - public Dictionary PhysObjects; - public BSShapeCollection Shapes; - - // Keeping track of the objects with collisions so we can report begin and end of a collision - public HashSet ObjectsWithCollisions = new HashSet(); - public HashSet ObjectsWithNoMoreCollisions = new HashSet(); - // Keep track of all the avatars so we can send them a collision event - // every tick so OpenSim will update its animation. - private HashSet m_avatars = new HashSet(); - - // List of all the objects that have vehicle properties and should be called - // to update each physics step. - private List m_vehicles = new List(); + private Dictionary m_avatars = new Dictionary(); + private Dictionary m_prims = new Dictionary(); + private HashSet m_avatarsWithCollisions = new HashSet(); + private HashSet m_primsWithCollisions = new HashSet(); + private List m_vehicles = new List(); + private float[] m_heightMap; + private float m_waterLevel; + private uint m_worldID; + public uint WorldID { get { return m_worldID; } } // let my minuions use my logger public ILog Logger { get { return m_log; } } + private bool m_initialized = false; + + private int m_detailedStatsStep = 0; + public IMesher mesher; - // Level of Detail values kept as float because that's what the Meshmerizer wants - public float MeshLOD { get; private set; } - public float MeshMegaPrimLOD { get; private set; } - public float MeshMegaPrimThreshold { get; private set; } - public float SculptLOD { get; private set; } + private float m_meshLOD; + public float MeshLOD + { + get { return m_meshLOD; } + } + private float m_sculptLOD; + public float SculptLOD + { + get { return m_sculptLOD; } + } - public uint WorldID { get; private set; } - public BulletSim World { get; private set; } + private BulletSim m_worldSim; + public BulletSim World + { + get { return m_worldSim; } + } + private BSConstraintCollection m_constraintCollection; + public BSConstraintCollection Constraints + { + get { return m_constraintCollection; } + } - // All the constraints that have been allocated in this instance. - public BSConstraintCollection Constraints { get; private set; } - - // Simulation parameters private int m_maxSubSteps; private float m_fixedTimeStep; private long m_simulationStep = 0; public long SimulationStep { get { return m_simulationStep; } } - private int m_taintsToProcessPerStep; + + public float LastSimulatedTimestep { get; private set; } // A value of the time now so all the collision and update routines do not have to get their own // Set to 'now' just before all the prims and actors are called for collisions and updates - public int SimulationNowTime { get; private set; } + private int m_simulationNowTime; + public int SimulationNowTime { get { return m_simulationNowTime; } } - // True if initialized and ready to do simulation steps - private bool m_initialized = false; - - // Flag which is true when processing taints. - // Not guaranteed to be correct all the time (don't depend on this) but good for debugging. - public bool InTaintTime { get; private set; } - - // Pinned memory used to pass step information between managed and unmanaged private int m_maxCollisionsPerFrame; private CollisionDesc[] m_collisionArray; private GCHandle m_collisionArrayPinnedHandle; @@ -129,19 +137,14 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters private EntityProperties[] m_updateArray; private GCHandle m_updateArrayPinnedHandle; - public bool ShouldMeshSculptedPrim { get; private set; } // cause scuplted prims to get meshed - public bool ShouldForceSimplePrimMeshing { get; private set; } // if a cube or sphere, let Bullet do internal shapes - public bool ShouldUseHullsForPhysicalObjects { get; private set; } // 'true' if should create hulls for physical objects + private bool _meshSculptedPrim = true; // cause scuplted prims to get meshed + private bool _forceSimplePrimMeshing = false; // if a cube or sphere, let Bullet do internal shapes public float PID_D { get; private set; } // derivative public float PID_P { get; private set; } // proportional public const uint TERRAIN_ID = 0; // OpenSim senses terrain with a localID of zero public const uint GROUNDPLANE_ID = 1; - public const uint CHILDTERRAIN_ID = 2; // Terrain allocated based on our mega-prim childre start here - - private float m_waterLevel; - public BSTerrainManager TerrainManager { get; private set; } public ConfigurationParameters Params { @@ -151,18 +154,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { get { return new Vector3(0f, 0f, Params.gravity); } } - // Just the Z value of the gravity - public float DefaultGravityZ + + private float m_maximumObjectMass; + public float MaximumObjectMass { - get { return Params.gravity; } + get { return m_maximumObjectMass; } } - public float MaximumObjectMass { get; private set; } - - // When functions in the unmanaged code must be called, it is only - // done at a known time just before the simulation step. The taint - // system saves all these function calls and executes them in - // order before the simulation. public delegate void TaintCallback(); private struct TaintCallbackEntry { @@ -174,19 +172,15 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters callback = c; } } - private Object _taintLock = new Object(); // lock for using the next object - private List _taintOperations; - private Dictionary _postTaintOperations; - private List _postStepOperations; + private List _taintedObjects; + private Object _taintLock = new Object(); // A pointer to an instance if this structure is passed to the C++ code - // Used to pass basic configuration values to the unmanaged code. ConfigurationParameters[] m_params; GCHandle m_paramsHandle; - // Handle to the callback used by the unmanaged code to call into the managed code. - // Used for debug logging. - // Need to store the handle in a persistant variable so it won't be freed. + public bool ShouldDebugLog { get; private set; } + private BulletSimAPI.DebugLogCallback m_DebugLogCallbackHandle; // Sometimes you just have to log everything. @@ -195,26 +189,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters private string m_physicsLoggingDir; private string m_physicsLoggingPrefix; private int m_physicsLoggingFileMinutes; - // 'true' of the vehicle code is to log lots of details - public bool VehicleLoggingEnabled { get; private set; } - #region Construction and Initialization + private bool m_vehicleLoggingEnabled; + public bool VehicleLoggingEnabled { get { return m_vehicleLoggingEnabled; } } + public BSScene(string identifier) { m_initialized = false; - // we are passed the name of the region we're working for. - RegionName = identifier; } public override void Initialise(IMesher meshmerizer, IConfigSource config) { - mesher = meshmerizer; - _taintOperations = new List(); - _postTaintOperations = new Dictionary(); - _postStepOperations = new List(); - PhysObjects = new Dictionary(); - Shapes = new BSShapeCollection(this); - // Allocate pinned memory to pass parameters. m_params = new ConfigurationParameters[1]; m_paramsHandle = GCHandle.Alloc(m_params, GCHandleType.Pinned); @@ -230,7 +215,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Enable very detailed logging. // By creating an empty logger when not logging, the log message invocation code - // can be left in and every call doesn't have to check for null. + // can be left in and every call doesn't have to check for null. if (m_physicsLoggingEnabled) { PhysicsLogging = new Logging.LogWriter(m_physicsLoggingDir, m_physicsLoggingPrefix, m_physicsLoggingFileMinutes); @@ -240,43 +225,39 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters PhysicsLogging = new Logging.LogWriter(); } - // If Debug logging level, enable logging from the unmanaged code - m_DebugLogCallbackHandle = null; - if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) - { - m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); - if (PhysicsLogging.Enabled) - // The handle is saved in a variable to make sure it doesn't get freed after this call - m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); - else - m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); - } - // Get the version of the DLL // TODO: this doesn't work yet. Something wrong with marshaling the returned string. // BulletSimVersion = BulletSimAPI.GetVersion(); // m_log.WarnFormat("{0}: BulletSim.dll version='{1}'", LogHeader, BulletSimVersion); - // The bounding box for the simulated world. The origin is 0,0,0 unless we're - // a child in a mega-region. - // Bullet actually doesn't care about the extents of the simulated - // area. It tracks active objects no matter where they are. - Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); + // if Debug, enable logging from the unmanaged code + if (m_log.IsDebugEnabled || PhysicsLogging.Enabled) + { + m_log.DebugFormat("{0}: Initialize: Setting debug callback for unmanaged code", LogHeader); + if (PhysicsLogging.Enabled) + m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLoggerPhysLog); + else + m_DebugLogCallbackHandle = new BulletSimAPI.DebugLogCallback(BulletLogger); + // the handle is saved in a variable to make sure it doesn't get freed after this call + BulletSimAPI.SetDebugLogCallback(m_DebugLogCallbackHandle); + } + + _taintedObjects = new List(); + + mesher = meshmerizer; + // The bounding box for the simulated world + Vector3 worldExtent = new Vector3(Constants.RegionSize, Constants.RegionSize, 8192f); // m_log.DebugFormat("{0}: Initialize: Calling BulletSimAPI.Initialize.", LogHeader); - World = new BulletSim(0, this, BulletSimAPI.Initialize2(worldExtent, m_paramsHandle.AddrOfPinnedObject(), + m_worldID = BulletSimAPI.Initialize(worldExtent, m_paramsHandle.AddrOfPinnedObject(), m_maxCollisionsPerFrame, m_collisionArrayPinnedHandle.AddrOfPinnedObject(), - m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject(), - m_DebugLogCallbackHandle)); + m_maxUpdatesPerFrame, m_updateArrayPinnedHandle.AddrOfPinnedObject()); - Constraints = new BSConstraintCollection(World); + // Initialization to support the transition to a new API which puts most of the logic + // into the C# code so it is easier to modify and add to. + m_worldSim = new BulletSim(m_worldID, this, BulletSimAPI.GetSimHandle2(m_worldID)); + m_constraintCollection = new BSConstraintCollection(World); - TerrainManager = new BSTerrainManager(this); - TerrainManager.CreateInitialGroundPlaneAndTerrain(); - - m_log.WarnFormat("{0} Linksets implemented with {1}", LogHeader, (BSLinkset.LinksetImplementation)Params.linksetImplementation); - - InTaintTime = false; m_initialized = true; } @@ -300,13 +281,10 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Very detailed logging for physics debugging m_physicsLoggingEnabled = pConfig.GetBoolean("PhysicsLoggingEnabled", false); m_physicsLoggingDir = pConfig.GetString("PhysicsLoggingDir", "."); - m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-%REGIONNAME%-"); + m_physicsLoggingPrefix = pConfig.GetString("PhysicsLoggingPrefix", "physics-"); m_physicsLoggingFileMinutes = pConfig.GetInt("PhysicsLoggingFileMinutes", 5); // Very detailed logging for vehicle debugging - VehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); - - // Do any replacements in the parameters - m_physicsLoggingPrefix = m_physicsLoggingPrefix.Replace("%REGIONNAME%", RegionName); + m_vehicleLoggingEnabled = pConfig.GetBoolean("VehicleLoggingEnabled", false); } } } @@ -331,51 +309,13 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { m_log.Debug("[BULLETS UNMANAGED]:" + msg); } - + // Called directly from unmanaged code so don't do much private void BulletLoggerPhysLog(string msg) { - DetailLog("[BULLETS UNMANAGED]:" + msg); + PhysicsLogging.Write("[BULLETS UNMANAGED]:" + msg); } - public override void Dispose() - { - // m_log.DebugFormat("{0}: Dispose()", LogHeader); - - // make sure no stepping happens while we're deleting stuff - m_initialized = false; - - TerrainManager.ReleaseGroundPlaneAndTerrain(); - - foreach (KeyValuePair kvp in PhysObjects) - { - kvp.Value.Destroy(); - } - PhysObjects.Clear(); - - // Now that the prims are all cleaned up, there should be no constraints left - if (Constraints != null) - { - Constraints.Dispose(); - Constraints = null; - } - - if (Shapes != null) - { - Shapes.Dispose(); - Shapes = null; - } - - // Anything left in the unmanaged code should be cleaned out - BulletSimAPI.Shutdown2(World.ptr); - - // Not logging any more - PhysicsLogging.Close(); - } - #endregion // Construction and Initialization - - #region Prim and Avatar addition and removal - public override PhysicsActor AddAvatar(string avName, Vector3 position, Vector3 size, bool isFlying) { m_log.ErrorFormat("{0}: CALL TO AddAvatar in BSScene. NOT IMPLEMENTED", LogHeader); @@ -389,13 +329,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return null; BSCharacter actor = new BSCharacter(localID, avName, this, position, size, isFlying); - lock (PhysObjects) PhysObjects.Add(localID, actor); - - // TODO: Remove kludge someday. - // We must generate a collision for avatars whether they collide or not. - // This is required by OpenSim to update avatar animations, etc. - lock (m_avatars) m_avatars.Add(actor); - + lock (m_avatars) m_avatars.Add(localID, actor); return actor; } @@ -410,9 +344,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { try { - lock (PhysObjects) PhysObjects.Remove(actor.LocalID); - // Remove kludge someday - lock (m_avatars) m_avatars.Remove(bsactor); + lock (m_avatars) m_avatars.Remove(actor.LocalID); } catch (Exception e) { @@ -430,11 +362,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters BSPrim bsprim = prim as BSPrim; if (bsprim != null) { - DetailLog("{0},RemovePrim,call", bsprim.LocalID); + // DetailLog("{0},RemovePrim,call", bsprim.LocalID); // m_log.DebugFormat("{0}: RemovePrim. id={1}/{2}", LogHeader, bsprim.Name, bsprim.LocalID); try { - lock (PhysObjects) PhysObjects.Remove(bsprim.LocalID); + lock (m_prims) m_prims.Remove(bsprim.LocalID); } catch (Exception e) { @@ -456,21 +388,18 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return null; - DetailLog("{0},AddPrimShape,call", localID); + // DetailLog("{0},AddPrimShape,call", localID); BSPrim prim = new BSPrim(localID, primName, this, position, size, rotation, pbs, isPhysical); - lock (PhysObjects) PhysObjects.Add(localID, prim); + lock (m_prims) m_prims.Add(localID, prim); return prim; } // This is a call from the simulator saying that some physical property has been updated. - // The BulletSim driver senses the changing of relevant properties so this taint + // The BulletSim driver senses the changing of relevant properties so this taint // information call is not needed. public override void AddPhysicsActorTaint(PhysicsActor prim) { } - #endregion // Prim and Avatar addition and removal - - #region Simulation // Simulate one timestep public override float Simulate(float timeStep) { @@ -479,45 +408,34 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters int collidersCount = 0; IntPtr collidersPtr; - int beforeTime = 0; - int simTime = 0; + LastSimulatedTimestep = timeStep; // prevent simulation until we've been initialized - if (!m_initialized) return 5.0f; + if (!m_initialized) return 10.0f; + + int simulateStartTime = Util.EnvironmentTickCount(); // update the prim states while we know the physics engine is not busy - int numTaints = _taintOperations.Count; ProcessTaints(); // Some of the prims operate with special vehicle properties ProcessVehicles(timeStep); - numTaints += _taintOperations.Count; ProcessTaints(); // the vehicles might have added taints // step the physical world one interval m_simulationStep++; int numSubSteps = 0; - try { - // DumpVehicles(); // DEBUG - if (PhysicsLogging.Enabled) beforeTime = Util.EnvironmentTickCount(); - - numSubSteps = BulletSimAPI.PhysicsStep2(World.ptr, timeStep, m_maxSubSteps, m_fixedTimeStep, + numSubSteps = BulletSimAPI.PhysicsStep(m_worldID, timeStep, m_maxSubSteps, m_fixedTimeStep, out updatedEntityCount, out updatedEntitiesPtr, out collidersCount, out collidersPtr); - - if (PhysicsLogging.Enabled) simTime = Util.EnvironmentTickCountSubtract(beforeTime); - DetailLog("{0},Simulate,call, frame={1}, nTaints={2}, simTime={3}, substeps={4}, updates={5}, colliders={6}", - DetailLogZero, m_simulationStep, numTaints, simTime, numSubSteps, updatedEntityCount, collidersCount); - // DumpVehicles(); // DEBUG + // DetailLog("{0},Simulate,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); } catch (Exception e) { - m_log.WarnFormat("{0},PhysicsStep Exception: nTaints={1}, substeps={2}, updates={3}, colliders={4}, e={5}", - LogHeader, numTaints, numSubSteps, updatedEntityCount, collidersCount, e); - DetailLog("{0},PhysicsStepException,call, nTaints={1}, substeps={2}, updates={3}, colliders={4}", - DetailLogZero, numTaints, numSubSteps, updatedEntityCount, collidersCount); - updatedEntityCount = 0; + m_log.WarnFormat("{0},PhysicsStep Exception: substeps={1}, updates={2}, colliders={3}, e={4}", LogHeader, numSubSteps, updatedEntityCount, collidersCount, e); + // DetailLog("{0},PhysicsStepException,call, substeps={1}, updates={2}, colliders={3}", DetailLogZero, numSubSteps, updatedEntityCount, collidersCount); + // updatedEntityCount = 0; collidersCount = 0; } @@ -525,7 +443,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // Don't have to use the pointers passed back since we know it is the same pinned memory we passed in // Get a value for 'now' so all the collision and update routines don't have to get their own - SimulationNowTime = Util.EnvironmentTickCount(); + m_simulationNowTime = Util.EnvironmentTickCount(); // If there were collisions, process them by sending the event to the prim. // Collisions must be processed before updates. @@ -544,32 +462,19 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // The above SendCollision's batch up the collisions on the objects. // Now push the collisions into the simulator. - if (ObjectsWithCollisions.Count > 0) - { - foreach (BSPhysObject bsp in ObjectsWithCollisions) - if (!bsp.SendCollisions()) - { - // If the object is done colliding, see that it's removed from the colliding list - ObjectsWithNoMoreCollisions.Add(bsp); - } - } + foreach (BSPrim bsp in m_primsWithCollisions) + bsp.SendCollisions(); + m_primsWithCollisions.Clear(); - // This is a kludge to get avatar movement updates. - // The simulator expects collisions for avatars even if there are have been no collisions. - // The event updates avatar animations and stuff. - // If you fix avatar animation updates, remove this overhead and let normal collision processing happen. - foreach (BSPhysObject bsp in m_avatars) - if (!ObjectsWithCollisions.Contains(bsp)) // don't call avatars twice - bsp.SendCollisions(); - - // Objects that are done colliding are removed from the ObjectsWithCollisions list. - // Not done above because it is inside an iteration of ObjectWithCollisions. - if (ObjectsWithNoMoreCollisions.Count > 0) - { - foreach (BSPhysObject po in ObjectsWithNoMoreCollisions) - ObjectsWithCollisions.Remove(po); - ObjectsWithNoMoreCollisions.Clear(); - } + // This is a kludge to get avatar movement updated. + // Don't send collisions only if there were collisions -- send everytime. + // ODE sends collisions even if there are none and this is used to update + // avatar animations and stuff. + // foreach (BSCharacter bsc in m_avatarsWithCollisions) + // bsc.SendCollisions(); + foreach (KeyValuePair kvp in m_avatars) + kvp.Value.SendCollisions(); + m_avatarsWithCollisions.Clear(); // If any of the objects had updated properties, tell the object it has been changed by the physics engine if (updatedEntityCount > 0) @@ -577,103 +482,144 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters for (int ii = 0; ii < updatedEntityCount; ii++) { EntityProperties entprop = m_updateArray[ii]; - BSPhysObject pobj; - if (PhysObjects.TryGetValue(entprop.ID, out pobj)) + BSPrim prim; + if (m_prims.TryGetValue(entprop.ID, out prim)) { - pobj.UpdateProperties(entprop); + prim.UpdateProperties(entprop); + continue; + } + BSCharacter actor; + if (m_avatars.TryGetValue(entprop.ID, out actor)) + { + actor.UpdateProperties(entprop); + continue; } } } - ProcessPostStepTaints(); + // If enabled, call into the physics engine to dump statistics + if (m_detailedStatsStep > 0) + { + if ((m_simulationStep % m_detailedStatsStep) == 0) + { + BulletSimAPI.DumpBulletStatistics(); + } + } - // This causes the unmanaged code to output ALL the values found in ALL the objects in the world. - // Only enable this in a limited test world with few objects. - // BulletSimAPI.DumpAllInfo2(World.ptr); // DEBUG DEBUG DEBUG + // this is a waste since the outside routine also calcuates the physics simulation + // period. TODO: There should be a way of computing physics frames from simulator computation. + // long simulateTotalTime = Util.EnvironmentTickCountSubtract(simulateStartTime); + // return (timeStep * (float)simulateTotalTime); - // The physics engine returns the number of milliseconds it simulated this call. - // These are summed and normalized to one second and divided by 1000 to give the reported physics FPS. - // We multiply by 55 to give a recognizable running rate (55 or less). - return numSubSteps * m_fixedTimeStep * 1000 * 55; - // return timeStep * 1000 * 55; + // TODO: FIX THIS: fps calculation possibly wrong. + // This calculation says 1/timeStep is the ideal frame rate. Any time added to + // that by the physics simulation gives a slower frame rate. + long totalSimulationTime = Util.EnvironmentTickCountSubtract(simulateStartTime); + if (totalSimulationTime >= timeStep) + return 0; + return 1f / (timeStep + totalSimulationTime); } // Something has collided - private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penetration) + private void SendCollision(uint localID, uint collidingWith, Vector3 collidePoint, Vector3 collideNormal, float penitration) { - if (localID <= TerrainManager.HighestTerrainID) + if (localID == TERRAIN_ID || localID == GROUNDPLANE_ID) { return; // don't send collisions to the terrain } - BSPhysObject collider; - if (!PhysObjects.TryGetValue(localID, out collider)) - { - // If the object that is colliding cannot be found, just ignore the collision. - DetailLog("{0},BSScene.SendCollision,colliderNotInObjectList,id={1},with={2}", DetailLogZero, localID, collidingWith); + ActorTypes type = ActorTypes.Prim; + if (collidingWith == TERRAIN_ID || collidingWith == GROUNDPLANE_ID) + type = ActorTypes.Ground; + else if (m_avatars.ContainsKey(collidingWith)) + type = ActorTypes.Agent; + + BSPrim prim; + if (m_prims.TryGetValue(localID, out prim)) { + prim.Collide(collidingWith, type, collidePoint, collideNormal, penitration); + m_primsWithCollisions.Add(prim); return; } - - // The terrain is not in the physical object list so 'collidee' can be null when Collide() is called. - BSPhysObject collidee = null; - PhysObjects.TryGetValue(collidingWith, out collidee); - - // DetailLog("{0},BSScene.SendCollision,collide,id={1},with={2}", DetailLogZero, localID, collidingWith); - - if (collider.Collide(collidingWith, collidee, collidePoint, collideNormal, penetration)) - { - // If a collision was posted, remember to send it to the simulator - ObjectsWithCollisions.Add(collider); + BSCharacter actor; + if (m_avatars.TryGetValue(localID, out actor)) { + actor.Collide(collidingWith, type, collidePoint, collideNormal, penitration); + m_avatarsWithCollisions.Add(actor); + return; } - return; } - #endregion // Simulation - public override void GetResults() { } - #region Terrain - public override void SetTerrain(float[] heightMap) { - TerrainManager.SetTerrain(heightMap); + m_heightMap = heightMap; + this.TaintedObject("BSScene.SetTerrain", delegate() + { + BulletSimAPI.SetHeightmap(m_worldID, m_heightMap); + }); } - public override void SetWaterLevel(float baseheight) + // Someday we will have complex terrain with caves and tunnels + // For the moment, it's flat and convex + public float GetTerrainHeightAtXYZ(Vector3 loc) + { + return GetTerrainHeightAtXY(loc.X, loc.Y); + } + + public float GetTerrainHeightAtXY(float tX, float tY) + { + if (tX < 0 || tX >= Constants.RegionSize || tY < 0 || tY >= Constants.RegionSize) + return 30; + return m_heightMap[((int)tX) * Constants.RegionSize + ((int)tY)]; + } + + public override void SetWaterLevel(float baseheight) { m_waterLevel = baseheight; + // TODO: pass to physics engine so things will float? } - // Someday.... - public float GetWaterLevelAtXYZ(Vector3 loc) + public float GetWaterLevel() { return m_waterLevel; } - public override void DeleteTerrain() + public override void DeleteTerrain() { // m_log.DebugFormat("{0}: DeleteTerrain()", LogHeader); } - // Although no one seems to check this, I do support combining. - public override bool SupportsCombining() + public override void Dispose() { - return TerrainManager.SupportsCombining(); - } - // This call says I am a child to region zero in a mega-region. 'pScene' is that - // of region zero, 'offset' is my offset from regions zero's origin, and - // 'extents' is the largest XY that is handled in my region. - public override void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - TerrainManager.Combine(pScene, offset, extents); - } + // m_log.DebugFormat("{0}: Dispose()", LogHeader); - // Unhook all the combining that I know about. - public override void UnCombine(PhysicsScene pScene) - { - TerrainManager.UnCombine(pScene); - } + // make sure no stepping happens while we're deleting stuff + m_initialized = false; - #endregion // Terrain + foreach (KeyValuePair kvp in m_avatars) + { + kvp.Value.Destroy(); + } + m_avatars.Clear(); + + foreach (KeyValuePair kvp in m_prims) + { + kvp.Value.Destroy(); + } + m_prims.Clear(); + + // Now that the prims are all cleaned up, there should be no constraints left + if (m_constraintCollection != null) + { + m_constraintCollection.Dispose(); + m_constraintCollection = null; + } + + // Anything left in the unmanaged code should be cleaned out + BulletSimAPI.Shutdown(WorldID); + + // Not logging any more + PhysicsLogging.Close(); + } public override Dictionary GetTopColliders() { @@ -682,7 +628,120 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public override bool IsThreaded { get { return false; } } - #region Taints + /// + /// Routine to figure out if we need to mesh this prim with our mesher + /// + /// + /// true if the prim needs meshing + public bool NeedsMeshing(PrimitiveBaseShape pbs) + { + // most of this is redundant now as the mesher will return null if it cant mesh a prim + // but we still need to check for sculptie meshing being enabled so this is the most + // convenient place to do it for now... + + // int iPropertiesNotSupportedDefault = 0; + + if (pbs.SculptEntry && !_meshSculptedPrim) + { + // Render sculpties as boxes + return false; + } + + // if it's a standard box or sphere with no cuts, hollows, twist or top shear, return false since Bullet + // can use an internal representation for the prim + if (!_forceSimplePrimMeshing) + { + if ((pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) + || (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 + && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z)) + { + + if (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 + && pbs.ProfileHollow == 0 + && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 + && pbs.PathBegin == 0 && pbs.PathEnd == 0 + && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 + && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 + && pbs.PathShearX == 0 && pbs.PathShearY == 0) + { + return false; + } + } + } + + /* TODO: verify that the mesher will now do all these shapes + if (pbs.ProfileHollow != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathBegin != 0) || pbs.PathEnd != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathTwistBegin != 0) || (pbs.PathTwist != 0)) + iPropertiesNotSupportedDefault++; + + if ((pbs.ProfileBegin != 0) || pbs.ProfileEnd != 0) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathScaleX != 100) || (pbs.PathScaleY != 100)) + iPropertiesNotSupportedDefault++; + + if ((pbs.PathShearX != 0) || (pbs.PathShearY != 0)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.Circle && pbs.PathCurve == (byte)Extrusion.Straight) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1 && (pbs.Scale.X != pbs.Scale.Y || pbs.Scale.Y != pbs.Scale.Z || pbs.Scale.Z != pbs.Scale.X)) + iPropertiesNotSupportedDefault++; + + if (pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte) Extrusion.Curve1) + iPropertiesNotSupportedDefault++; + + // test for torus + if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Square) + { + if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.Circle) + { + if (pbs.PathCurve == (byte)Extrusion.Straight) + { + iPropertiesNotSupportedDefault++; + } + // ProfileCurve seems to combine hole shape and profile curve so we need to only compare against the lower 3 bits + else if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.HalfCircle) + { + if (pbs.PathCurve == (byte)Extrusion.Curve1 || pbs.PathCurve == (byte)Extrusion.Curve2) + { + iPropertiesNotSupportedDefault++; + } + } + else if ((pbs.ProfileCurve & 0x07) == (byte)ProfileShape.EquilateralTriangle) + { + if (pbs.PathCurve == (byte)Extrusion.Straight) + { + iPropertiesNotSupportedDefault++; + } + else if (pbs.PathCurve == (byte)Extrusion.Curve1) + { + iPropertiesNotSupportedDefault++; + } + } + if (iPropertiesNotSupportedDefault == 0) + { + return false; + } + */ + return true; + } // Calls to the PhysicsActors can't directly call into the physics engine // because it might be busy. We delay changes to a known time. @@ -692,67 +751,17 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters if (!m_initialized) return; lock (_taintLock) - { - _taintOperations.Add(new TaintCallbackEntry(ident, callback)); - } - + _taintedObjects.Add(new TaintCallbackEntry(ident, callback)); return; } - // Sometimes a potentially tainted operation can be used in and out of taint time. - // This routine executes the command immediately if in taint-time otherwise it is queued. - public void TaintedObject(bool inTaintTime, string ident, TaintCallback callback) - { - if (inTaintTime) - callback(); - else - TaintedObject(ident, callback); - } - // When someone tries to change a property on a BSPrim or BSCharacter, the object queues // a callback into itself to do the actual property change. That callback is called // here just before the physics engine is called to step the simulation. public void ProcessTaints() { - InTaintTime = true; - ProcessRegularTaints(); - ProcessPostTaintTaints(); - InTaintTime = false; - } - - private void ProcessRegularTaints() - { - if (_taintOperations.Count > 0) // save allocating new list if there is nothing to process + if (_taintedObjects.Count > 0) // save allocating new list if there is nothing to process { - int taintCount = m_taintsToProcessPerStep; - TaintCallbackEntry oneCallback = new TaintCallbackEntry(); - while (_taintOperations.Count > 0 && taintCount-- > 0) - { - bool gotOne = false; - lock (_taintLock) - { - if (_taintOperations.Count > 0) - { - oneCallback = _taintOperations[0]; - _taintOperations.RemoveAt(0); - gotOne = true; - } - } - if (gotOne) - { - try - { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, oneCallback.ident); - oneCallback.callback(); - } - catch (Exception e) - { - DetailLog("{0},BSScene.ProcessTaints,doTaintException,id={1}", DetailLogZero, oneCallback.ident); // DEBUG DEBUG DEBUG - m_log.ErrorFormat("{0}: ProcessTaints: {1}: Exception: {2}", LogHeader, oneCallback.ident, e); - } - } - } - /* // swizzle a new list into the list location so we can process what's there List oldList; lock (_taintLock) @@ -765,7 +774,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { try { - DetailLog("{0},BSScene.ProcessTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG tcbe.callback(); } catch (Exception e) @@ -774,113 +782,20 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } } oldList.Clear(); - */ } } - // Schedule an update to happen after all the regular taints are processed. - // Note that new requests for the same operation ("ident") for the same object ("ID") - // will replace any previous operation by the same object. - public void PostTaintObject(String ident, uint ID, TaintCallback callback) - { - if (!m_initialized) return; - - string uniqueIdent = ident + "-" + ID.ToString(); - lock (_taintLock) - { - _postTaintOperations[uniqueIdent] = new TaintCallbackEntry(uniqueIdent, callback); - } - - return; - } - - private void ProcessPostTaintTaints() - { - if (_postTaintOperations.Count > 0) - { - Dictionary oldList; - lock (_taintLock) - { - oldList = _postTaintOperations; - _postTaintOperations = new Dictionary(); - } - - foreach (KeyValuePair kvp in oldList) - { - try - { - DetailLog("{0},BSScene.ProcessPostTaintTaints,doTaint,id={1}", DetailLogZero, kvp.Key); // DEBUG DEBUG DEBUG - kvp.Value.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessPostTaintTaints: {1}: Exception: {2}", LogHeader, kvp.Key, e); - } - } - oldList.Clear(); - } - } - - public void PostStepTaintObject(String ident, TaintCallback callback) - { - if (!m_initialized) return; - - lock (_taintLock) - { - _postStepOperations.Add(new TaintCallbackEntry(ident, callback)); - } - - return; - } - - private void ProcessPostStepTaints() - { - if (_postStepOperations.Count > 0) - { - List oldList; - lock (_taintLock) - { - oldList = _postStepOperations; - _postStepOperations = new List(); - } - - foreach (TaintCallbackEntry tcbe in oldList) - { - try - { - DetailLog("{0},BSScene.ProcessPostStepTaints,doTaint,id={1}", DetailLogZero, tcbe.ident); // DEBUG DEBUG DEBUG - tcbe.callback(); - } - catch (Exception e) - { - m_log.ErrorFormat("{0}: ProcessPostStepTaints: {1}: Exception: {2}", LogHeader, tcbe.ident, e); - } - } - oldList.Clear(); - } - } - - public bool AssertInTaintTime(string whereFrom) - { - if (!InTaintTime) - { - DetailLog("{0},BSScene.AssertInTaintTime,NOT IN TAINT TIME,Region={1},Where={2}", DetailLogZero, RegionName, whereFrom); - m_log.ErrorFormat("{0} NOT IN TAINT TIME!! Region={1}, Where={2}", LogHeader, RegionName, whereFrom); - Util.PrintCallStack(); - } - return InTaintTime; - } - - #endregion // Taints - #region Vehicles public void VehicleInSceneTypeChanged(BSPrim vehic, Vehicle newType) { - RemoveVehiclePrim(vehic); - if (newType != Vehicle.TYPE_NONE) + if (newType == Vehicle.TYPE_NONE) { - // make it so the scene will call us each tick to do vehicle things + RemoveVehiclePrim(vehic); + } + else + { + // make it so the scene will call us each tick to do vehicle things AddVehiclePrim(vehic); } } @@ -912,22 +827,21 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters } // Some prims have extra vehicle actions - // Called at taint time! + // no locking because only called when physics engine is not busy private void ProcessVehicles(float timeStep) { - foreach (BSPhysObject pobj in m_vehicles) + foreach (BSPrim prim in m_vehicles) { - pobj.StepVehicle(timeStep); + prim.StepVehicle(timeStep); } } #endregion Vehicles - #region INI and command line parameter processing + #region Parameters delegate void ParamUser(BSScene scene, IConfig conf, string paramName, float val); delegate float ParamGet(BSScene scene); delegate void ParamSet(BSScene scene, string paramName, uint localID, float val); - delegate void SetOnObject(BSScene scene, BSPhysObject obj, float val); private struct ParameterDefn { @@ -937,7 +851,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters public ParamUser userParam; // get the value from the configuration file public ParamGet getter; // return the current value stored for this parameter public ParamSet setter; // set the current value for this parameter - public SetOnObject onObject; // set the value on an object in the physical domain public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s) { name = n; @@ -946,17 +859,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters userParam = u; getter = g; setter = s; - onObject = null; - } - public ParameterDefn(string n, string d, float v, ParamUser u, ParamGet g, ParamSet s, SetOnObject o) - { - name = n; - desc = d; - defaultValue = v; - userParam = u; - getter = g; - setter = s; - onObject = o; } } @@ -967,7 +869,7 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // getters and setters. // It is easiest to find an existing definition and copy it. // Parameter values are floats. Booleans are converted to a floating value. - // + // // A ParameterDefn() takes the following parameters: // -- the text name of the parameter. This is used for console input and ini file. // -- a short text description of the parameter. This shows up in the console listing. @@ -978,7 +880,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters // // The single letter parameters for the delegates are: // s = BSScene - // o = BSPhysObject // p = string parameter name // l = localID of referenced object // v = float value @@ -987,40 +888,25 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters { new ParameterDefn("MeshSculptedPrim", "Whether to create meshes for sculpties", ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.ShouldMeshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldMeshSculptedPrim); }, - (s,p,l,v) => { s.ShouldMeshSculptedPrim = s.BoolNumeric(v); } ), + (s,cf,p,v) => { s._meshSculptedPrim = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s._meshSculptedPrim); }, + (s,p,l,v) => { s._meshSculptedPrim = s.BoolNumeric(v); } ), new ParameterDefn("ForceSimplePrimMeshing", "If true, only use primitive meshes for objects", ConfigurationParameters.numericFalse, - (s,cf,p,v) => { s.ShouldForceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldForceSimplePrimMeshing); }, - (s,p,l,v) => { s.ShouldForceSimplePrimMeshing = s.BoolNumeric(v); } ), - new ParameterDefn("UseHullsForPhysicalObjects", "If true, create hulls for physical objects", - ConfigurationParameters.numericTrue, - (s,cf,p,v) => { s.ShouldUseHullsForPhysicalObjects = cf.GetBoolean(p, s.BoolNumeric(v)); }, - (s) => { return s.NumericBool(s.ShouldUseHullsForPhysicalObjects); }, - (s,p,l,v) => { s.ShouldUseHullsForPhysicalObjects = s.BoolNumeric(v); } ), + (s,cf,p,v) => { s._forceSimplePrimMeshing = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s._forceSimplePrimMeshing); }, + (s,p,l,v) => { s._forceSimplePrimMeshing = s.BoolNumeric(v); } ), - new ParameterDefn("MeshLevelOfDetail", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", + new ParameterDefn("MeshLOD", "Level of detail to render meshes (32, 16, 8 or 4. 32=most detailed)", 8f, - (s,cf,p,v) => { s.MeshLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.MeshLOD; }, - (s,p,l,v) => { s.MeshLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrim", "Level of detail to render meshes larger than threshold meters", - 16f, - (s,cf,p,v) => { s.MeshMegaPrimLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.MeshMegaPrimLOD; }, - (s,p,l,v) => { s.MeshMegaPrimLOD = v; } ), - new ParameterDefn("MeshLevelOfDetailMegaPrimThreshold", "Size (in meters) of a mesh before using MeshMegaPrimLOD", - 10f, - (s,cf,p,v) => { s.MeshMegaPrimThreshold = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.MeshMegaPrimThreshold; }, - (s,p,l,v) => { s.MeshMegaPrimThreshold = v; } ), - new ParameterDefn("SculptLevelOfDetail", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", + (s,cf,p,v) => { s.m_meshLOD = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_meshLOD; }, + (s,p,l,v) => { s.m_meshLOD = (int)v; } ), + new ParameterDefn("SculptLOD", "Level of detail to render sculpties (32, 16, 8 or 4. 32=most detailed)", 32f, - (s,cf,p,v) => { s.SculptLOD = (float)cf.GetInt(p, (int)v); }, - (s) => { return s.SculptLOD; }, - (s,p,l,v) => { s.SculptLOD = v; } ), + (s,cf,p,v) => { s.m_sculptLOD = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_sculptLOD; }, + (s,p,l,v) => { s.m_sculptLOD = (int)v; } ), new ParameterDefn("MaxSubStep", "In simulation step, maximum number of substeps", 10f, @@ -1042,16 +928,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_maxUpdatesPerFrame = cf.GetInt(p, (int)v); }, (s) => { return (float)s.m_maxUpdatesPerFrame; }, (s,p,l,v) => { s.m_maxUpdatesPerFrame = (int)v; } ), - new ParameterDefn("MaxTaintsToProcessPerStep", "Number of update taints to process before each simulation step", - 100f, - (s,cf,p,v) => { s.m_taintsToProcessPerStep = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_taintsToProcessPerStep; }, - (s,p,l,v) => { s.m_taintsToProcessPerStep = (int)v; } ), new ParameterDefn("MaxObjectMass", "Maximum object mass (10000.01)", 10000.01f, - (s,cf,p,v) => { s.MaximumObjectMass = cf.GetFloat(p, v); }, - (s) => { return (float)s.MaximumObjectMass; }, - (s,p,l,v) => { s.MaximumObjectMass = v; } ), + (s,cf,p,v) => { s.m_maximumObjectMass = cf.GetFloat(p, v); }, + (s) => { return (float)s.m_maximumObjectMass; }, + (s,p,l,v) => { s.m_maximumObjectMass = v; } ), new ParameterDefn("PID_D", "Derivitive factor for motion smoothing", 2200f, @@ -1088,118 +969,104 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters -9.80665f, (s,cf,p,v) => { s.m_params[0].gravity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].gravity; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].gravity, p, PhysParameterEntry.APPLY_TO_NONE, v); }, - (s,o,v) => { BulletSimAPI.SetGravity2(s.World.ptr, new Vector3(0f,0f,v)); } ), + (s,p,l,v) => { s.m_params[0].gravity = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("LinearDamping", "Factor to damp linear movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].linearDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearDamping, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearDamping, p, l, v); } ), new ParameterDefn("AngularDamping", "Factor to damp angular movement per second (0.0 - 1.0)", 0f, (s,cf,p,v) => { s.m_params[0].angularDamping = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularDamping; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularDamping, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDamping2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularDamping, p, l, v); } ), new ParameterDefn("DeactivationTime", "Seconds before considering an object potentially static", 0.2f, (s,cf,p,v) => { s.m_params[0].deactivationTime = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].deactivationTime; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].deactivationTime, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetDeactivationTime2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].deactivationTime, p, l, v); } ), new ParameterDefn("LinearSleepingThreshold", "Seconds to measure linear movement before considering static", 0.8f, (s,cf,p,v) => { s.m_params[0].linearSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linearSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].linearSleepingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].linearSleepingThreshold, p, l, v); } ), new ParameterDefn("AngularSleepingThreshold", "Seconds to measure angular movement before considering static", 1.0f, (s,cf,p,v) => { s.m_params[0].angularSleepingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].angularSleepingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].angularSleepingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetSleepingThresholds2(o.PhysBody.ptr, v, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].angularSleepingThreshold, p, l, v); } ), new ParameterDefn("CcdMotionThreshold", "Continuious collision detection threshold (0 means no CCD)" , 0f, // set to zero to disable (s,cf,p,v) => { s.m_params[0].ccdMotionThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdMotionThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdMotionThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdMotionThreshold2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdMotionThreshold, p, l, v); } ), new ParameterDefn("CcdSweptSphereRadius", "Continuious collision detection test radius" , 0f, (s,cf,p,v) => { s.m_params[0].ccdSweptSphereRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].ccdSweptSphereRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetCcdSweptSphereRadius2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].ccdSweptSphereRadius, p, l, v); } ), new ParameterDefn("ContactProcessingThreshold", "Distance between contacts before doing collision check" , 0.1f, (s,cf,p,v) => { s.m_params[0].contactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].contactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].contactProcessingThreshold, p, l, v); }, - (s,o,v) => { BulletSimAPI.SetContactProcessingThreshold2(o.PhysBody.ptr, v); } ), + (s,p,l,v) => { s.UpdateParameterPrims(ref s.m_params[0].contactProcessingThreshold, p, l, v); } ), new ParameterDefn("TerrainFriction", "Factor to reduce movement against terrain surface" , 0.5f, (s,cf,p,v) => { s.m_params[0].terrainFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainFriction; }, - (s,p,l,v) => { s.m_params[0].terrainFriction = v; /* TODO: set on real terrain */} ), + (s,p,l,v) => { s.m_params[0].terrainFriction = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("TerrainHitFraction", "Distance to measure hit collisions" , 0.8f, (s,cf,p,v) => { s.m_params[0].terrainHitFraction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainHitFraction; }, - (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; /* TODO: set on real terrain */ } ), + (s,p,l,v) => { s.m_params[0].terrainHitFraction = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("TerrainRestitution", "Bouncyness" , 0f, (s,cf,p,v) => { s.m_params[0].terrainRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].terrainRestitution; }, - (s,p,l,v) => { s.m_params[0].terrainRestitution = v; /* TODO: set on real terrain */ } ), + (s,p,l,v) => { s.m_params[0].terrainRestitution = v; s.TaintedUpdateParameter(p,l,v); } ), new ParameterDefn("AvatarFriction", "Factor to reduce movement against an avatar. Changed on avatar recreation.", - 0.2f, + 0.5f, (s,cf,p,v) => { s.m_params[0].avatarFriction = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarFriction; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarFriction, p, l, v); } ), - new ParameterDefn("AvatarStandingFriction", "Avatar friction when standing. Changed on avatar recreation.", - 10f, - (s,cf,p,v) => { s.m_params[0].avatarStandingFriction = cf.GetFloat(p, v); }, - (s) => { return s.m_params[0].avatarStandingFriction; }, - (s,p,l,v) => { s.m_params[0].avatarStandingFriction = v; } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarFriction, p, l, v); } ), new ParameterDefn("AvatarDensity", "Density of an avatar. Changed on avatar recreation.", 60f, (s,cf,p,v) => { s.m_params[0].avatarDensity = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarDensity; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarDensity, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarDensity, p, l, v); } ), new ParameterDefn("AvatarRestitution", "Bouncyness. Changed on avatar recreation.", 0f, (s,cf,p,v) => { s.m_params[0].avatarRestitution = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarRestitution; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarRestitution, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarRestitution, p, l, v); } ), new ParameterDefn("AvatarCapsuleRadius", "Radius of space around an avatar", 0.37f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleRadius = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleRadius; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleRadius, p, l, v); } ), new ParameterDefn("AvatarCapsuleHeight", "Default height of space around avatar", 1.5f, (s,cf,p,v) => { s.m_params[0].avatarCapsuleHeight = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarCapsuleHeight; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarCapsuleHeight, p, l, v); } ), new ParameterDefn("AvatarContactProcessingThreshold", "Distance from capsule to check for collisions", 0.1f, (s,cf,p,v) => { s.m_params[0].avatarContactProcessingThreshold = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].avatarContactProcessingThreshold; }, - (s,p,l,v) => { s.UpdateParameterObject(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), + (s,p,l,v) => { s.UpdateParameterAvatars(ref s.m_params[0].avatarContactProcessingThreshold, p, l, v); } ), new ParameterDefn("MaxPersistantManifoldPoolSize", "Number of manifolds pooled (0 means default of 4096)", - 0f, + 0f, // zero to disable (s,cf,p,v) => { s.m_params[0].maxPersistantManifoldPoolSize = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].maxPersistantManifoldPoolSize; }, (s,p,l,v) => { s.m_params[0].maxPersistantManifoldPoolSize = v; } ), new ParameterDefn("MaxCollisionAlgorithmPoolSize", "Number of collisions pooled (0 means default of 4096)", - 0f, + 0f, // zero to disable (s,cf,p,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].maxCollisionAlgorithmPoolSize; }, (s,p,l,v) => { s.m_params[0].maxCollisionAlgorithmPoolSize = v; } ), @@ -1214,12 +1081,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].shouldForceUpdateAllAabbs; }, (s,p,l,v) => { s.m_params[0].shouldForceUpdateAllAabbs = v; } ), new ParameterDefn("ShouldRandomizeSolverOrder", "Enable for slightly better stacking interaction", - ConfigurationParameters.numericTrue, + ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].shouldRandomizeSolverOrder = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s) => { return s.m_params[0].shouldRandomizeSolverOrder; }, (s,p,l,v) => { s.m_params[0].shouldRandomizeSolverOrder = v; } ), new ParameterDefn("ShouldSplitSimulationIslands", "Enable splitting active object scanning islands", - ConfigurationParameters.numericTrue, + ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].shouldSplitSimulationIslands = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, (s) => { return s.m_params[0].shouldSplitSimulationIslands; }, (s,p,l,v) => { s.m_params[0].shouldSplitSimulationIslands = v; } ), @@ -1234,11 +1101,6 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s) => { return s.m_params[0].numberOfSolverIterations; }, (s,p,l,v) => { s.m_params[0].numberOfSolverIterations = v; } ), - new ParameterDefn("LinksetImplementation", "Type of linkset implementation (0=Constraint, 1=Compound, 2=Manual)", - (float)BSLinkset.LinksetImplementation.Compound, - (s,cf,p,v) => { s.m_params[0].linksetImplementation = cf.GetFloat(p,v); }, - (s) => { return s.m_params[0].linksetImplementation; }, - (s,p,l,v) => { s.m_params[0].linksetImplementation = v; } ), new ParameterDefn("LinkConstraintUseFrameOffset", "For linksets built with constraints, enable frame offsetFor linksets built with constraints, enable frame offset.", ConfigurationParameters.numericFalse, (s,cf,p,v) => { s.m_params[0].linkConstraintUseFrameOffset = s.NumericBool(cf.GetBoolean(p, s.BoolNumeric(v))); }, @@ -1259,27 +1121,28 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters (s,cf,p,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintTransMotorMaxForce; }, (s,p,l,v) => { s.m_params[0].linkConstraintTransMotorMaxForce = v; } ), - new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=no violation, 1=infinite. Default=0.1", - 0.1f, + new ParameterDefn("LinkConstraintCFM", "Amount constraint can be violated. 0=none, 1=all. Default=0", + 0.0f, (s,cf,p,v) => { s.m_params[0].linkConstraintCFM = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintCFM; }, (s,p,l,v) => { s.m_params[0].linkConstraintCFM = v; } ), new ParameterDefn("LinkConstraintERP", "Amount constraint is corrected each tick. 0=none, 1=all. Default = 0.2", - 0.1f, + 0.2f, (s,cf,p,v) => { s.m_params[0].linkConstraintERP = cf.GetFloat(p, v); }, (s) => { return s.m_params[0].linkConstraintERP; }, (s,p,l,v) => { s.m_params[0].linkConstraintERP = v; } ), - new ParameterDefn("LinkConstraintSolverIterations", "Number of solver iterations when computing constraint. (0 = Bullet default)", - 40, - (s,cf,p,v) => { s.m_params[0].linkConstraintSolverIterations = cf.GetFloat(p, v); }, - (s) => { return s.m_params[0].linkConstraintSolverIterations; }, - (s,p,l,v) => { s.m_params[0].linkConstraintSolverIterations = v; } ), - new ParameterDefn("LogPhysicsStatisticsFrames", "Frames between outputting detailed phys stats. (0 is off)", + new ParameterDefn("DetailedStats", "Frames between outputting detailed phys stats. (0 is off)", 0f, - (s,cf,p,v) => { s.m_params[0].physicsLoggingFrames = cf.GetInt(p, (int)v); }, - (s) => { return (float)s.m_params[0].physicsLoggingFrames; }, - (s,p,l,v) => { s.m_params[0].physicsLoggingFrames = (int)v; } ), + (s,cf,p,v) => { s.m_detailedStatsStep = cf.GetInt(p, (int)v); }, + (s) => { return (float)s.m_detailedStatsStep; }, + (s,p,l,v) => { s.m_detailedStatsStep = (int)v; } ), + new ParameterDefn("ShouldDebugLog", "Enables detailed DEBUG log statements", + ConfigurationParameters.numericFalse, + (s,cf,p,v) => { s.ShouldDebugLog = cf.GetBoolean(p, s.BoolNumeric(v)); }, + (s) => { return s.NumericBool(s.ShouldDebugLog); }, + (s,p,l,v) => { s.ShouldDebugLog = s.BoolNumeric(v); } ), + }; // Convert a boolean to our numeric true and false values @@ -1337,12 +1200,11 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters private PhysParameterEntry[] SettableParameters = new PhysParameterEntry[1]; - // This creates an array in the correct format for returning the list of - // parameters. This is used by the 'list' option of the 'physics' command. private void BuildParameterTable() { if (SettableParameters.Length < ParameterDefinitions.Length) { + List entries = new List(); for (int ii = 0; ii < ParameterDefinitions.Length; ii++) { @@ -1387,54 +1249,60 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters return ret; } + // check to see if we are updating a parameter for a particular or all of the prims + protected void UpdateParameterPrims(ref float loc, string parm, uint localID, float val) + { + List operateOn; + lock (m_prims) operateOn = new List(m_prims.Keys); + UpdateParameterSet(operateOn, ref loc, parm, localID, val); + } + + // check to see if we are updating a parameter for a particular or all of the avatars + protected void UpdateParameterAvatars(ref float loc, string parm, uint localID, float val) + { + List operateOn; + lock (m_avatars) operateOn = new List(m_avatars.Keys); + UpdateParameterSet(operateOn, ref loc, parm, localID, val); + } + // update all the localIDs specified // If the local ID is APPLY_TO_NONE, just change the default value // If the localID is APPLY_TO_ALL change the default value and apply the new value to all the lIDs // If the localID is a specific object, apply the parameter change to only that object - private void UpdateParameterObject(ref float defaultLoc, string parm, uint localID, float val) + protected void UpdateParameterSet(List lIDs, ref float defaultLoc, string parm, uint localID, float val) { - List objectIDs = new List(); switch (localID) { case PhysParameterEntry.APPLY_TO_NONE: defaultLoc = val; // setting only the default value - // This will cause a call into the physical world if some operation is specified (SetOnObject). - objectIDs.Add(TERRAIN_ID); - TaintedUpdateParameter(parm, objectIDs, val); break; case PhysParameterEntry.APPLY_TO_ALL: defaultLoc = val; // setting ALL also sets the default value - lock (PhysObjects) objectIDs = new List(PhysObjects.Keys); - TaintedUpdateParameter(parm, objectIDs, val); + List objectIDs = lIDs; + string xparm = parm.ToLower(); + float xval = val; + TaintedObject("BSScene.UpdateParameterSet", delegate() { + foreach (uint lID in objectIDs) + { + BulletSimAPI.UpdateParameter(m_worldID, lID, xparm, xval); + } + }); break; - default: + default: // setting only one localID - objectIDs.Add(localID); - TaintedUpdateParameter(parm, objectIDs, val); + TaintedUpdateParameter(parm, localID, val); break; } } // schedule the actual updating of the paramter to when the phys engine is not busy - private void TaintedUpdateParameter(string parm, List lIDs, float val) + protected void TaintedUpdateParameter(string parm, uint localID, float val) { + uint xlocalID = localID; + string xparm = parm.ToLower(); float xval = val; - List xlIDs = lIDs; - string xparm = parm; - TaintedObject("BSScene.UpdateParameterSet", delegate() { - ParameterDefn thisParam; - if (TryGetParameter(xparm, out thisParam)) - { - if (thisParam.onObject != null) - { - foreach (uint lID in xlIDs) - { - BSPhysObject theObject = null; - PhysObjects.TryGetValue(lID, out theObject); - thisParam.onObject(this, theObject, xval); - } - } - } + TaintedObject("BSScene.TaintedUpdateParameter", delegate() { + BulletSimAPI.UpdateParameter(m_worldID, xlocalID, xparm, xval); }); } @@ -1458,24 +1326,12 @@ public sealed class BSScene : PhysicsScene, IPhysicsParameters #endregion Runtime settable parameters - // Debugging routine for dumping detailed physical information for vehicle prims - private void DumpVehicles() - { - foreach (BSPrim prim in m_vehicles) - { - BulletSimAPI.DumpRigidBody2(World.ptr, prim.PhysBody.ptr); - BulletSimAPI.DumpCollisionShape2(World.ptr, prim.PhysShape.ptr); - } - } - // Invoke the detailed logger and output something if it's enabled. public void DetailLog(string msg, params Object[] args) { PhysicsLogging.Write(msg, args); - // Add the Flush() if debugging crashes. Gets all the messages written out. - PhysicsLogging.Flush(); } - // Used to fill in the LocalID when there isn't one. It's the correct number of characters. + // used to fill in the LocalID when there isn't one public const string DetailLogZero = "0000000000"; } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs deleted file mode 100755 index 29a23c0247..0000000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapeCollection.cs +++ /dev/null @@ -1,1000 +0,0 @@ -/* - * 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 copyrightD - * 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.Text; -using OMV = OpenMetaverse; -using OpenSim.Framework; -using OpenSim.Region.Physics.Manager; -using OpenSim.Region.Physics.ConvexDecompositionDotNet; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSShapeCollection : IDisposable -{ - private static string LogHeader = "[BULLETSIM SHAPE COLLECTION]"; - - private BSScene PhysicsScene { get; set; } - - private Object m_collectionActivityLock = new Object(); - - // Description of a Mesh - private struct MeshDesc - { - public IntPtr ptr; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // Description of a hull. - // Meshes and hulls have the same shape hash key but we only need hulls for efficient collision calculations. - private struct HullDesc - { - public IntPtr ptr; - public int referenceCount; - public DateTime lastReferenced; - public UInt64 shapeKey; - } - - // The sharable set of meshes and hulls. Indexed by their shape hash. - private Dictionary Meshes = new Dictionary(); - private Dictionary Hulls = new Dictionary(); - - public BSShapeCollection(BSScene physScene) - { - PhysicsScene = physScene; - } - - public void Dispose() - { - // TODO!!!!!!!!! - } - - // Callbacks called just before either the body or shape is destroyed. - // Mostly used for changing bodies out from under Linksets. - // Useful for other cases where parameters need saving. - // Passing 'null' says no callback. - public delegate void ShapeDestructionCallback(BulletShape shape); - public delegate void BodyDestructionCallback(BulletBody body); - - // Called to update/change the body and shape for an object. - // First checks the shape and updates that if necessary then makes - // sure the body is of the right type. - // Return 'true' if either the body or the shape changed. - // 'shapeCallback' and 'bodyCallback' are, if non-null, functions called just before - // the current shape or body is destroyed. This allows the caller to remove any - // higher level dependencies on the shape or body. Mostly used for LinkSets to - // remove the physical constraints before the body is destroyed. - // Called at taint-time!! - public bool GetBodyAndShape(bool forceRebuild, BulletSim sim, BSPhysObject prim, - ShapeDestructionCallback shapeCallback, BodyDestructionCallback bodyCallback) - { - PhysicsScene.AssertInTaintTime("BSShapeCollection.GetBodyAndShape"); - - bool ret = false; - - // This lock could probably be pushed down lower but building shouldn't take long - lock (m_collectionActivityLock) - { - // Do we have the correct geometry for this type of object? - // Updates prim.BSShape with information/pointers to shape. - // Returns 'true' of BSShape is changed to a new shape. - bool newGeom = CreateGeom(forceRebuild, prim, shapeCallback); - // If we had to select a new shape geometry for the object, - // rebuild the body around it. - // Updates prim.BSBody with information/pointers to requested body - // Returns 'true' if BSBody was changed. - bool newBody = CreateBody((newGeom || forceRebuild), prim, PhysicsScene.World, - prim.PhysShape, bodyCallback); - ret = newGeom || newBody; - } - DetailLog("{0},BSShapeCollection.GetBodyAndShape,taintExit,force={1},ret={2},body={3},shape={4}", - prim.LocalID, forceRebuild, ret, prim.PhysBody, prim.PhysShape); - - return ret; - } - - // Track another user of a body. - // We presume the caller has allocated the body. - // Bodies only have one user so the body is just put into the world if not already there. - public void ReferenceBody(BulletBody body, bool inTaintTime) - { - lock (m_collectionActivityLock) - { - DetailLog("{0},BSShapeCollection.ReferenceBody,newBody,body={1}", body.ID, body); - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.ReferenceBody", delegate() - { - if (!BulletSimAPI.IsInWorld2(body.ptr)) - { - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, body.ptr); - DetailLog("{0},BSShapeCollection.ReferenceBody,addedToWorld,ref={1}", body.ID, body); - } - }); - } - } - - // Release the usage of a body. - // Called when releasing use of a BSBody. BSShape is handled separately. - public void DereferenceBody(BulletBody body, bool inTaintTime, BodyDestructionCallback bodyCallback ) - { - if (body.ptr == IntPtr.Zero) - return; - - lock (m_collectionActivityLock) - { - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceBody", delegate() - { - DetailLog("{0},BSShapeCollection.DereferenceBody,DestroyingBody,body={1},inTaintTime={2}", - body.ID, body, inTaintTime); - // If the caller needs to know the old body is going away, pass the event up. - if (bodyCallback != null) bodyCallback(body); - - if (BulletSimAPI.IsInWorld2(body.ptr)) - { - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, body.ptr); - DetailLog("{0},BSShapeCollection.DereferenceBody,removingFromWorld. Body={1}", body.ID, body); - } - - // Zero any reference to the shape so it is not freed when the body is deleted. - BulletSimAPI.SetCollisionShape2(PhysicsScene.World.ptr, body.ptr, IntPtr.Zero); - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, body.ptr); - }); - } - } - - // Track the datastructures and use count for a shape. - // When creating a hull, this is called first to reference the mesh - // and then again to reference the hull. - // Meshes and hulls for the same shape have the same hash key. - // NOTE that native shapes are not added to the mesh list or removed. - // Returns 'true' if this is the initial reference to the shape. Otherwise reused. - public bool ReferenceShape(BulletShape shape) - { - bool ret = false; - switch (shape.type) - { - case ShapeData.PhysicsShapeType.SHAPE_MESH: - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - // There is an existing instance of this mesh. - meshDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceShape,existingMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - } - else - { - // This is a new reference to a mesh - meshDesc.ptr = shape.ptr; - meshDesc.shapeKey = shape.shapeKey; - // We keep a reference to the underlying IMesh data so a hull can be built - meshDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceShape,newMesh,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), meshDesc.referenceCount); - ret = true; - } - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - break; - case ShapeData.PhysicsShapeType.SHAPE_HULL: - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - // There is an existing instance of this hull. - hullDesc.referenceCount++; - DetailLog("{0},BSShapeCollection.ReferenceShape,existingHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - } - else - { - // This is a new reference to a hull - hullDesc.ptr = shape.ptr; - hullDesc.shapeKey = shape.shapeKey; - hullDesc.referenceCount = 1; - DetailLog("{0},BSShapeCollection.ReferenceShape,newHull,key={1},cnt={2}", - BSScene.DetailLogZero, shape.shapeKey.ToString("X"), hullDesc.referenceCount); - ret = true; - - } - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - // Native shapes are not tracked and they don't go into any list - break; - } - return ret; - } - - // Release the usage of a shape. - public void DereferenceShape(BulletShape shape, bool inTaintTime, ShapeDestructionCallback shapeCallback) - { - if (shape.ptr == IntPtr.Zero) - return; - - PhysicsScene.TaintedObject(inTaintTime, "BSShapeCollection.DereferenceShape", delegate() - { - if (shape.ptr != IntPtr.Zero) - { - if (shape.isNativeShape) - { - // Native shapes are not tracked and are released immediately - DetailLog("{0},BSShapeCollection.DereferenceShape,deleteNativeShape,ptr={1},taintTime={2}", - BSScene.DetailLogZero, shape.ptr.ToString("X"), inTaintTime); - if (shapeCallback != null) shapeCallback(shape); - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); - } - else - { - switch (shape.type) - { - case ShapeData.PhysicsShapeType.SHAPE_HULL: - DereferenceHull(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_MESH: - DereferenceMesh(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_COMPOUND: - DereferenceCompound(shape, shapeCallback); - break; - case ShapeData.PhysicsShapeType.SHAPE_UNKNOWN: - break; - default: - break; - } - } - } - }); - } - - // Count down the reference count for a mesh shape - // Called at taint-time. - private void DereferenceMesh(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - MeshDesc meshDesc; - if (Meshes.TryGetValue(shape.shapeKey, out meshDesc)) - { - meshDesc.referenceCount--; - // TODO: release the Bullet storage - if (shapeCallback != null) shapeCallback(shape); - meshDesc.lastReferenced = System.DateTime.Now; - Meshes[shape.shapeKey] = meshDesc; - DetailLog("{0},BSShapeCollection.DereferenceMesh,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, meshDesc.referenceCount); - - } - } - - // Count down the reference count for a hull shape - // Called at taint-time. - private void DereferenceHull(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - HullDesc hullDesc; - if (Hulls.TryGetValue(shape.shapeKey, out hullDesc)) - { - hullDesc.referenceCount--; - // TODO: release the Bullet storage (aging old entries?) - - // Tell upper layers that, if they have dependencies on this shape, this link is going away - if (shapeCallback != null) shapeCallback(shape); - - hullDesc.lastReferenced = System.DateTime.Now; - Hulls[shape.shapeKey] = hullDesc; - DetailLog("{0},BSShapeCollection.DereferenceHull,shape={1},refCnt={2}", - BSScene.DetailLogZero, shape, hullDesc.referenceCount); - } - } - - // Remove a reference to a compound shape. - // Taking a compound shape apart is a little tricky because if you just delete the - // physical shape, it will free all the underlying children. We can't do that because - // they could be shared. So, this removes each of the children from the compound and - // dereferences them separately before destroying the compound collision object itself. - // Called at taint-time. - private void DereferenceCompound(BulletShape shape, ShapeDestructionCallback shapeCallback) - { - if (!BulletSimAPI.IsCompound2(shape.ptr)) - { - // Failed the sanity check!! - PhysicsScene.Logger.ErrorFormat("{0} Attempt to free a compound shape that is not compound!! type={1}, ptr={2}", - LogHeader, shape.type, shape.ptr.ToString("X")); - DetailLog("{0},BSShapeCollection.DereferenceCompound,notACompoundShape,type={1},ptr={2}", - BSScene.DetailLogZero, shape.type, shape.ptr.ToString("X")); - return; - } - - int numChildren = BulletSimAPI.GetNumberOfCompoundChildren2(shape.ptr); - DetailLog("{0},BSShapeCollection.DereferenceCompound,shape={1},children={2}", BSScene.DetailLogZero, shape, numChildren); - - for (int ii = numChildren - 1; ii >= 0; ii--) - { - IntPtr childShape = BulletSimAPI.RemoveChildShapeFromCompoundShapeIndex2(shape.ptr, ii); - DereferenceAnonCollisionShape(childShape); - } - BulletSimAPI.DeleteCollisionShape2(PhysicsScene.World.ptr, shape.ptr); - } - - // Sometimes we have a pointer to a collision shape but don't know what type it is. - // Figure out type and call the correct dereference routine. - // Called at taint-time. - private void DereferenceAnonCollisionShape(IntPtr cShape) - { - MeshDesc meshDesc; - HullDesc hullDesc; - - BulletShape shapeInfo = new BulletShape(cShape); - if (TryGetMeshByPtr(cShape, out meshDesc)) - { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_MESH; - shapeInfo.shapeKey = meshDesc.shapeKey; - } - else - { - if (TryGetHullByPtr(cShape, out hullDesc)) - { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_HULL; - shapeInfo.shapeKey = hullDesc.shapeKey; - } - else - { - if (BulletSimAPI.IsCompound2(cShape)) - { - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_COMPOUND; - } - else - { - if (BulletSimAPI.IsNativeShape2(cShape)) - { - shapeInfo.isNativeShape = true; - shapeInfo.type = ShapeData.PhysicsShapeType.SHAPE_BOX; // (technically, type doesn't matter) - } - } - } - } - - DetailLog("{0},BSShapeCollection.DereferenceAnonCollisionShape,shape={1}", BSScene.DetailLogZero, shapeInfo); - - if (shapeInfo.type != ShapeData.PhysicsShapeType.SHAPE_UNKNOWN) - { - DereferenceShape(shapeInfo, true, null); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} Could not decypher shape type. Region={1}, addr={2}", - LogHeader, PhysicsScene.RegionName, cShape.ToString("X")); - } - } - - // Create the geometry information in Bullet for later use. - // The objects needs a hull if it's physical otherwise a mesh is enough. - // if 'forceRebuild' is true, the geometry is unconditionally rebuilt. For meshes and hulls, - // shared geometries will be used. If the parameters of the existing shape are the same - // as this request, the shape is not rebuilt. - // Info in prim.BSShape is updated to the new shape. - // Returns 'true' if the geometry was rebuilt. - // Called at taint-time! - private bool CreateGeom(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_AVATAR) - { - // an avatar capsule is close to a native shape (it is not shared) - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_AVATAR, - ShapeData.FixedShapeKey.KEY_CAPSULE, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,avatarCapsule,shape={1}", prim.LocalID, prim.PhysShape); - ret = true; - haveShape = true; - } - - // Compound shapes are handled special as they are rebuilt from scratch. - // This isn't too great a hardship since most of the child shapes will already been created. - if (!haveShape && prim.PreferredPhysicalShape == ShapeData.PhysicsShapeType.SHAPE_COMPOUND) - { - ret = GetReferenceToCompoundShape(prim, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,compoundShape,shape={1}", prim.LocalID, prim.PhysShape); - haveShape = true; - } - - if (!haveShape) - { - ret = CreateGeomNonSpecial(forceRebuild, prim, shapeCallback); - } - - return ret; - } - - // Create a mesh/hull shape or a native shape if 'nativeShapePossible' is 'true'. - private bool CreateGeomNonSpecial(bool forceRebuild, BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - bool ret = false; - bool haveShape = false; - bool nativeShapePossible = true; - PrimitiveBaseShape pbs = prim.BaseShape; - - // If the prim attributes are simple, this could be a simple Bullet native shape - if (!haveShape - && pbs != null - && nativeShapePossible - && ((pbs.SculptEntry && !PhysicsScene.ShouldMeshSculptedPrim) - || (pbs.ProfileBegin == 0 && pbs.ProfileEnd == 0 - && pbs.ProfileHollow == 0 - && pbs.PathTwist == 0 && pbs.PathTwistBegin == 0 - && pbs.PathBegin == 0 && pbs.PathEnd == 0 - && pbs.PathTaperX == 0 && pbs.PathTaperY == 0 - && pbs.PathScaleX == 100 && pbs.PathScaleY == 100 - && pbs.PathShearX == 0 && pbs.PathShearY == 0) ) ) - { - // It doesn't look like Bullet scales spheres so make sure the scales are all equal - if ((pbs.ProfileShape == ProfileShape.HalfCircle && pbs.PathCurve == (byte)Extrusion.Curve1) - && pbs.Scale.X == pbs.Scale.Y && pbs.Scale.Y == pbs.Scale.Z) - { - haveShape = true; - if (forceRebuild - || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_SPHERE - ) - { - ret = GetReferenceToNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_SPHERE, - ShapeData.FixedShapeKey.KEY_SPHERE, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,sphere,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - if (!haveShape && pbs.ProfileShape == ProfileShape.Square && pbs.PathCurve == (byte)Extrusion.Straight) - { - haveShape = true; - if (forceRebuild - || prim.Scale != prim.Size - || prim.PhysShape.type != ShapeData.PhysicsShapeType.SHAPE_BOX - ) - { - ret = GetReferenceToNativeShape( prim, ShapeData.PhysicsShapeType.SHAPE_BOX, - ShapeData.FixedShapeKey.KEY_BOX, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,box,force={1},shape={2}", - prim.LocalID, forceRebuild, prim.PhysShape); - } - } - } - - // If a simple shape is not happening, create a mesh and possibly a hull. - if (!haveShape && pbs != null) - { - ret = CreateGeomMeshOrHull(prim, shapeCallback); - } - - return ret; - } - - public bool CreateGeomMeshOrHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - - bool ret = false; - // Note that if it's a native shape, the check for physical/non-physical is not - // made. Native shapes work in either case. - if (prim.IsPhysical && PhysicsScene.ShouldUseHullsForPhysicalObjects) - { - // Update prim.BSShape to reference a hull of this shape. - ret = GetReferenceToHull(prim,shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,hull,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - else - { - ret = GetReferenceToMesh(prim, shapeCallback); - DetailLog("{0},BSShapeCollection.CreateGeom,mesh,shape={1},key={2}", - prim.LocalID, prim.PhysShape, prim.PhysShape.shapeKey.ToString("X")); - } - return ret; - } - - // Creates a native shape and assignes it to prim.BSShape. - // "Native" shapes are never shared. they are created here and destroyed in DereferenceShape(). - private bool GetReferenceToNativeShape(BSPhysObject prim, - ShapeData.PhysicsShapeType shapeType, ShapeData.FixedShapeKey shapeKey, - ShapeDestructionCallback shapeCallback) - { - // release any previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - // Bullet native objects are scaled by the Bullet engine so pass the size in - prim.Scale = prim.Size; - - BulletShape newShape = BuildPhysicalNativeShape(prim, shapeType, shapeKey); - - // Don't need to do a 'ReferenceShape()' here because native shapes are not shared. - DetailLog("{0},BSShapeCollection.AddNativeShapeToPrim,create,newshape={1},scale={2}", - prim.LocalID, newShape, prim.Scale); - - prim.PhysShape = newShape; - return true; - } - - private BulletShape BuildPhysicalNativeShape(BSPhysObject prim, ShapeData.PhysicsShapeType shapeType, - ShapeData.FixedShapeKey shapeKey) - { - BulletShape newShape; - // Need to make sure the passed shape information is for the native type. - ShapeData nativeShapeData = new ShapeData(); - nativeShapeData.Type = shapeType; - nativeShapeData.ID = prim.LocalID; - nativeShapeData.Scale = prim.Scale; - nativeShapeData.Size = prim.Scale; - nativeShapeData.MeshKey = (ulong)shapeKey; - nativeShapeData.HullKey = (ulong)shapeKey; - - if (shapeType == ShapeData.PhysicsShapeType.SHAPE_AVATAR) - { - newShape = new BulletShape( - BulletSimAPI.BuildCapsuleShape2(PhysicsScene.World.ptr, 1f, 1f, prim.Scale) - , shapeType); - DetailLog("{0},BSShapeCollection.BuiletPhysicalNativeShape,capsule,scale={1}", prim.LocalID, prim.Scale); - } - else - { - newShape = new BulletShape(BulletSimAPI.BuildNativeShape2(PhysicsScene.World.ptr, nativeShapeData), shapeType); - } - if (newShape.ptr == IntPtr.Zero) - { - PhysicsScene.Logger.ErrorFormat("{0} BuildPhysicalNativeShape failed. ID={1}, shape={2}", - LogHeader, prim.LocalID, shapeType); - } - newShape.shapeKey = (System.UInt64)shapeKey; - newShape.isNativeShape = true; - - return newShape; - } - - // Builds a mesh shape in the physical world and updates prim.BSShape. - // Dereferences previous shape in BSShape and adds a reference for this new shape. - // Returns 'true' of a mesh was actually built. Otherwise . - // Called at taint-time! - private bool GetReferenceToMesh(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape = new BulletShape(IntPtr.Zero); - - float lod; - System.UInt64 newMeshKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if this new shape is the same as last time, don't recreate the mesh - if (newMeshKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_MESH) - return false; - - DetailLog("{0},BSShapeCollection.GetReferenceToMesh,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newMeshKey.ToString("X")); - - // Since we're recreating new, get rid of the reference to the previous shape - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalMesh(prim.PhysObjectName, newMeshKey, prim.BaseShape, prim.Size, lod); - // Take evasive action if the mesh was not constructed. - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - // meshes are already scaled by the meshmerizer - prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.PhysShape = newShape; - - return true; // 'true' means a new shape has been added to this prim - } - - private BulletShape CreatePhysicalMesh(string objName, System.UInt64 newMeshKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - IMesh meshData = null; - IntPtr meshPtr = IntPtr.Zero; - MeshDesc meshDesc; - if (Meshes.TryGetValue(newMeshKey, out meshDesc)) - { - // If the mesh has already been built just use it. - meshPtr = meshDesc.ptr; - } - else - { - // Pass false for physicalness as this creates some sort of bounding box which we don't need - meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - - if (meshData != null) - { - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - float[] verticesAsFloats = new float[vertices.Count * 3]; - int vi = 0; - foreach (OMV.Vector3 vv in vertices) - { - verticesAsFloats[vi++] = vv.X; - verticesAsFloats[vi++] = vv.Y; - verticesAsFloats[vi++] = vv.Z; - } - - // m_log.DebugFormat("{0}: BSShapeCollection.CreatePhysicalMesh: calling CreateMesh. lid={1}, key={2}, indices={3}, vertices={4}", - // LogHeader, prim.LocalID, newMeshKey, indices.Length, vertices.Count); - - meshPtr = BulletSimAPI.CreateMeshShape2(PhysicsScene.World.ptr, - indices.GetLength(0), indices, vertices.Count, verticesAsFloats); - } - } - BulletShape newShape = new BulletShape(meshPtr, ShapeData.PhysicsShapeType.SHAPE_MESH); - newShape.shapeKey = newMeshKey; - - return newShape; - } - - // See that hull shape exists in the physical world and update prim.BSShape. - // We could be creating the hull because scale changed or whatever. - private bool GetReferenceToHull(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - BulletShape newShape; - - float lod; - System.UInt64 newHullKey = ComputeShapeKey(prim.Size, prim.BaseShape, out lod); - - // if the hull hasn't changed, don't rebuild it - if (newHullKey == prim.PhysShape.shapeKey && prim.PhysShape.type == ShapeData.PhysicsShapeType.SHAPE_HULL) - return false; - - DetailLog("{0},BSShapeCollection.GetReferenceToHull,create,oldKey={1},newKey={2}", - prim.LocalID, prim.PhysShape.shapeKey.ToString("X"), newHullKey.ToString("X")); - - // Remove usage of the previous shape. - DereferenceShape(prim.PhysShape, true, shapeCallback); - - newShape = CreatePhysicalHull(prim.PhysObjectName, newHullKey, prim.BaseShape, prim.Size, lod); - newShape = VerifyMeshCreated(newShape, prim); - - ReferenceShape(newShape); - - // hulls are already scaled by the meshmerizer - prim.Scale = new OMV.Vector3(1f, 1f, 1f); - prim.PhysShape = newShape; - return true; // 'true' means a new shape has been added to this prim - } - - List m_hulls; - private BulletShape CreatePhysicalHull(string objName, System.UInt64 newHullKey, PrimitiveBaseShape pbs, OMV.Vector3 size, float lod) - { - - IntPtr hullPtr = IntPtr.Zero; - HullDesc hullDesc; - if (Hulls.TryGetValue(newHullKey, out hullDesc)) - { - // If the hull shape already is created, just use it. - hullPtr = hullDesc.ptr; - } - else - { - // Build a new hull in the physical world - // Pass false for physicalness as this creates some sort of bounding box which we don't need - IMesh meshData = PhysicsScene.mesher.CreateMesh(objName, pbs, size, lod, false); - if (meshData != null) - { - - int[] indices = meshData.getIndexListAsInt(); - List vertices = meshData.getVertexList(); - - //format conversion from IMesh format to DecompDesc format - List convIndices = new List(); - List convVertices = new List(); - for (int ii = 0; ii < indices.GetLength(0); ii++) - { - convIndices.Add(indices[ii]); - } - foreach (OMV.Vector3 vv in vertices) - { - convVertices.Add(new float3(vv.X, vv.Y, vv.Z)); - } - - // setup and do convex hull conversion - m_hulls = new List(); - DecompDesc dcomp = new DecompDesc(); - dcomp.mIndices = convIndices; - dcomp.mVertices = convVertices; - ConvexBuilder convexBuilder = new ConvexBuilder(HullReturn); - // create the hull into the _hulls variable - convexBuilder.process(dcomp); - - // Convert the vertices and indices for passing to unmanaged. - // The hull information is passed as a large floating point array. - // The format is: - // convHulls[0] = number of hulls - // convHulls[1] = number of vertices in first hull - // convHulls[2] = hull centroid X coordinate - // convHulls[3] = hull centroid Y coordinate - // convHulls[4] = hull centroid Z coordinate - // convHulls[5] = first hull vertex X - // convHulls[6] = first hull vertex Y - // convHulls[7] = first hull vertex Z - // convHulls[8] = second hull vertex X - // ... - // convHulls[n] = number of vertices in second hull - // convHulls[n+1] = second hull centroid X coordinate - // ... - // - // TODO: is is very inefficient. Someday change the convex hull generator to return - // data structures that do not need to be converted in order to pass to Bullet. - // And maybe put the values directly into pinned memory rather than marshaling. - int hullCount = m_hulls.Count; - int totalVertices = 1; // include one for the count of the hulls - foreach (ConvexResult cr in m_hulls) - { - totalVertices += 4; // add four for the vertex count and centroid - totalVertices += cr.HullIndices.Count * 3; // we pass just triangles - } - float[] convHulls = new float[totalVertices]; - - convHulls[0] = (float)hullCount; - int jj = 1; - foreach (ConvexResult cr in m_hulls) - { - // copy vertices for index access - float3[] verts = new float3[cr.HullVertices.Count]; - int kk = 0; - foreach (float3 ff in cr.HullVertices) - { - verts[kk++] = ff; - } - - // add to the array one hull's worth of data - convHulls[jj++] = cr.HullIndices.Count; - convHulls[jj++] = 0f; // centroid x,y,z - convHulls[jj++] = 0f; - convHulls[jj++] = 0f; - foreach (int ind in cr.HullIndices) - { - convHulls[jj++] = verts[ind].x; - convHulls[jj++] = verts[ind].y; - convHulls[jj++] = verts[ind].z; - } - } - // create the hull data structure in Bullet - hullPtr = BulletSimAPI.CreateHullShape2(PhysicsScene.World.ptr, hullCount, convHulls); - } - } - - BulletShape newShape = new BulletShape(hullPtr, ShapeData.PhysicsShapeType.SHAPE_HULL); - newShape.shapeKey = newHullKey; - - return newShape; // 'true' means a new shape has been added to this prim - } - - // Callback from convex hull creater with a newly created hull. - // Just add it to our collection of hulls for this shape. - private void HullReturn(ConvexResult result) - { - m_hulls.Add(result); - return; - } - - // Compound shapes are always built from scratch. - // This shouldn't be to bad since most of the parts will be meshes that had been built previously. - private bool GetReferenceToCompoundShape(BSPhysObject prim, ShapeDestructionCallback shapeCallback) - { - // Remove reference to the old shape - // Don't need to do this as the shape is freed when the new root shape is created below. - // DereferenceShape(prim.PhysShape, true, shapeCallback); - - BulletShape cShape = new BulletShape( - BulletSimAPI.CreateCompoundShape2(PhysicsScene.World.ptr, false), ShapeData.PhysicsShapeType.SHAPE_COMPOUND); - - // Create the shape for the root prim and add it to the compound shape. Cannot be a native shape. - CreateGeomMeshOrHull(prim, shapeCallback); - BulletSimAPI.AddChildShapeToCompoundShape2(cShape.ptr, prim.PhysShape.ptr, OMV.Vector3.Zero, OMV.Quaternion.Identity); - DetailLog("{0},BSShapeCollection.GetReferenceToCompoundShape,addRootPrim,compShape={1},rootShape={2}", - prim.LocalID, cShape, prim.PhysShape); - - prim.PhysShape = cShape; - - return true; - } - - // Create a hash of all the shape parameters to be used as a key - // for this particular shape. - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs, out float retLod) - { - // level of detail based on size and type of the object - float lod = PhysicsScene.MeshLOD; - if (pbs.SculptEntry) - lod = PhysicsScene.SculptLOD; - - // Mega prims usually get more detail because one can interact with shape approximations at this size. - float maxAxis = Math.Max(size.X, Math.Max(size.Y, size.Z)); - if (maxAxis > PhysicsScene.MeshMegaPrimThreshold) - lod = PhysicsScene.MeshMegaPrimLOD; - - retLod = lod; - return pbs.GetMeshKey(size, lod); - } - // For those who don't want the LOD - private System.UInt64 ComputeShapeKey(OMV.Vector3 size, PrimitiveBaseShape pbs) - { - float lod; - return ComputeShapeKey(size, pbs, out lod); - } - - // The creation of a mesh or hull can fail if an underlying asset is not available. - // There are two cases: 1) the asset is not in the cache and it needs to be fetched; - // and 2) the asset cannot be converted (like failed decompression of JPEG2000s). - // The first case causes the asset to be fetched. The second case requires - // us to not loop forever. - // Called after creating a physical mesh or hull. If the physical shape was created, - // just return. - private BulletShape VerifyMeshCreated(BulletShape newShape, BSPhysObject prim) - { - // If the shape was successfully created, nothing more to do - if (newShape.ptr != IntPtr.Zero) - return newShape; - - // If this mesh has an underlying asset and we have not failed getting it before, fetch the asset - if (prim.BaseShape.SculptEntry && !prim.LastAssetBuildFailed && prim.BaseShape.SculptTexture != OMV.UUID.Zero) - { - prim.LastAssetBuildFailed = true; - BSPhysObject xprim = prim; - DetailLog("{0},BSShapeCollection.VerifyMeshCreated,fetchAsset,lID={1},lastFailed={2}", - LogHeader, prim.LocalID, prim.LastAssetBuildFailed); - Util.FireAndForget(delegate - { - RequestAssetDelegate assetProvider = PhysicsScene.RequestAssetMethod; - if (assetProvider != null) - { - BSPhysObject yprim = xprim; // probably not necessary, but, just in case. - assetProvider(yprim.BaseShape.SculptTexture, delegate(AssetBase asset) - { - if (!yprim.BaseShape.SculptEntry) - return; - if (yprim.BaseShape.SculptTexture.ToString() != asset.ID) - return; - - yprim.BaseShape.SculptData = asset.Data; - // This will cause the prim to see that the filler shape is not the right - // one and try again to build the object. - // No race condition with the normal shape setting since the rebuild is at taint time. - yprim.ForceBodyShapeRebuild(false); - - }); - } - }); - } - else - { - if (prim.LastAssetBuildFailed) - { - PhysicsScene.Logger.ErrorFormat("{0} Mesh failed to fetch asset. lID={1}, texture={2}", - LogHeader, prim.LocalID, prim.BaseShape.SculptTexture); - } - } - - // While we figure out the real problem, stick a simple native shape on the object. - BulletShape fillinShape = - BuildPhysicalNativeShape(prim, ShapeData.PhysicsShapeType.SHAPE_BOX, ShapeData.FixedShapeKey.KEY_BOX); - - return fillinShape; - } - - // Create a body object in Bullet. - // Updates prim.BSBody with the information about the new body if one is created. - // Returns 'true' if an object was actually created. - // Called at taint-time. - private bool CreateBody(bool forceRebuild, BSPhysObject prim, BulletSim sim, BulletShape shape, - BodyDestructionCallback bodyCallback) - { - bool ret = false; - - // the mesh, hull or native shape must have already been created in Bullet - bool mustRebuild = (prim.PhysBody.ptr == IntPtr.Zero); - - // If there is an existing body, verify it's of an acceptable type. - // If not a solid object, body is a GhostObject. Otherwise a RigidBody. - if (!mustRebuild) - { - CollisionObjectTypes bodyType = (CollisionObjectTypes)BulletSimAPI.GetBodyType2(prim.PhysBody.ptr); - if (prim.IsSolid && bodyType != CollisionObjectTypes.CO_RIGID_BODY - || !prim.IsSolid && bodyType != CollisionObjectTypes.CO_GHOST_OBJECT) - { - // If the collisionObject is not the correct type for solidness, rebuild what's there - mustRebuild = true; - } - } - - if (mustRebuild || forceRebuild) - { - // Free any old body - DereferenceBody(prim.PhysBody, true, bodyCallback); - - BulletBody aBody; - IntPtr bodyPtr = IntPtr.Zero; - if (prim.IsSolid) - { - bodyPtr = BulletSimAPI.CreateBodyFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.RawPosition, prim.RawOrientation); - DetailLog("{0},BSShapeCollection.CreateBody,mesh,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); - } - else - { - bodyPtr = BulletSimAPI.CreateGhostFromShape2(sim.ptr, shape.ptr, - prim.LocalID, prim.ForcePosition, prim.ForceOrientation); - DetailLog("{0},BSShapeCollection.CreateBody,ghost,ptr={1}", prim.LocalID, bodyPtr.ToString("X")); - } - aBody = new BulletBody(prim.LocalID, bodyPtr); - - ReferenceBody(aBody, true); - - prim.PhysBody = aBody; - - ret = true; - } - - return ret; - } - - private bool TryGetMeshByPtr(IntPtr addr, out MeshDesc outDesc) - { - bool ret = false; - MeshDesc foundDesc = new MeshDesc(); - foreach (MeshDesc md in Meshes.Values) - { - if (md.ptr == addr) - { - foundDesc = md; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private bool TryGetHullByPtr(IntPtr addr, out HullDesc outDesc) - { - bool ret = false; - HullDesc foundDesc = new HullDesc(); - foreach (HullDesc hd in Hulls.Values) - { - if (hd.ptr == addr) - { - foundDesc = hd; - ret = true; - break; - } - - } - outDesc = foundDesc; - return ret; - } - - private void DetailLog(string msg, params Object[] args) - { - if (PhysicsScene.PhysicsLogging.Enabled) - PhysicsScene.DetailLog(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs b/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs deleted file mode 100755 index 7c34af29bd..0000000000 --- a/OpenSim/Region/Physics/BulletSPlugin/BSTerrainManager.cs +++ /dev/null @@ -1,479 +0,0 @@ -/* - * 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 copyrightD - * 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.Text; - -using OpenSim.Framework; -using OpenSim.Region.Framework; -using OpenSim.Region.CoreModules; -using OpenSim.Region.Physics.Manager; - -using Nini.Config; -using log4net; - -using OpenMetaverse; - -namespace OpenSim.Region.Physics.BulletSPlugin -{ -public sealed class BSTerrainManager -{ - static string LogHeader = "[BULLETSIM TERRAIN MANAGER]"; - - // These height values are fractional so the odd values will be - // noticable when debugging. - public const float HEIGHT_INITIALIZATION = 24.987f; - public const float HEIGHT_INITIAL_LASTHEIGHT = 24.876f; - public const float HEIGHT_GETHEIGHT_RET = 24.765f; - - // If the min and max height are equal, we reduce the min by this - // amount to make sure that a bounding box is built for the terrain. - public const float HEIGHT_EQUAL_FUDGE = 0.2f; - - public const float TERRAIN_COLLISION_MARGIN = 0.0f; - - // Until the whole simulator is changed to pass us the region size, we rely on constants. - public Vector3 DefaultRegionSize = new Vector3(Constants.RegionSize, Constants.RegionSize, Constants.RegionHeight); - - // The scene that I am part of - private BSScene PhysicsScene { get; set; } - - // The ground plane created to keep thing from falling to infinity. - private BulletBody m_groundPlane; - - // If doing mega-regions, if we're region zero we will be managing multiple - // region terrains since region zero does the physics for the whole mega-region. - private Dictionary m_heightMaps; - - // True of the terrain has been modified. - // Used to force recalculation of terrain height after terrain has been modified - private bool m_terrainModified; - - // If we are doing mega-regions, terrains are added from TERRAIN_ID to m_terrainCount. - // This is incremented before assigning to new region so it is the last ID allocated. - private uint m_terrainCount = BSScene.CHILDTERRAIN_ID - 1; - public uint HighestTerrainID { get {return m_terrainCount; } } - - // If doing mega-regions, this holds our offset from region zero of - // the mega-regions. "parentScene" points to the PhysicsScene of region zero. - private Vector3 m_worldOffset; - // If the parent region (region 0), this is the extent of the combined regions - // relative to the origin of region zero - private Vector3 m_worldMax; - private PhysicsScene MegaRegionParentPhysicsScene { get; set; } - - public BSTerrainManager(BSScene physicsScene) - { - PhysicsScene = physicsScene; - m_heightMaps = new Dictionary(); - m_terrainModified = false; - - // Assume one region of default size - m_worldOffset = Vector3.Zero; - m_worldMax = new Vector3(DefaultRegionSize); - MegaRegionParentPhysicsScene = null; - } - - // Create the initial instance of terrain and the underlying ground plane. - // The objects are allocated in the unmanaged space and the pointers are tracked - // by the managed code. - // The terrains and the groundPlane are not added to the list of PhysObjects. - // This is called from the initialization routine so we presume it is - // safe to call Bullet in real time. We hope no one is moving prims around yet. - public void CreateInitialGroundPlaneAndTerrain() - { - // The ground plane is here to catch things that are trying to drop to negative infinity - BulletShape groundPlaneShape = new BulletShape( - BulletSimAPI.CreateGroundPlaneShape2(BSScene.GROUNDPLANE_ID, 1f, TERRAIN_COLLISION_MARGIN), - ShapeData.PhysicsShapeType.SHAPE_GROUNDPLANE); - m_groundPlane = new BulletBody(BSScene.GROUNDPLANE_ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(groundPlaneShape.ptr, BSScene.GROUNDPLANE_ID, - Vector3.Zero, Quaternion.Identity)); - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr); - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, m_groundPlane.ptr); - // Ground plane does not move - BulletSimAPI.ForceActivationState2(m_groundPlane.ptr, ActivationState.DISABLE_SIMULATION); - // Everything collides with the ground plane. - BulletSimAPI.SetCollisionFilterMask2(m_groundPlane.ptr, - (uint)CollisionFilterGroups.GroundPlaneFilter, (uint)CollisionFilterGroups.GroundPlaneMask); - - Vector3 minTerrainCoords = new Vector3(0f, 0f, HEIGHT_INITIALIZATION - HEIGHT_EQUAL_FUDGE); - Vector3 maxTerrainCoords = new Vector3(DefaultRegionSize.X, DefaultRegionSize.Y, HEIGHT_INITIALIZATION); - int totalHeights = (int)maxTerrainCoords.X * (int)maxTerrainCoords.Y; - float[] initialMap = new float[totalHeights]; - for (int ii = 0; ii < totalHeights; ii++) - { - initialMap[ii] = HEIGHT_INITIALIZATION; - } - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, initialMap, minTerrainCoords, maxTerrainCoords, true); - } - - // Release all the terrain structures we might have allocated - public void ReleaseGroundPlaneAndTerrain() - { - if (m_groundPlane.ptr != IntPtr.Zero) - { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, m_groundPlane.ptr)) - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, m_groundPlane.ptr); - } - m_groundPlane.ptr = IntPtr.Zero; - } - - ReleaseTerrain(); - } - - // Release all the terrain we have allocated - public void ReleaseTerrain() - { - foreach (KeyValuePair kvp in m_heightMaps) - { - if (BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr)) - { - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, kvp.Value.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(kvp.Value.Ptr); - } - } - m_heightMaps.Clear(); - } - - // The simulator wants to set a new heightmap for the terrain. - public void SetTerrain(float[] heightMap) { - float[] localHeightMap = heightMap; - PhysicsScene.TaintedObject("TerrainManager.SetTerrain", delegate() - { - if (m_worldOffset != Vector3.Zero && MegaRegionParentPhysicsScene != null) - { - // If a child of a mega-region, we shouldn't have any terrain allocated for us - ReleaseGroundPlaneAndTerrain(); - // If doing the mega-prim stuff and we are the child of the zero region, - // the terrain is added to our parent - if (MegaRegionParentPhysicsScene is BSScene) - { - DetailLog("{0},SetTerrain.ToParent,offset={1},worldMax={2}", - BSScene.DetailLogZero, m_worldOffset, m_worldMax); - ((BSScene)MegaRegionParentPhysicsScene).TerrainManager.UpdateOrCreateTerrain(BSScene.CHILDTERRAIN_ID, - localHeightMap, m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - } - else - { - // If not doing the mega-prim thing, just change the terrain - DetailLog("{0},SetTerrain.Existing", BSScene.DetailLogZero); - - UpdateOrCreateTerrain(BSScene.TERRAIN_ID, localHeightMap, - m_worldOffset, m_worldOffset + DefaultRegionSize, true); - } - }); - } - - // If called with no mapInfo for the terrain, this will create a new mapInfo and terrain - // based on the passed information. The 'id' should be either the terrain id or - // BSScene.CHILDTERRAIN_ID. If the latter, a new child terrain ID will be allocated and used. - // The latter feature is for creating child terrains for mega-regions. - // If called with a mapInfo in m_heightMaps but the terrain has no body yet (mapInfo.terrainBody.Ptr == 0) - // then a new body and shape is created and the mapInfo is filled. - // This call is used for doing the initial terrain creation. - // If called with a mapInfo in m_heightMaps and there is an existing terrain body, a new - // terrain shape is created and added to the body. - // This call is most often used to update the heightMap and parameters of the terrain. - // (The above does suggest that some simplification/refactoring is in order.) - private void UpdateOrCreateTerrain(uint id, float[] heightMap, Vector3 minCoords, Vector3 maxCoords, bool inTaintTime) - { - DetailLog("{0},BSTerrainManager.UpdateOrCreateTerrain,call,minC={1},maxC={2},inTaintTime={3}", - BSScene.DetailLogZero, minCoords, maxCoords, inTaintTime); - - float minZ = float.MaxValue; - float maxZ = float.MinValue; - Vector2 terrainRegionBase = new Vector2(minCoords.X, minCoords.Y); - - int heightMapSize = heightMap.Length; - for (int ii = 0; ii < heightMapSize; ii++) - { - float height = heightMap[ii]; - if (height < minZ) minZ = height; - if (height > maxZ) maxZ = height; - } - - // The shape of the terrain is from its base to its extents. - minCoords.Z = minZ; - maxCoords.Z = maxZ; - - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainRegionBase, out mapInfo)) - { - // If this is terrain we know about, it's easy to update - - mapInfo.heightMap = heightMap; - mapInfo.minCoords = minCoords; - mapInfo.maxCoords = maxCoords; - mapInfo.minZ = minZ; - mapInfo.maxZ = maxZ; - mapInfo.sizeX = maxCoords.X - minCoords.X; - mapInfo.sizeY = maxCoords.Y - minCoords.Y; - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,call,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:UpdateExisting", delegate() - { - if (MegaRegionParentPhysicsScene != null) - { - // It's possible that Combine() was called after this code was queued. - // If we are a child of combined regions, we don't create any terrain for us. - DetailLog("{0},UpdateOrCreateTerrain:AmACombineChild,taint", BSScene.DetailLogZero); - - // Get rid of any terrain that may have been allocated for us. - ReleaseGroundPlaneAndTerrain(); - - // I hate doing this, but just bail - return; - } - - if (mapInfo.terrainBody.ptr != IntPtr.Zero) - { - // Updating an existing terrain. - DetailLog("{0},UpdateOrCreateTerrain:UpdateExisting,taint,terrainBase={1},minC={2}, maxC={3}, szX={4}, szY={5}", - BSScene.DetailLogZero, terrainRegionBase, mapInfo.minCoords, mapInfo.maxCoords, mapInfo.sizeX, mapInfo.sizeY); - - // Remove from the dynamics world because we're going to mangle this object - BulletSimAPI.RemoveObjectFromWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // Get rid of the old terrain - BulletSimAPI.DestroyObject2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - BulletSimAPI.ReleaseHeightMapInfo2(mapInfo.Ptr); - mapInfo.Ptr = IntPtr.Zero; - - /* - // NOTE: This routine is half here because I can't get the terrain shape replacement - // to work. In the short term, the above three lines completely delete the old - // terrain and the code below recreates one from scratch. - // Hopefully the Bullet community will help me out on this one. - - // First, release the old collision shape (there is only one terrain) - BulletSimAPI.DeleteCollisionShape2(m_physicsScene.World.Ptr, mapInfo.terrainShape.Ptr); - - // Fill the existing height map info with the new location and size information - BulletSimAPI.FillHeightMapInfo2(m_physicsScene.World.Ptr, mapInfo.Ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create a terrain shape based on the new info - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr)); - - // Stuff the shape into the existing terrain body - BulletSimAPI.SetBodyShape2(m_physicsScene.World.Ptr, mapInfo.terrainBody.Ptr, mapInfo.terrainShape.Ptr); - */ - } - // else - { - // Creating a new terrain. - DetailLog("{0},UpdateOrCreateTerrain:CreateNewTerrain,taint,baseX={1},baseY={2},minZ={3},maxZ={4}", - BSScene.DetailLogZero, mapInfo.minCoords.X, mapInfo.minCoords.Y, minZ, maxZ); - - mapInfo.ID = id; - mapInfo.Ptr = BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, mapInfo.ID, - mapInfo.minCoords, mapInfo.maxCoords, mapInfo.heightMap, TERRAIN_COLLISION_MARGIN); - - // Create the terrain shape from the mapInfo - mapInfo.terrainShape = new BulletShape(BulletSimAPI.CreateTerrainShape2(mapInfo.Ptr), - ShapeData.PhysicsShapeType.SHAPE_TERRAIN); - - // The terrain object initial position is at the center of the object - Vector3 centerPos; - centerPos.X = minCoords.X + (mapInfo.sizeX / 2f); - centerPos.Y = minCoords.Y + (mapInfo.sizeY / 2f); - centerPos.Z = minZ + ((maxZ - minZ) / 2f); - - mapInfo.terrainBody = new BulletBody(mapInfo.ID, - BulletSimAPI.CreateBodyWithDefaultMotionState2(mapInfo.terrainShape.ptr, - id, centerPos, Quaternion.Identity)); - } - - // Make sure the entry is in the heightmap table - m_heightMaps[terrainRegionBase] = mapInfo; - - // Set current terrain attributes - BulletSimAPI.SetFriction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainFriction); - BulletSimAPI.SetHitFraction2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainHitFraction); - BulletSimAPI.SetRestitution2(mapInfo.terrainBody.ptr, PhysicsScene.Params.terrainRestitution); - BulletSimAPI.SetCollisionFlags2(mapInfo.terrainBody.ptr, CollisionFlags.CF_STATIC_OBJECT); - - // Return the new terrain to the world of physical objects - BulletSimAPI.AddObjectToWorld2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - // redo its bounding box now that it is in the world - BulletSimAPI.UpdateSingleAabb2(PhysicsScene.World.ptr, mapInfo.terrainBody.ptr); - - BulletSimAPI.SetCollisionFilterMask2(mapInfo.terrainBody.ptr, - (uint)CollisionFilterGroups.TerrainFilter, - (uint)CollisionFilterGroups.TerrainMask); - - // Make sure the new shape is processed. - // BulletSimAPI.Activate2(mapInfo.terrainBody.ptr, true); - // BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.ISLAND_SLEEPING); - BulletSimAPI.ForceActivationState2(mapInfo.terrainBody.ptr, ActivationState.DISABLE_SIMULATION); - - m_terrainModified = true; - }); - } - else - { - // We don't know about this terrain so either we are creating a new terrain or - // our mega-prim child is giving us a new terrain to add to the phys world - - // if this is a child terrain, calculate a unique terrain id - uint newTerrainID = id; - if (newTerrainID >= BSScene.CHILDTERRAIN_ID) - newTerrainID = ++m_terrainCount; - - float[] heightMapX = heightMap; - Vector3 minCoordsX = minCoords; - Vector3 maxCoordsX = maxCoords; - - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,call,id={1}, minC={2}, maxC={3}", - BSScene.DetailLogZero, newTerrainID, minCoords, minCoords); - - // Code that must happen at taint-time - PhysicsScene.TaintedObject(inTaintTime, "BSScene.UpdateOrCreateTerrain:NewTerrain", delegate() - { - DetailLog("{0},UpdateOrCreateTerrain:NewTerrain,taint,baseX={1},baseY={2}", BSScene.DetailLogZero, minCoords.X, minCoords.Y); - // Create a new mapInfo that will be filled with the new info - mapInfo = new BulletHeightMapInfo(id, heightMapX, - BulletSimAPI.CreateHeightMapInfo2(PhysicsScene.World.ptr, newTerrainID, - minCoordsX, maxCoordsX, heightMapX, TERRAIN_COLLISION_MARGIN)); - // Put the unfilled heightmap info into the collection of same - m_heightMaps.Add(terrainRegionBase, mapInfo); - // Build the terrain - UpdateOrCreateTerrain(newTerrainID, heightMap, minCoords, maxCoords, true); - - m_terrainModified = true; - }); - } - } - - // Someday we will have complex terrain with caves and tunnels - public float GetTerrainHeightAtXYZ(Vector3 loc) - { - // For the moment, it's flat and convex - return GetTerrainHeightAtXY(loc.X, loc.Y); - } - - // Given an X and Y, find the height of the terrain. - // Since we could be handling multiple terrains for a mega-region, - // the base of the region is calcuated assuming all regions are - // the same size and that is the default. - // Once the heightMapInfo is found, we have all the information to - // compute the offset into the array. - private float lastHeightTX = 999999f; - private float lastHeightTY = 999999f; - private float lastHeight = HEIGHT_INITIAL_LASTHEIGHT; - private float GetTerrainHeightAtXY(float tX, float tY) - { - // You'd be surprized at the number of times this routine is called - // with the same parameters as last time. - if (!m_terrainModified && lastHeightTX == tX && lastHeightTY == tY) - return lastHeight; - - lastHeightTX = tX; - lastHeightTY = tY; - float ret = HEIGHT_GETHEIGHT_RET; - - int offsetX = ((int)(tX / (int)DefaultRegionSize.X)) * (int)DefaultRegionSize.X; - int offsetY = ((int)(tY / (int)DefaultRegionSize.Y)) * (int)DefaultRegionSize.Y; - Vector2 terrainBaseXY = new Vector2(offsetX, offsetY); - - BulletHeightMapInfo mapInfo; - if (m_heightMaps.TryGetValue(terrainBaseXY, out mapInfo)) - { - float regionX = tX - offsetX; - float regionY = tY - offsetY; - int mapIndex = (int)regionY * (int)mapInfo.sizeY + (int)regionX; - try - { - ret = mapInfo.heightMap[mapIndex]; - } - catch - { - // Sometimes they give us wonky values of X and Y. Give a warning and return something. - PhysicsScene.Logger.WarnFormat("{0} Bad request for terrain height. terrainBase={1}, x={2}, y={3}", - LogHeader, terrainBaseXY, regionX, regionY); - ret = HEIGHT_GETHEIGHT_RET; - } - // DetailLog("{0},BSTerrainManager.GetTerrainHeightAtXY,bX={1},baseY={2},szX={3},szY={4},regX={5},regY={6},index={7},ht={8}", - // BSScene.DetailLogZero, offsetX, offsetY, mapInfo.sizeX, mapInfo.sizeY, regionX, regionY, mapIndex, ret); - } - else - { - PhysicsScene.Logger.ErrorFormat("{0} GetTerrainHeightAtXY: terrain not found: region={1}, x={2}, y={3}", - LogHeader, PhysicsScene.RegionName, tX, tY); - } - m_terrainModified = false; - lastHeight = ret; - return ret; - } - - // Although no one seems to check this, I do support combining. - public bool SupportsCombining() - { - return true; - } - - // This routine is called two ways: - // One with 'offset' and 'pScene' zero and null but 'extents' giving the maximum - // extent of the combined regions. This is to inform the parent of the size - // of the combined regions. - // and one with 'offset' as the offset of the child region to the base region, - // 'pScene' pointing to the parent and 'extents' of zero. This informs the - // child of its relative base and new parent. - public void Combine(PhysicsScene pScene, Vector3 offset, Vector3 extents) - { - m_worldOffset = offset; - m_worldMax = extents; - MegaRegionParentPhysicsScene = pScene; - if (pScene != null) - { - // We are a child. - // We want m_worldMax to be the highest coordinate of our piece of terrain. - m_worldMax = offset + DefaultRegionSize; - } - DetailLog("{0},BSTerrainManager.Combine,offset={1},extents={2},wOffset={3},wMax={4}", - BSScene.DetailLogZero, offset, extents, m_worldOffset, m_worldMax); - } - - // Unhook all the combining that I know about. - public void UnCombine(PhysicsScene pScene) - { - // Just like ODE, for the moment a NOP - DetailLog("{0},BSTerrainManager.UnCombine", BSScene.DetailLogZero); - } - - - private void DetailLog(string msg, params Object[] args) - { - PhysicsScene.PhysicsLogging.Write(msg, args); - } -} -} diff --git a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs index 702bd77096..504bd3c41c 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BulletSimAPI.cs @@ -33,153 +33,38 @@ using OpenMetaverse; namespace OpenSim.Region.Physics.BulletSPlugin { // Classes to allow some type checking for the API -// These hold pointers to allocated objects in the unmanaged space. - -// The physics engine controller class created at initialization public struct BulletSim { - public BulletSim(uint worldId, BSScene bss, IntPtr xx) - { - ptr = xx; - worldID = worldId; - physicsScene = bss; - } - public IntPtr ptr; - public uint worldID; + public BulletSim(uint id, BSScene bss, IntPtr xx) { ID = id; scene = bss; Ptr = xx; } + public uint ID; // The scene is only in here so very low level routines have a handle to print debug/error messages - public BSScene physicsScene; + public BSScene scene; + public IntPtr Ptr; } -// An allocated Bullet btRigidBody public struct BulletBody { - public BulletBody(uint id, IntPtr xx) - { - ID = id; - ptr = xx; - collisionFilter = 0; - collisionMask = 0; - } - public IntPtr ptr; + public BulletBody(uint id, IntPtr xx) { ID = id; Ptr = xx; } + public IntPtr Ptr; public uint ID; - public CollisionFilterGroups collisionFilter; - public CollisionFilterGroups collisionMask; - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } } -public struct BulletShape -{ - public BulletShape(IntPtr xx) - { - ptr = xx; - type=ShapeData.PhysicsShapeType.SHAPE_UNKNOWN; - shapeKey = 0; - isNativeShape = false; - } - public BulletShape(IntPtr xx, ShapeData.PhysicsShapeType typ) - { - ptr = xx; - type = typ; - shapeKey = 0; - isNativeShape = false; - } - public IntPtr ptr; - public ShapeData.PhysicsShapeType type; - public System.UInt64 shapeKey; - public bool isNativeShape; - public override string ToString() - { - StringBuilder buff = new StringBuilder(); - buff.Append(""); - return buff.ToString(); - } -} - - // Constraint type values as defined by Bullet -public enum ConstraintType : int -{ - POINT2POINT_CONSTRAINT_TYPE = 3, - HINGE_CONSTRAINT_TYPE, - CONETWIST_CONSTRAINT_TYPE, - D6_CONSTRAINT_TYPE, - SLIDER_CONSTRAINT_TYPE, - CONTACT_CONSTRAINT_TYPE, - D6_SPRING_CONSTRAINT_TYPE, - MAX_CONSTRAINT_TYPE -} - -// An allocated Bullet btConstraint public struct BulletConstraint { - public BulletConstraint(IntPtr xx) - { - ptr = xx; - } - public IntPtr ptr; -} - -// An allocated HeightMapThing which holds various heightmap info. -// Made a class rather than a struct so there would be only one -// instance of this and C# will pass around pointers rather -// than making copies. -public class BulletHeightMapInfo -{ - public BulletHeightMapInfo(uint id, float[] hm, IntPtr xx) { - ID = id; - Ptr = xx; - heightMap = hm; - terrainRegionBase = new Vector2(0f, 0f); - minCoords = new Vector3(100f, 100f, 25f); - maxCoords = new Vector3(101f, 101f, 26f); - minZ = maxZ = 0f; - sizeX = sizeY = 256f; - } - public uint ID; + public BulletConstraint(IntPtr xx) { Ptr = xx; } public IntPtr Ptr; - public float[] heightMap; - public Vector2 terrainRegionBase; - public Vector3 minCoords; - public Vector3 maxCoords; - public float sizeX, sizeY; - public float minZ, maxZ; - public BulletShape terrainShape; - public BulletBody terrainBody; } // =============================================================================== [StructLayout(LayoutKind.Sequential)] -public struct ConvexHull +public struct ConvexHull { Vector3 Offset; int VertexCount; Vector3[] Vertices; } [StructLayout(LayoutKind.Sequential)] -public struct ShapeData +public struct ShapeData { public enum PhysicsShapeType { @@ -190,11 +75,7 @@ public struct ShapeData SHAPE_CYLINDER = 4, SHAPE_SPHERE = 5, SHAPE_MESH = 6, - SHAPE_HULL = 7, - // following defined by BulletSim - SHAPE_GROUNDPLANE = 20, - SHAPE_TERRAIN = 21, - SHAPE_COMPOUND = 22, + SHAPE_HULL = 7 }; public uint ID; public PhysicsShapeType Type; @@ -210,25 +91,13 @@ public struct ShapeData public float Restitution; public float Collidable; // true of things bump into this public float Static; // true if a static object. Otherwise gravity, etc. - public float Solid; // true if object cannot be passed through - public Vector3 Size; // note that bools are passed as floats since bool size changes by language and architecture public const float numericTrue = 1f; public const float numericFalse = 0f; - - // The native shapes have predefined shape hash keys - public enum FixedShapeKey : ulong - { - KEY_BOX = 1, - KEY_SPHERE = 2, - KEY_CONE = 3, - KEY_CYLINDER = 4, - KEY_CAPSULE = 5, - } } [StructLayout(LayoutKind.Sequential)] -public struct SweepHit +public struct SweepHit { public uint ID; public float Fraction; @@ -284,7 +153,6 @@ public struct ConfigurationParameters public float terrainHitFraction; public float terrainRestitution; public float avatarFriction; - public float avatarStandingFriction; public float avatarDensity; public float avatarRestitution; public float avatarCapsuleRadius; @@ -300,45 +168,18 @@ public struct ConfigurationParameters public float shouldEnableFrictionCaching; public float numberOfSolverIterations; - public float linksetImplementation; public float linkConstraintUseFrameOffset; public float linkConstraintEnableTransMotor; public float linkConstraintTransMotorMaxVel; public float linkConstraintTransMotorMaxForce; public float linkConstraintERP; public float linkConstraintCFM; - public float linkConstraintSolverIterations; - - public float physicsLoggingFrames; public const float numericTrue = 1f; public const float numericFalse = 0f; } - -// The states a bullet collision object can have -public enum ActivationState : uint -{ - ACTIVE_TAG = 1, - ISLAND_SLEEPING, - WANTS_DEACTIVATION, - DISABLE_DEACTIVATION, - DISABLE_SIMULATION, -} - -public enum CollisionObjectTypes : int -{ - CO_COLLISION_OBJECT = 1 << 0, - CO_RIGID_BODY = 1 << 1, - CO_GHOST_OBJECT = 1 << 2, - CO_SOFT_BODY = 1 << 3, - CO_HF_FLUID = 1 << 4, - CO_USER_TYPE = 1 << 5, -} - -// Values used by Bullet and BulletSim to control object properties. -// Bullet's "CollisionFlags" has more to do with operations on the -// object (if collisions happen, if gravity effects it, ...). +// Values used by Bullet and BulletSim to control collisions public enum CollisionFlags : uint { CF_STATIC_OBJECT = 1 << 0, @@ -350,54 +191,9 @@ public enum CollisionFlags : uint CF_DISABLE_SPU_COLLISION_PROCESS = 1 << 6, // Following used by BulletSim to control collisions BS_SUBSCRIBE_COLLISION_EVENTS = 1 << 10, - BS_FLOATS_ON_WATER = 1 << 11, - BS_NONE = 0, - BS_ALL = 0xFFFFFFFF, - - // These are the collision flags switched depending on physical state. - // The other flags are used for other things and should not be fooled with. - BS_ACTIVE = CF_STATIC_OBJECT - | CF_KINEMATIC_OBJECT - | CF_NO_CONTACT_RESPONSE -}; - -// Values for collisions groups and masks -public enum CollisionFilterGroups : uint -{ - // Don't use the bit definitions!! Define the use in a - // filter/mask definition below. This way collision interactions - // are more easily debugged. - BNoneFilter = 0, - BDefaultFilter = 1 << 0, - BStaticFilter = 1 << 1, - BKinematicFilter = 1 << 2, - BDebrisFilter = 1 << 3, - BSensorTrigger = 1 << 4, - BCharacterFilter = 1 << 5, - BAllFilter = 0xFFFFFFFF, - // Filter groups defined by BulletSim - BGroundPlaneFilter = 1 << 10, - BTerrainFilter = 1 << 11, - BRaycastFilter = 1 << 12, - BSolidFilter = 1 << 13, - BLinksetFilter = 1 << 14, - - // The collsion filters and masked are defined in one place -- don't want them scattered - AvatarFilter = BCharacterFilter, - AvatarMask = BAllFilter, - ObjectFilter = BSolidFilter, - ObjectMask = BAllFilter, - StaticObjectFilter = BStaticFilter, - StaticObjectMask = BAllFilter, - LinksetFilter = BLinksetFilter, - LinksetMask = BAllFilter & ~BLinksetFilter, - VolumeDetectFilter = BSensorTrigger, - VolumeDetectMask = ~BSensorTrigger, - TerrainFilter = BTerrainFilter, - TerrainMask = BAllFilter & ~BStaticFilter, - GroundPlaneFilter = BGroundPlaneFilter, - GroundPlaneMask = BAllFilter - + BS_VOLUME_DETECT_OBJECT = 1 << 11, + BS_PHANTOM_OBJECT = 1 << 12, + BS_PHYSICAL_OBJECT = 1 << 13, }; // CFM controls the 'hardness' of the constraint. 0=fixed, 0..1=violatable. Default=0 @@ -425,23 +221,14 @@ public enum ConstraintParamAxis : int // =============================================================================== static class BulletSimAPI { -// Link back to the managed code for outputting log messages -[UnmanagedFunctionPointer(CallingConvention.Cdecl)] -public delegate void DebugLogCallback([MarshalAs(UnmanagedType.LPStr)]string msg); - [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] [return: MarshalAs(UnmanagedType.LPStr)] public static extern string GetVersion(); -/* Remove the linkage to the old api methods [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, - int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray, - DebugLogCallback logRoutine); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void CreateInitialGroundPlaneAndTerrain(uint worldID); +public static extern uint Initialize(Vector3 maxPosition, IntPtr parms, + int maxCollisions, IntPtr collisionArray, + int maxUpdates, IntPtr updateArray); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetHeightmap(uint worldID, [MarshalAs(UnmanagedType.LPArray)] float[] heightMap); @@ -455,19 +242,19 @@ public static extern bool UpdateParameter(uint worldID, uint localID, // =============================================================================== [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, +public static extern int PhysicsStep(uint worldID, float timeStep, int maxSubSteps, float fixedTimeStep, + out int updatedEntityCount, out IntPtr updatedEntitiesPtr, out int collidersCount, out IntPtr collidersPtr); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, +public static extern bool CreateHull(uint worldID, System.UInt64 meshKey, int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls ); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, +public static extern bool CreateMesh(uint worldID, System.UInt64 meshKey, int indexCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); @@ -481,6 +268,23 @@ public static extern bool DestroyMesh(uint worldID, System.UInt64 meshKey); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool CreateObject(uint worldID, ShapeData shapeData); +/* Remove old functionality +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void CreateLinkset(uint worldID, int objectCount, ShapeData[] shapeDatas); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern void AddConstraint(uint worldID, uint id1, uint id2, + Vector3 frame1, Quaternion frame1rot, + Vector3 frame2, Quaternion frame2rot, + Vector3 lowLinear, Vector3 hiLinear, Vector3 lowAngular, Vector3 hiAngular); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool RemoveConstraintByID(uint worldID, uint id1); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool RemoveConstraint(uint worldID, uint id1, uint id2); + */ + [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetObjectPosition(uint WorldID, uint id); @@ -496,7 +300,6 @@ public static extern bool SetObjectVelocity(uint worldID, uint id, Vector3 veloc [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetObjectAngularVelocity(uint worldID, uint id, Vector3 angularVelocity); -// Set the current force acting on the object [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool SetObjectForce(uint worldID, uint id, Vector3 force); @@ -537,8 +340,10 @@ 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); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void SetDebugLogCallback(DebugLogCallback callback); @@ -553,7 +358,6 @@ public static extern void SetDebugLogCallback(DebugLogCallback callback); // The names have a "2" tacked on. This will be removed as the C# code gets rebuilt // and the old code is removed. -// Functions use while converting from API1 to API2. Can be removed when totally converted. [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr GetSimHandle2(uint worldID); @@ -564,25 +368,23 @@ public static extern IntPtr GetBodyHandleWorldID2(uint worldID, uint id); public static extern IntPtr GetBodyHandle2(IntPtr world, uint id); // =============================================================================== -// Initialization and simulation [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Initialize2(Vector3 maxPosition, IntPtr parms, int maxCollisions, IntPtr collisionArray, - int maxUpdates, IntPtr updateArray, - DebugLogCallback logRoutine); + int maxUpdates, IntPtr updateArray); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool UpdateParameter2(IntPtr world, uint localID, String parm, float value); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetHeightMap2(IntPtr world, float[] heightmap); +public static extern void SetHeightmap2(IntPtr world, float[] heightmap); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void Shutdown2(IntPtr sim); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSteps, float fixedTimeStep, - out int updatedEntityCount, + out int updatedEntityCount, out IntPtr updatedEntitiesPtr, out int collidersCount, out IntPtr collidersPtr); @@ -590,98 +392,23 @@ public static extern int PhysicsStep2(IntPtr world, float timeStep, int maxSubSt [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool PushUpdate2(IntPtr obj); -// ===================================================================================== -// Mesh, hull, shape and body creation helper routines +/* [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateMeshShape2(IntPtr world, - int indicesCount, [MarshalAs(UnmanagedType.LPArray)] int[] indices, - int verticesCount, [MarshalAs(UnmanagedType.LPArray)] float[] vertices ); +public static extern IntPtr CreateMesh2(IntPtr world, int indicesCount, int* indices, int verticesCount, float* vertices ); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHullShape2(IntPtr world, - int hullCount, [MarshalAs(UnmanagedType.LPArray)] float[] hulls); +public static extern bool BuildHull2(IntPtr world, IntPtr mesh); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildHullShapeFromMesh2(IntPtr world, IntPtr meshShape); +public static extern bool ReleaseHull2(IntPtr world, IntPtr mesh); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildNativeShape2(IntPtr world, ShapeData shapeData); +public static extern bool DestroyMesh2(IntPtr world, IntPtr mesh); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsNativeShape2(IntPtr shape); +public static extern IntPtr CreateObject2(IntPtr world, ShapeData shapeData); +*/ -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr BuildCapsuleShape2(IntPtr world, float radius, float height, Vector3 scale); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateCompoundShape2(IntPtr sim, bool enableDynamicAabbTree); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetNumberOfCompoundChildren2(IntPtr cShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddChildShapeToCompoundShape2(IntPtr cShape, IntPtr addShape, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr RemoveChildShapeFromCompoundShapeIndex2(IntPtr cShape, int indx); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveChildShapeFromCompoundShape2(IntPtr cShape, IntPtr removeShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr DuplicateCollisionShape2(IntPtr sim, IntPtr srcShape, uint id); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShapeAndInfo2(IntPtr sim, IntPtr shape, uint id, IntPtr constructionInfo); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool DeleteCollisionShape2(IntPtr world, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetBodyType2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateBodyWithDefaultMotionState2(IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGhostFromShape2(IntPtr sim, IntPtr shape, uint id, Vector3 pos, Quaternion rot); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr AllocateBodyInfo2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ReleaseBodyInfo2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DestroyObject2(IntPtr sim, IntPtr obj); - -// ===================================================================================== -// Terrain creation and helper routines -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateHeightMapInfo2(IntPtr sim, uint id, Vector3 minCoords, Vector3 maxCoords, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr FillHeightMapInfo2(IntPtr sim, IntPtr mapInfo, uint id, Vector3 minCoords, Vector3 maxCoords, - [MarshalAs(UnmanagedType.LPArray)] float[] heightMap, float collisionMargin); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool ReleaseHeightMapInfo2(IntPtr heightMapInfo); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateGroundPlaneShape2(uint id, float height, float collisionMargin); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr CreateTerrainShape2(IntPtr mapInfo); - -// ===================================================================================== -// Constraint creation and helper routines [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern IntPtr Create6DofConstraint2(IntPtr world, IntPtr obj1, IntPtr obj2, Vector3 frame1loc, Quaternion frame1rot, @@ -706,7 +433,7 @@ public static extern void SetConstraintEnable2(IntPtr constrain, float numericTr public static extern void SetConstraintNumSolverIterations2(IntPtr constrain, float iterations); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool SetFrames2(IntPtr constrain, +public static extern bool SetFrames2(IntPtr constrain, Vector3 frameA, Quaternion frameArot, Vector3 frameB, Quaternion frameBrot); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] @@ -733,108 +460,11 @@ public static extern bool SetConstraintParam2(IntPtr constrain, ConstraintParams [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern bool DestroyConstraint2(IntPtr world, IntPtr constrain); -// ===================================================================================== -// btCollisionWorld entries [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateSingleAabb2(IntPtr world, IntPtr obj); +public static extern Vector3 AddObjectToWorld2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateAabbs2(IntPtr world); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool GetForceUpdateAllAabbs2(IntPtr world); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetForceUpdateAllAabbs2(IntPtr world, bool force); - -// ===================================================================================== -// btDynamicsWorld entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool AddObjectToWorld2(IntPtr world, IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveObjectFromWorld2(IntPtr world, IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool AddConstraintToWorld2(IntPtr world, IntPtr constrain, bool disableCollisionsBetweenLinkedObjects); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool RemoveConstraintFromWorld2(IntPtr world, IntPtr constrain); -// ===================================================================================== -// btCollisionObject entries -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAnisotripicFriction2(IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 SetAnisotripicFriction2(IntPtr constrain, Vector3 frict); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool HasAnisotripicFriction2(IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetContactProcessingThreshold2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetContactProcessingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsStaticObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsKinematicObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsStaticOrKinematicObject2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool HasContactResponse2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCollisionShape2(IntPtr sim, IntPtr obj, IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetCollisionShape2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetActivationState2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetActivationState2(IntPtr obj, int state); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetDeactivationTime2(IntPtr obj, float dtime); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetDeactivationTime2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ForceActivationState2(IntPtr obj, ActivationState state); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Activate2(IntPtr obj, bool forceActivation); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsActive2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetRestitution2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetRestitution2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetFriction2(IntPtr obj, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetFriction2(IntPtr obj); - - /* Haven't defined the type 'Transform' -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetWorldTransform2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void setWorldTransform2(IntPtr obj, Transform trans); - */ +public static extern Vector3 RemoveObjectFromWorld2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern Vector3 GetPosition2(IntPtr obj); @@ -843,290 +473,85 @@ public static extern Vector3 GetPosition2(IntPtr obj); public static extern Quaternion GetOrientation2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); +public static extern bool SetTranslation2(IntPtr obj, Vector3 position, Quaternion rotation); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetBroadphaseHandle2(IntPtr obj); +public static extern bool SetVelocity2(IntPtr obj, Vector3 velocity); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetBroadphaseHandle2(IntPtr obj, IntPtr handle); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetInterpolationWorldTransform2(IntPtr obj); +public static extern bool SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationWorldTransform2(IntPtr obj, Transform trans); - */ +public static extern bool SetObjectForce2(IntPtr obj, Vector3 force); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationLinearVelocity2(IntPtr obj, Vector3 vel); +public static extern bool AddObjectForce2(IntPtr obj, Vector3 force); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationAngularVelocity2(IntPtr obj, Vector3 vel); +public static extern bool SetCcdMotionThreshold2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInterpolationVelocity2(IntPtr obj, Vector3 linearVel, Vector3 angularVel); +public static extern bool SetCcdSweepSphereRadius2(IntPtr obj, float val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetHitFraction2(IntPtr obj); +public static extern bool SetDamping2(IntPtr obj, float lin_damping, float ang_damping); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetHitFraction2(IntPtr obj, float val); +public static extern bool SetDeactivationTime2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetContactProcessingThreshold2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetFriction2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetRestitution2(IntPtr obj, float val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetLinearVelocity2(IntPtr obj, Vector3 val); + +[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] +public static extern bool SetInterpolation2(IntPtr obj, Vector3 lin, Vector3 ang); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern CollisionFlags GetCollisionFlags2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags SetCollisionFlags2(IntPtr obj, CollisionFlags flags); +public static extern IntPtr SetCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); +public static extern IntPtr AddToCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern CollisionFlags RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); +public static extern IntPtr RemoveFromCollisionFlags2(IntPtr obj, CollisionFlags flags); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdMotionThreshold2(IntPtr obj); +public static extern bool SetMassProps2(IntPtr obj, float mass, Vector3 inertia); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdMotionThreshold2(IntPtr obj, float val); +public static extern bool UpdateInertiaTensor2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetCcdSweptSphereRadius2(IntPtr obj); +public static extern bool SetGravity2(IntPtr obj, Vector3 val); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCcdSweptSphereRadius2(IntPtr obj, float val); +public static extern IntPtr ClearForces2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetUserPointer2(IntPtr obj); +public static extern IntPtr ClearAllForces2(IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetUserPointer2(IntPtr obj, IntPtr val); +public static extern bool SetMargin2(IntPtr obj, float val); -// ===================================================================================== -// btRigidBody entries [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyGravity2(IntPtr obj); +public static extern bool UpdateSingleAabb2(IntPtr world, IntPtr obj); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetGravity2(IntPtr obj, Vector3 val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetGravity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetDamping2(IntPtr obj, float lin_damping, float ang_damping); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetLinearDamping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularDamping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetLinearSleepingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularSleepingThreshold2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyDamping2(IntPtr obj, float timeStep); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetMassProps2(IntPtr obj, float mass, Vector3 inertia); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLinearFactor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLinearFactor2(IntPtr obj, Vector3 factor); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCenterOfMassTransform2(IntPtr obj, Transform trans); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCenterOfMassByPosRot2(IntPtr obj, Vector3 pos, Quaternion rot); - -// Add a force to the object as if its mass is one. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyCentralForce2(IntPtr obj, Vector3 force); - -// Set the force being applied to the object as if its mass is one. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetObjectForce2(IntPtr obj, Vector3 force); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTotalForce2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetTotalTorque2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetInvInertiaDiagLocal2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetInvInertiaDiagLocal2(IntPtr obj, Vector3 inert); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetSleepingThresholds2(IntPtr obj, float lin_threshold, float ang_threshold); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyTorque2(IntPtr obj, Vector3 torque); - -// Apply force at the given point. Will add torque to the object. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyForce2(IntPtr obj, Vector3 force, Vector3 pos); - -// Apply impulse to the object. Same as "ApplycentralForce" but force scaled by object's mass. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyCentralImpulse2(IntPtr obj, Vector3 imp); - -// Apply impulse to the object's torque. Force is scaled by object's mass. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyTorqueImpulse2(IntPtr obj, Vector3 imp); - -// Apply impulse at the point given. For is scaled by object's mass and effects both linear and angular forces. -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ApplyImpulse2(IntPtr obj, Vector3 imp, Vector3 pos); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ClearForces2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void ClearAllForces2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateInertiaTensor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetCenterOfMassPosition2(IntPtr obj); - - /* -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Transform GetCenterOfMassTransform2(IntPtr obj); - */ - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLinearVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAngularVelocity2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLinearVelocity2(IntPtr obj, Vector3 val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularVelocity2(IntPtr obj, Vector3 angularVelocity); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetVelocityInLocalPoint2(IntPtr obj, Vector3 pos); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void Translate2(IntPtr obj, Vector3 trans); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void UpdateDeactivation2(IntPtr obj, float timeStep); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool WantsSleeping2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularFactor2(IntPtr obj, float factor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetAngularFactorV2(IntPtr obj, Vector3 factor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetAngularFactor2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsInWorld2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void AddConstraintRef2(IntPtr obj, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void RemoveConstraintRef2(IntPtr obj, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern IntPtr GetConstraintRef2(IntPtr obj, int index); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetNumConstraintRefs2(IntPtr obj); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetCollisionFilterMask2(IntPtr body, uint filter, uint mask); - -// ===================================================================================== -// btCollisionShape entries - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetAngularMotionDisc2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetContactBreakingThreshold2(IntPtr shape, float defaultFactor); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsPolyhedral2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConvex2d2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConvex2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsNonMoving2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsConcave2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsCompound2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsSoftBody2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern bool IsInfinite2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetLocalScaling2(IntPtr shape, Vector3 scale); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 GetLocalScaling2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern Vector3 CalculateLocalInertia2(IntPtr shape, float mass); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern int GetShapeType2(IntPtr shape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void SetMargin2(IntPtr shape, float val); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern float GetMargin2(IntPtr shape); - -// ===================================================================================== -// Debugging -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpRigidBody2(IntPtr sim, IntPtr collisionObject); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpCollisionShape2(IntPtr sim, IntPtr collisionShape); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpConstraint2(IntPtr sim, IntPtr constrain); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpAllInfo2(IntPtr sim); - -[DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] -public static extern void DumpMapInfo2(IntPtr sim, IntPtr manInfo); +public static extern bool DestroyObject2(IntPtr world, uint id); [DllImport("BulletSim", CallingConvention = CallingConvention.Cdecl), SuppressUnmanagedCodeSecurity] public static extern void DumpPhysicsStatistics2(IntPtr sim); diff --git a/OpenSim/Region/Physics/Manager/PhysicsActor.cs b/OpenSim/Region/Physics/Manager/PhysicsActor.cs index 5af6373f0e..14f65b8e14 100644 --- a/OpenSim/Region/Physics/Manager/PhysicsActor.cs +++ b/OpenSim/Region/Physics/Manager/PhysicsActor.cs @@ -340,12 +340,6 @@ namespace OpenSim.Region.Physics.Manager /// Getting this returns the velocity calculated by physics scene updates, using factors such as target velocity, /// time to accelerate and collisions. /// - public virtual Vector3 TargetVelocity - { - get { return Velocity; } - set { Velocity = value; } - } - public abstract Vector3 Velocity { get; set; } public abstract Vector3 Torque { get; set; } diff --git a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs index c73655791b..f3b0630843 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODECharacter.cs @@ -100,7 +100,7 @@ namespace OpenSim.Region.Physics.OdePlugin private bool m_hackSentFly = false; private int m_requestedUpdateFrequency = 0; private Vector3 m_taintPosition; - internal bool m_avatarplanted = false; + /// /// Hold set forces so we can process them outside physics calculations. This prevents race conditions if we set force /// while calculatios are going on @@ -413,7 +413,7 @@ namespace OpenSim.Region.Physics.OdePlugin set { m_iscollidingObj = value; - if (value && !m_avatarplanted) + if (value) m_pidControllerActive = false; else m_pidControllerActive = true; diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index a59f63fcdd..2e78de5fe4 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -66,14 +66,6 @@ namespace OpenSim.Region.Physics.OdePlugin public int ExpectedCollisionContacts { get { return m_expectedCollisionContacts; } } private int m_expectedCollisionContacts = 0; - /// - /// Gets collide bits so that we can still perform land collisions if a mesh fails to load. - /// - private int BadMeshAssetCollideBits - { - get { return m_isphysical ? (int)CollisionCategories.Land : 0; } - } - /// /// Is this prim subject to physics? Even if not, it's still solid for collision purposes. /// @@ -164,7 +156,7 @@ namespace OpenSim.Region.Physics.OdePlugin private PrimitiveBaseShape _pbs; private OdeScene _parent_scene; - + /// /// The physics space which contains prim geometries /// @@ -3341,6 +3333,7 @@ Console.WriteLine(" JointCreateFixed"); m_material = pMaterial; } + private void CheckMeshAsset() { if (_pbs.SculptEntry && !m_assetFailed && _pbs.SculptTexture != UUID.Zero) @@ -3350,14 +3343,14 @@ Console.WriteLine(" JointCreateFixed"); { RequestAssetDelegate assetProvider = _parent_scene.RequestAssetMethod; if (assetProvider != null) - assetProvider(_pbs.SculptTexture, MeshAssetReceived); + assetProvider(_pbs.SculptTexture, MeshAssetReveived); }); } } - private void MeshAssetReceived(AssetBase asset) + void MeshAssetReveived(AssetBase asset) { - if (asset != null && asset.Data != null && asset.Data.Length > 0) + if (asset.Data != null && asset.Data.Length > 0) { if (!_pbs.SculptEntry) return; @@ -3370,12 +3363,6 @@ Console.WriteLine(" JointCreateFixed"); m_taintshape = true; _parent_scene.AddPhysicsActorTaint(this); } - else - { - m_log.WarnFormat( - "[ODE PRIM]: Could not get mesh/sculpt asset {0} for {1} at {2} in {3}", - _pbs.SculptTexture, Name, _position, _parent_scene.Name); - } } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs index d53bd90b61..7a50c4c66a 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdeScene.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdeScene.cs @@ -501,8 +501,6 @@ namespace OpenSim.Region.Physics.OdePlugin public int physics_logging_interval = 0; public bool physics_logging_append_existing_logfile = false; - private bool avplanted = false; - private bool av_av_collisions_off = false; public d.Vector3 xyz = new d.Vector3(128.1640f, 128.3079f, 25.7600f); public d.Vector3 hpr = new d.Vector3(125.5000f, -17.0000f, 0.0000f); @@ -646,9 +644,6 @@ namespace OpenSim.Region.Physics.OdePlugin avMovementDivisorWalk = physicsconfig.GetFloat("av_movement_divisor_walk", 1.3f); avMovementDivisorRun = physicsconfig.GetFloat("av_movement_divisor_run", 0.8f); avCapRadius = physicsconfig.GetFloat("av_capsule_radius", 0.37f); - avplanted = physicsconfig.GetBoolean("av_planted", false); - av_av_collisions_off = physicsconfig.GetBoolean("av_av_collisions_off", false); - IsAvCapsuleTilted = physicsconfig.GetBoolean("av_capsule_tilted", false); contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", 80); @@ -668,8 +663,6 @@ namespace OpenSim.Region.Physics.OdePlugin meshSculptLOD = physicsconfig.GetFloat("mesh_lod", 32f); MeshSculptphysicalLOD = physicsconfig.GetFloat("mesh_physical_lod", 16f); m_filterCollisions = physicsconfig.GetBoolean("filter_collisions", false); - - if (Environment.OSVersion.Platform == PlatformID.Unix) { @@ -1316,10 +1309,6 @@ namespace OpenSim.Region.Physics.OdePlugin if ((p1 is OdePrim) && (((OdePrim)p1).m_isVolumeDetect)) skipThisContact = true; // No collision on volume detect prims - if (av_av_collisions_off) - if ((p1 is OdeCharacter) && (p2 is OdeCharacter)) - skipThisContact = true; - if (!skipThisContact && (p2 is OdePrim) && (((OdePrim)p2).m_isVolumeDetect)) skipThisContact = true; // No collision on volume detect prims @@ -1983,8 +1972,7 @@ namespace OpenSim.Region.Physics.OdePlugin newAv.Flying = isFlying; newAv.MinimumGroundFlightOffset = minimumGroundFlightOffset; - newAv.m_avatarplanted = avplanted; - + return newAv; } @@ -1999,7 +1987,6 @@ namespace OpenSim.Region.Physics.OdePlugin internal void AddCharacter(OdeCharacter chr) { - chr.m_avatarplanted = avplanted; if (!_characters.Contains(chr)) { _characters.Add(chr); @@ -4320,4 +4307,4 @@ namespace OpenSim.Region.Physics.OdePlugin m_stats[ODEPrimUpdateFrameMsStatName] = 0; } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 905540d36e..3144d76432 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -39,8 +39,11 @@ using OpenSim.Framework.Console; using OpenSim.Region.Physics.Manager; using Mono.Addins; +[assembly: Addin("RegionCombinerModule", "0.1")] +[assembly: AddinDependency("OpenSim", "0.5")] namespace OpenSim.Region.RegionCombinerModule { + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule")] public class RegionCombinerModule : ISharedRegionModule, IRegionCombinerModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -719,21 +722,21 @@ namespace OpenSim.Region.RegionCombinerModule rootConn.ClientEventForwarder = new RegionCombinerClientEventForwarder(rootConn); // Sets up the CoarseLocationUpdate forwarder for this root region - scene.EventManager.OnNewPresence += SetCoarseLocationDelegate; + scene.EventManager.OnNewPresence += SetCourseLocationDelegate; // Adds this root region to a dictionary of regions that are connectable m_regions.Add(scene.RegionInfo.originRegionID, rootConn); } } - private void SetCoarseLocationDelegate(ScenePresence presence) + private void SetCourseLocationDelegate(ScenePresence presence) { - presence.SetSendCoarseLocationMethod(SendCoarseLocationUpdates); + presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); } // This delegate was refactored for non-combined regions. // This combined region version will not use the pre-compiled lists of locations and ids - private void SendCoarseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) + private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) { RegionConnections connectiondata = null; lock (m_regions) @@ -756,18 +759,18 @@ namespace OpenSim.Region.RegionCombinerModule } }); - DistributeCoarseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); + DistributeCourseLocationUpdates(CoarseLocations, AvatarUUIDs, connectiondata, presence); } - private void DistributeCoarseLocationUpdates(List locations, List uuids, + private void DistributeCourseLocationUpdates(List locations, List uuids, RegionConnections connectiondata, ScenePresence rootPresence) { RegionData[] rdata = connectiondata.ConnectedRegions.ToArray(); //List clients = new List(); - Dictionary updates = new Dictionary(); + Dictionary updates = new Dictionary(); // Root Region entry - RegionCoarseLocationStruct rootupdatedata = new RegionCoarseLocationStruct(); + RegionCourseLocationStruct rootupdatedata = new RegionCourseLocationStruct(); rootupdatedata.Locations = new List(); rootupdatedata.Uuids = new List(); rootupdatedata.Offset = Vector2.Zero; @@ -781,7 +784,7 @@ namespace OpenSim.Region.RegionCombinerModule foreach (RegionData regiondata in rdata) { Vector2 offset = new Vector2(regiondata.Offset.X, regiondata.Offset.Y); - RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); + RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; @@ -807,7 +810,7 @@ namespace OpenSim.Region.RegionCombinerModule if (!updates.ContainsKey(offset)) { // This shouldn't happen - RegionCoarseLocationStruct updatedata = new RegionCoarseLocationStruct(); + RegionCourseLocationStruct updatedata = new RegionCourseLocationStruct(); updatedata.Locations = new List(); updatedata.Uuids = new List(); updatedata.Offset = offset; diff --git a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs index 224ac9947c..53a678f82f 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCourseLocation.cs @@ -33,7 +33,7 @@ using OpenSim.Framework; namespace OpenSim.Region.RegionCombinerModule { - struct RegionCoarseLocationStruct + struct RegionCourseLocationStruct { public List Locations; public List Uuids; diff --git a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml b/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml deleted file mode 100644 index 13cb8b6dc5..0000000000 --- a/OpenSim/Region/RegionCombinerModule/Resources/RegionCombinerModule.addin.xml +++ /dev/null @@ -1,14 +0,0 @@ - - - - - - - - - - - - - - diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 3bbdbe83bc..82de06f3c8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -59,7 +59,6 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; using PresenceInfo = OpenSim.Services.Interfaces.PresenceInfo; using PrimType = OpenSim.Region.Framework.Scenes.PrimType; using AssetLandmark = OpenSim.Framework.AssetLandmark; -using RegionFlags = OpenSim.Framework.RegionFlags; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; @@ -113,7 +112,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected Dictionary m_userInfoCache = new Dictionary(); protected int EMAIL_PAUSE_TIME = 20; // documented delay value for smtp. - protected ISoundModule m_SoundModule = null; // protected Timer m_ShoutSayTimer; protected int m_SayShoutCount = 0; @@ -161,7 +159,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_TransferModule = m_ScriptEngine.World.RequestModuleInterface(); m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); - m_SoundModule = m_ScriptEngine.World.RequestModuleInterface(); AsyncCommands = new AsyncCommandManager(ScriptEngine); } @@ -344,7 +341,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return GetLinkParts(m_host, linkType); } - public static List GetLinkParts(SceneObjectPart part, int linkType) + private List GetLinkParts(SceneObjectPart part, int linkType) { List ret = new List(); if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) @@ -429,40 +426,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return key; } - /// - /// Return the UUID of the asset matching the specified key or name - /// and asset type. - /// - /// - /// - /// - protected UUID KeyOrName(string k, AssetType type) + // convert a LSL_Rotation to a Quaternion + public static Quaternion Rot2Quaternion(LSL_Rotation r) { - UUID key; - - if (!UUID.TryParse(k, out key)) - { - TaskInventoryItem item = m_host.Inventory.GetInventoryItem(k); - if (item != null && item.Type == (int)type) - key = item.AssetID; - } - else - { - lock (m_host.TaskInventory) - { - foreach (KeyValuePair item in m_host.TaskInventory) - { - if (item.Value.Type == (int)type && item.Value.Name == k) - { - key = item.Value.ItemID; - break; - } - } - } - } - - - return key; + Quaternion q = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + q.Normalize(); + return q; } //These are the implementations of the various ll-functions used by the LSL scripts. @@ -1271,7 +1240,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llGround(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; + Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, + (float)offset.y, + (float)offset.z); //Get the slope normal. This gives us the equation of the plane tangent to the slope. LSL_Vector vsn = llGroundNormal(offset); @@ -1521,22 +1492,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part == null || part.ParentGroup.IsDeleted) return; - // First we need to check whether or not we need to clamp the size of a physics-enabled prim + if (scale.x < 0.01) + scale.x = 0.01; + if (scale.y < 0.01) + scale.y = 0.01; + if (scale.z < 0.01) + scale.z = 0.01; + PhysicsActor pa = part.ParentGroup.RootPart.PhysActor; + if (pa != null && pa.IsPhysical) { - scale.x = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.x)); - scale.y = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.y)); - scale.z = Math.Max(World.m_minPhys, Math.Min(World.m_maxPhys, scale.z)); - } - else - { - // If not physical, then we clamp the scale to the non-physical min/max - scale.x = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.x)); - scale.y = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.y)); - scale.z = Math.Max(World.m_minNonphys, Math.Min(World.m_maxNonphys, scale.z)); + if (scale.x > World.m_maxPhys) + scale.x = World.m_maxPhys; + if (scale.y > World.m_maxPhys) + scale.y = World.m_maxPhys; + if (scale.z > World.m_maxPhys) + scale.z = World.m_maxPhys; } + if (scale.x > World.m_maxNonphys) + scale.x = World.m_maxNonphys; + if (scale.y > World.m_maxNonphys) + scale.y = World.m_maxNonphys; + if (scale.z > World.m_maxNonphys) + scale.z = World.m_maxNonphys; + Vector3 tmp = part.Scale; tmp.X = (float)scale.x; tmp.Y = (float)scale.y; @@ -1609,7 +1590,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (face == ScriptBaseClass.ALL_SIDES) face = SceneObjectPart.ALL_SIDES; - m_host.SetFaceColorAlpha(face, color, null); + m_host.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); } public void SetTexGen(SceneObjectPart part, int face,int style) @@ -2221,7 +2202,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api pos.x > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a east-adjacent region. pos.y < -10.0 || // return FALSE if more than 10 meters into a south-adjacent region. pos.y > (Constants.RegionSize + 10) || // return FALSE if more than 10 meters into a north-adjacent region. - pos.z > Constants.RegionHeight // return FALSE if altitude than 4096m + pos.z > 4096 // return FALSE if altitude than 4096m ) ) { @@ -2232,15 +2213,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // this could possibly be done in the above else-if block, but we're doing the check here to keep the code easier to read. Vector3 objectPos = m_host.ParentGroup.RootPart.AbsolutePosition; - LandData here = World.GetLandData(objectPos); - LandData there = World.GetLandData(pos); + LandData here = World.GetLandData((float)objectPos.X, (float)objectPos.Y); + LandData there = World.GetLandData((float)pos.x, (float)pos.y); // we're only checking prim limits if it's moving to a different parcel under the assumption that if the object got onto the parcel without exceeding the prim limits. bool sameParcel = here.GlobalID == there.GlobalID; - if (!sameParcel && !World.Permissions.CanRezObject( - m_host.ParentGroup.PrimCount, m_host.ParentGroup.OwnerID, pos)) + if (!sameParcel && !World.Permissions.CanObjectEntry(m_host.UUID, false, new Vector3((float)pos.x, (float)pos.y, (float)pos.z))) { return 0; } @@ -2299,15 +2279,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part.ParentGroup.RootPart == part) { SceneObjectGroup parent = part.ParentGroup; - if (!World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos)) + Vector3 dest = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); + if (!World.Permissions.CanObjectEntry(parent.UUID, false, dest)) return; Util.FireAndForget(delegate(object x) { - parent.UpdateGroupPosition((Vector3)toPos); + parent.UpdateGroupPosition(dest); }); } else { - part.OffsetPosition = (Vector3)toPos; + part.OffsetPosition = new Vector3((float)toPos.x, (float)toPos.y, (float)toPos.z); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); @@ -2317,7 +2298,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGetPos() { m_host.AddScriptLPS(1); - return m_host.GetWorldPosition(); + Vector3 pos = m_host.GetWorldPosition(); + return new LSL_Vector(pos.X, pos.Y, pos.Z); } public LSL_Vector llGetLocalPos() @@ -2344,9 +2326,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api pos = part.AbsolutePosition; } -// m_log.DebugFormat("[LSL API]: Returning {0} in GetPartLocalPos()", pos); - - return new LSL_Vector(pos); + return new LSL_Vector(pos.X, pos.Y, pos.Z); } public void llSetRot(LSL_Rotation rot) @@ -2354,18 +2334,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // try to let this work as in SL... - if (m_host.ParentID == 0) + if (m_host.LinkNum < 2) { - // special case: If we are root, rotate complete SOG to new rotation - SetRot(m_host, rot); + // Special case: If we are root, rotate complete SOG to new + // rotation. + // We are root if the link number is 0 (single prim) or 1 + // (root prim). ParentID may be nonzero in attachments and + // using it would cause attachments and HUDs to rotate + // to the wrong positions. + + SetRot(m_host, Rot2Quaternion(rot)); } else { // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. - SceneObjectPart rootPart = m_host.ParentGroup.RootPart; - if (rootPart != null) // better safe than sorry + SceneObjectPart rootPart; + if (m_host.ParentGroup != null) // better safe than sorry { - SetRot(m_host, rootPart.RotationOffset * (Quaternion)rot); + rootPart = m_host.ParentGroup.RootPart; + if (rootPart != null) + SetRot(m_host, rootPart.RotationOffset * Rot2Quaternion(rot)); } } @@ -2375,7 +2363,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLocalRot(LSL_Rotation rot) { m_host.AddScriptLPS(1); - SetRot(m_host, rot); + + SetRot(m_host, Rot2Quaternion(rot)); ScriptSleep(200); } @@ -2487,7 +2476,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (local != 0) force *= llGetRot(); - m_host.ParentGroup.RootPart.SetForce(force); + m_host.ParentGroup.RootPart.SetForce(new Vector3((float)force.x, (float)force.y, (float)force.z)); } } @@ -2499,7 +2488,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - force = m_host.ParentGroup.RootPart.GetForce(); + Vector3 tmpForce = m_host.ParentGroup.RootPart.GetForce(); + force.x = tmpForce.X; + force.y = tmpForce.Y; + force.z = tmpForce.Z; } return force; @@ -2508,8 +2500,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llTarget(LSL_Vector position, double range) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerTargetWaypoint(position, - (float)range); + return m_host.ParentGroup.registerTargetWaypoint( + new Vector3((float)position.x, (float)position.y, (float)position.z), (float)range); } public void llTargetRemove(int number) @@ -2521,7 +2513,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llRotTarget(LSL_Rotation rot, double error) { m_host.AddScriptLPS(1); - return m_host.ParentGroup.registerRotTargetWaypoint(rot, (float)error); + return m_host.ParentGroup.registerRotTargetWaypoint( + new Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s), (float)error); } public void llRotTargetRemove(int number) @@ -2533,7 +2526,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llMoveToTarget(LSL_Vector target, double tau) { m_host.AddScriptLPS(1); - m_host.MoveToTarget(target, (float)tau); + m_host.MoveToTarget(new Vector3((float)target.x, (float)target.y, (float)target.z), (float)tau); } public void llStopMoveToTarget() @@ -2546,7 +2539,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); //No energy force yet - Vector3 v = force; + Vector3 v = new Vector3((float)force.x, (float)force.y, (float)force.z); if (v.Length() > 20000.0f) { v.Normalize(); @@ -2559,13 +2552,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llApplyRotationalImpulse(LSL_Vector force, int local) { m_host.AddScriptLPS(1); - m_host.ParentGroup.RootPart.ApplyAngularImpulse(force, local != 0); + m_host.ParentGroup.RootPart.ApplyAngularImpulse(new Vector3((float)force.x, (float)force.y, (float)force.z), local != 0); } public void llSetTorque(LSL_Vector torque, int local) { m_host.AddScriptLPS(1); - m_host.ParentGroup.RootPart.SetAngularImpulse(torque, local != 0); + m_host.ParentGroup.RootPart.SetAngularImpulse(new Vector3((float)torque.x, (float)torque.y, (float)torque.z), local != 0); } public LSL_Vector llGetTorque() @@ -2675,32 +2668,63 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // send the sound, once, to all clients in range - if (m_SoundModule != null) - { - m_SoundModule.SendSound(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, false, 0, - 0, false, false); - } + m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, false, false); } + // Xantor 20080528 we should do this differently. + // 1) apply the sound to the object + // 2) schedule full update + // just sending the sound out once doesn't work so well when other avatars come in view later on + // or when the prim gets moved, changed, sat on, whatever + // see large number of mantises (mantes?) + // 20080530 Updated to remove code duplication + // 20080530 Stop sound if there is one, otherwise volume only changes don't work public void llLoopSound(string sound, double volume) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) - { - m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), - volume, 20, false); - } + + if (m_host.Sound != UUID.Zero) + llStopSound(); + + m_host.Sound = KeyOrName(sound); + m_host.SoundGain = volume; + m_host.SoundFlags = 1; // looping + m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? + + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); } public void llLoopSoundMaster(string sound, double volume) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) + m_host.ParentGroup.LoopSoundMasterPrim = m_host; + lock (m_host.ParentGroup.LoopSoundSlavePrims) { - m_SoundModule.LoopSound(m_host.UUID, KeyOrName(sound), - volume, 20, true); + foreach (SceneObjectPart prim in m_host.ParentGroup.LoopSoundSlavePrims) + { + if (prim.Sound != UUID.Zero) + llStopSound(); + + prim.Sound = KeyOrName(sound); + prim.SoundGain = volume; + prim.SoundFlags = 1; // looping + prim.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? + + prim.ScheduleFullUpdate(); + prim.SendFullUpdateToAllClients(); + } } + if (m_host.Sound != UUID.Zero) + llStopSound(); + + m_host.Sound = KeyOrName(sound); + m_host.SoundGain = volume; + m_host.SoundFlags = 1; // looping + m_host.SoundRadius = 20; // Magic number, 20 seems reasonable. Make configurable? + + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); } public void llLoopSoundSlave(string sound, double volume) @@ -2717,39 +2741,61 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); // send the sound, once, to all clients in range - if (m_SoundModule != null) - { - m_SoundModule.SendSound(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, false, 0, - 0, true, false); - } + m_host.SendSound(KeyOrName(sound).ToString(), volume, false, 0, 0, true, false); } public void llTriggerSound(string sound, double volume) { m_host.AddScriptLPS(1); - // send the sound, once, to all clients in rangeTrigger or play an attached sound in this part's inventory. - if (m_SoundModule != null) - { - m_SoundModule.SendSound(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, true, 0, 0, - false, false); - } + // send the sound, once, to all clients in range + m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, 0, false, false); } + // Xantor 20080528: Clear prim data of sound instead public void llStopSound() { m_host.AddScriptLPS(1); - - if (m_SoundModule != null) - m_SoundModule.StopSound(m_host.UUID); + if (m_host.ParentGroup.LoopSoundSlavePrims.Contains(m_host)) + { + if (m_host.ParentGroup.LoopSoundMasterPrim == m_host) + { + foreach (SceneObjectPart part in m_host.ParentGroup.LoopSoundSlavePrims) + { + part.Sound = UUID.Zero; + part.SoundGain = 0; + part.SoundFlags = 0; + part.SoundRadius = 0; + part.ScheduleFullUpdate(); + part.SendFullUpdateToAllClients(); + } + m_host.ParentGroup.LoopSoundMasterPrim = null; + m_host.ParentGroup.LoopSoundSlavePrims.Clear(); + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundGain = 0; + m_host.SoundFlags = 0; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } + } + else + { + m_host.Sound = UUID.Zero; + m_host.SoundGain = 0; + m_host.SoundFlags = 0; + m_host.SoundRadius = 0; + m_host.ScheduleFullUpdate(); + m_host.SendFullUpdateToAllClients(); + } } public void llPreloadSound(string sound) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) - m_SoundModule.PreloadSound(m_host.UUID, KeyOrName(sound), 0); + m_host.PreloadSound(sound); ScriptSleep(1000); } @@ -3077,10 +3123,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } + Vector3 llpos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Vector3 llvel = new Vector3((float)vel.x, (float)vel.y, (float)vel.z); + // need the magnitude later // float velmag = (float)Util.GetMagnitude(llvel); - SceneObjectGroup new_group = World.RezObject(m_host, item, pos, rot, vel, param); + SceneObjectGroup new_group = World.RezObject(m_host, item, llpos, Rot2Quaternion(rot), llvel, param); // If either of these are null, then there was an unknown error. if (new_group == null) @@ -3107,11 +3156,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api PhysicsActor pa = new_group.RootPart.PhysActor; - if (pa != null && pa.IsPhysical && (Vector3)vel != Vector3.Zero) + if (pa != null && pa.IsPhysical && llvel != Vector3.Zero) { float groupmass = new_group.GetMass(); - vel *= -groupmass; - llApplyImpulse(vel, 0); + llvel *= -groupmass; + llApplyImpulse(new LSL_Vector(llvel.X, llvel.Y,llvel.Z), 0); } // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) return; @@ -3162,7 +3211,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - m_host.StartLookAt((Quaternion)(r3 * r2 * r1), (float)strength, (float)damping); + m_host.StartLookAt(Rot2Quaternion(r3 * r2 * r1), (float)strength, (float)damping); } } @@ -3588,7 +3637,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - m_host.RotLookAt(target, (float)strength, (float)damping); + m_host.RotLookAt(Rot2Quaternion(target), (float)strength, (float)damping); } } @@ -3669,7 +3718,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected void TargetOmega(SceneObjectPart part, LSL_Vector axis, double spinrate, double gain) { - part.UpdateAngularVelocity(axis * spinrate); + part.UpdateAngularVelocity(new Vector3((float)(axis.x * spinrate), (float)(axis.y * spinrate), (float)(axis.z * spinrate))); } public LSL_Integer llGetStartParameter() @@ -3883,7 +3932,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api try { foreach (SceneObjectPart part in parts) - part.SetFaceColorAlpha(face, color, null); + part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); } finally { @@ -4109,16 +4158,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } /// - /// Returns the name of the child prim or seated avatar matching the - /// specified link number. - /// - /// - /// The number of a link in the linkset or a link-related constant. - /// - /// - /// The name determined to match the specified link number. - /// - /// /// The rules governing the returned name are not simple. The only /// time a blank name is returned is if the target prim has a blank /// name. If no prim with the given link number can be found then @@ -4146,14 +4185,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Mentions NULL_KEY being returned /// http://wiki.secondlife.com/wiki/LlGetLinkName /// Mentions using the LINK_* constants, some of which are negative - /// + /// public LSL_String llGetLinkName(int linknum) { m_host.AddScriptLPS(1); - // simplest case, this prims link number - if (linknum == m_host.LinkNum || linknum == ScriptBaseClass.LINK_THIS) - return m_host.Name; - // parse for sitting avatare-names List nametable = new List(); World.ForEachRootScenePresence(delegate(ScenePresence presence) @@ -4177,6 +4212,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return nametable[totalprims - linknum]; } + // simplest case, this prims link number + if (m_host.LinkNum == linknum) + return m_host.Name; + // Single prim if (m_host.LinkNum == 0) { @@ -4325,7 +4364,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.RegionInfo.RegionName+" "+ m_host.AbsolutePosition.ToString(), agentItem.ID, true, m_host.AbsolutePosition, - bucket, true); + bucket); ScenePresence sp; @@ -4363,7 +4402,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetText(string text, LSL_Vector color, double alpha) { m_host.AddScriptLPS(1); - Vector3 av3 = Util.Clip(color, 0.0f, 1.0f); + 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)); if (text.Length > 254) text = text.Remove(254); @@ -4590,11 +4631,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(5000); } - public void llTeleportAgent(string agent, string destination, LSL_Vector targetPos, LSL_Vector targetLookAt) + public void llTeleportAgent(string agent, string destination, LSL_Vector pos, LSL_Vector lookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); + Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); + if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4623,13 +4667,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector targetPos, LSL_Vector targetLookAt) + public void llTeleportAgentGlobalCoords(string agent, LSL_Vector global_coords, LSL_Vector pos, LSL_Vector lookAt) { m_host.AddScriptLPS(1); UUID agentId = new UUID(); ulong regionHandle = Utils.UIntsToLong((uint)global_coords.x, (uint)global_coords.y); + Vector3 targetPos = new Vector3((float)pos.x, (float)pos.y, (float)pos.z); + Vector3 targetLookAt = new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z); if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); @@ -4731,7 +4777,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } // TODO: Parameter check logic required. - m_host.CollisionSound = KeyOrName(impact_sound, AssetType.Sound); + UUID soundId = UUID.Zero; + if (!UUID.TryParse(impact_sound, out soundId)) + { + TaskInventoryItem item = m_host.Inventory.GetInventoryItem(impact_sound); + + if (item != null && item.Type == (int)AssetType.Sound) + soundId = item.AssetID; + } + + m_host.CollisionSound = soundId; m_host.CollisionSoundVolume = (float)impact_volume; m_host.CollisionSoundType = 1; } @@ -4917,7 +4972,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api distance_attenuation = 1f / normalized_units; } - Vector3 applied_linear_impulse = impulse; + Vector3 applied_linear_impulse = new Vector3((float)impulse.x, (float)impulse.y, (float)impulse.z); { float impulse_length = applied_linear_impulse.Length(); @@ -5565,15 +5620,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// separated list. There is a space after /// each comma. /// + public LSL_String llList2CSV(LSL_List src) { + + string ret = String.Empty; + int x = 0; + m_host.AddScriptLPS(1); - return string.Join(", ", - (new List(src.Data)).ConvertAll(o => - { - return o.ToString(); - }).ToArray()); + if (src.Data.Length > 0) + { + ret = src.Data[x++].ToString(); + for (; x < src.Data.Length; x++) + { + ret += ", "+src.Data[x].ToString(); + } + } + + return ret; } /// @@ -5872,36 +5937,27 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Returns the index of the first occurrence of test /// in src. /// - /// Source list - /// List to search for - /// - /// The index number of the point in src where test was found if it was found. - /// Otherwise returns -1 - /// + public LSL_Integer llListFindList(LSL_List src, LSL_List test) { + int index = -1; int length = src.Length - test.Length + 1; m_host.AddScriptLPS(1); // If either list is empty, do not match + if (src.Length != 0 && test.Length != 0) { for (int i = 0; i < length; i++) { - // Why this piece of insanity? This is because most script constants are C# value types (e.g. int) - // rather than wrapped LSL types. Such a script constant does not have int.Equal(LSL_Integer) code - // and so the comparison fails even if the LSL_Integer conceptually has the same value. - // Therefore, here we test Equals on both the source and destination objects. - // However, a future better approach may be use LSL struct script constants (e.g. LSL_Integer(1)). - if (src.Data[i].Equals(test.Data[0]) || test.Data[0].Equals(src.Data[i])) + if (src.Data[i].Equals(test.Data[0])) { int j; for (j = 1; j < test.Length; j++) - if (!(src.Data[i+j].Equals(test.Data[j]) || test.Data[j].Equals(src.Data[i+j]))) + if (!src.Data[i+j].Equals(test.Data[j])) break; - if (j == test.Length) { index = i; @@ -5912,18 +5968,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } return index; + } public LSL_String llGetObjectName() { m_host.AddScriptLPS(1); - return m_host.Name !=null ? m_host.Name : String.Empty; + return m_host.Name!=null?m_host.Name:String.Empty; } public void llSetObjectName(string name) { m_host.AddScriptLPS(1); - m_host.Name = name != null ? name : String.Empty; + m_host.Name = name!=null?name:String.Empty; } public LSL_String llGetDate() @@ -6097,7 +6154,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api flags |= ScriptBaseClass.AGENT_SITTING; } - if (agent.Animator.Animations.ImplicitDefaultAnimation.AnimID + if (agent.Animator.Animations.DefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { flags |= ScriptBaseClass.AGENT_SITTING; @@ -6254,16 +6311,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); List parts = GetLinkParts(linknumber); - - try + if (parts.Count > 0) { - foreach (SceneObjectPart part in parts) + try + { + foreach (var part in parts) + { + SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); + } + } + finally { - SetTextureAnim(part, mode, face, sizex, sizey, start, length, rate); } - } - finally - { } } @@ -6293,12 +6352,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector bottom_south_west) { m_host.AddScriptLPS(1); - if (m_SoundModule != null) - { - m_SoundModule.TriggerSoundLimited(m_host.UUID, - KeyOrName(sound, AssetType.Sound), volume, - bottom_south_west, top_north_east); - } + float radius1 = (float)llVecDist(llGetPos(), top_north_east); + float radius2 = (float)llVecDist(llGetPos(), bottom_south_west); + float radius = Math.Abs(radius1 - radius2); + m_host.SendSound(KeyOrName(sound).ToString(), volume, true, 0, radius, false, false); } public void llEjectFromLand(string pest) @@ -6484,7 +6541,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Plug the x,y coordinates of the slope normal into the equation of the plane to get //the height of that point on the plane. The resulting vector gives the slope. - Vector3 vsl = vsn; + Vector3 vsl = new Vector3(); + vsl.X = (float)vsn.x; + vsl.Y = (float)vsn.y; vsl.Z = (float)(((vsn.x * vsn.x) + (vsn.y * vsn.y)) / (-1 * vsn.z)); vsl.Normalize(); //Normalization might be overkill here @@ -6495,7 +6554,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llGroundNormal(LSL_Vector offset) { m_host.AddScriptLPS(1); - Vector3 pos = m_host.GetWorldPosition() + (Vector3)offset; + Vector3 pos = m_host.GetWorldPosition() + new Vector3((float)offset.x, + (float)offset.y, + (float)offset.z); // Clamp to valid position if (pos.X < 0) pos.X = 0; @@ -6660,7 +6721,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List parts = GetLinkParts(linknumber); - foreach (SceneObjectPart part in parts) + foreach (var part in parts) { SetParticleSystem(part, rules); } @@ -6904,17 +6965,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (m_TransferModule != null) { byte[] bucket = new byte[] { (byte)AssetType.Folder }; - - Vector3 pos = m_host.AbsolutePosition; - + GridInstantMessage msg = new GridInstantMessage(World, - m_host.OwnerID, m_host.Name, destID, + m_host.UUID, m_host.Name + ", an object owned by " + + resolveName(m_host.OwnerID) + ",", destID, (byte)InstantMessageDialog.TaskInventoryOffered, - false, string.Format("'{0}'", category), -// We won't go so far as to add a SLURL, but this is the format used by LL as of 2012-10-06 -// false, string.Format("'{0}' ( http://slurl.com/secondlife/{1}/{2}/{3}/{4} )", category, World.Name, (int)pos.X, (int)pos.Y, (int)pos.Z), - folderID, false, pos, - bucket, false); + false, category + "\n" + m_host.Name + " is located at " + + World.RegionInfo.RegionName + " " + + m_host.AbsolutePosition.ToString(), + folderID, true, m_host.AbsolutePosition, + bucket); m_TransferModule.SendInstantMessage(msg, delegate(bool success) {}); } @@ -6950,7 +7010,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, vec); + m_host.ParentGroup.RootPart.SetVehicleVectorParam(param, + new Vector3((float)vec.x, (float)vec.y, (float)vec.z)); } } @@ -6962,7 +7023,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_host.ParentGroup.IsDeleted) { - m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, rot); + m_host.ParentGroup.RootPart.SetVehicleRotationParam(param, Rot2Quaternion(rot)); } } @@ -6992,8 +7053,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) rot.s = 1; // ZERO_ROTATION = 0,0,0,1 - part.SitTargetPosition = offset; - part.SitTargetOrientation = rot; + part.SitTargetPosition = new Vector3((float)offset.x, (float)offset.y, (float)offset.z); + part.SitTargetOrientation = Rot2Quaternion(rot); part.ParentGroup.HasGroupChanged = true; } @@ -7096,13 +7157,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetCameraEyeOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraEyeOffset(offset); + m_host.SetCameraEyeOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); } public void llSetCameraAtOffset(LSL_Vector offset) { m_host.AddScriptLPS(1); - m_host.SetCameraAtOffset(offset); + m_host.SetCameraAtOffset(new Vector3((float)offset.x, (float)offset.y, (float)offset.z)); } public LSL_String llDumpList2String(LSL_List src, string seperator) @@ -7124,7 +7185,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer llScriptDanger(LSL_Vector pos) { m_host.AddScriptLPS(1); - bool result = World.ScriptDanger(m_host.LocalId, pos); + bool result = World.ScriptDanger(m_host.LocalId, new Vector3((float)pos.x, (float)pos.y, (float)pos.z)); if (result) { return 1; @@ -7706,7 +7767,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules, "llSetPrimitiveParams"); + setLinkPrimParams(ScriptBaseClass.LINK_THIS, rules); ScriptSleep(200); } @@ -7715,12 +7776,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); - setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParamsFast"); - - ScriptSleep(200); + setLinkPrimParams(linknumber, rules); } - private void setLinkPrimParams(int linknumber, LSL_List rules, string originFunc) + private void setLinkPrimParams(int linknumber, LSL_List rules) { List parts = new List(); List prims = GetLinkParts(linknumber); @@ -7731,16 +7790,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api parts.Add(p); LSL_List remaining = null; - uint rulesParsed = 0; if (parts.Count > 0) { foreach (object part in parts) { if (part is SceneObjectPart) - remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((SceneObjectPart)part, rules); else - remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((ScenePresence)part, rules); } while ((object)remaining != null && remaining.Length > 2) @@ -7759,9 +7817,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api foreach (object part in parts) { if (part is SceneObjectPart) - remaining = SetPrimParams((SceneObjectPart)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((SceneObjectPart)part, rules); else - remaining = SetPrimParams((ScenePresence)part, rules, originFunc, ref rulesParsed); + remaining = SetPrimParams((ScenePresence)part, rules); } } } @@ -7799,7 +7857,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void llSetLinkPrimitiveParams(int linknumber, LSL_List rules) { - setLinkPrimParams(linknumber, rules, "llSetLinkPrimitiveParams"); llSetLinkPrimitiveParamsFast(linknumber, rules); ScriptSleep(200); } @@ -7827,13 +7884,195 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new Vector3((float)x, (float)y, (float)z); } - protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules, string originFunc, ref uint rulesParsed) + protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules) + { + //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. + + int idx = 0; + + bool positionChanged = false; + Vector3 finalPos = Vector3.Zero; + + try + { + while (idx < rules.Length) + { + int code = rules.GetLSLIntegerItem(idx++); + + int remain = rules.Length - idx; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_POSITION: + case (int)ScriptBaseClass.PRIM_POS_LOCAL: + { + if (remain < 1) + return null; + + LSL_Vector v; + v = rules.GetVector3Item(idx++); + + SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); + if (part == null) + break; + + LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; + LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + if (part.LinkNum > 1) + { + localRot = GetPartLocalRot(part); + localPos = GetPartLocalPos(part); + } + + v -= localPos; + v /= localRot; + + LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); + + v = v + 2 * sitOffset; + + av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); + av.SendAvatarDataToAllAgents(); + + } + break; + + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + case (int)ScriptBaseClass.PRIM_ROTATION: + { + if (remain < 1) + return null; + + LSL_Rotation r; + r = rules.GetQuaternionItem(idx++); + + SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); + if (part == null) + break; + + LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; + LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; + + if (part.LinkNum > 1) + localRot = GetPartLocalRot(part); + + r = r * llGetRootRotation() / localRot; + av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); + av.SendAvatarDataToAllAgents(); + } + break; + + // parse rest doing nothing but number of parameters error check + case (int)ScriptBaseClass.PRIM_SIZE: + case (int)ScriptBaseClass.PRIM_MATERIAL: + case (int)ScriptBaseClass.PRIM_PHANTOM: + case (int)ScriptBaseClass.PRIM_PHYSICS: + case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: + case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + case (int)ScriptBaseClass.PRIM_NAME: + case (int)ScriptBaseClass.PRIM_DESC: + if (remain < 1) + return null; + idx++; + break; + + case (int)ScriptBaseClass.PRIM_GLOW: + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + case (int)ScriptBaseClass.PRIM_TEXGEN: + if (remain < 2) + return null; + idx += 2; + break; + + case (int)ScriptBaseClass.PRIM_TYPE: + if (remain < 3) + return null; + code = (int)rules.GetLSLIntegerItem(idx++); + remain = rules.Length - idx; + switch (code) + { + case (int)ScriptBaseClass.PRIM_TYPE_BOX: + case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: + case (int)ScriptBaseClass.PRIM_TYPE_PRISM: + if (remain < 6) + return null; + idx += 6; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: + if (remain < 5) + return null; + idx += 5; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_TORUS: + case (int)ScriptBaseClass.PRIM_TYPE_TUBE: + case (int)ScriptBaseClass.PRIM_TYPE_RING: + if (remain < 11) + return null; + idx += 11; + break; + + case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: + if (remain < 2) + return null; + idx += 2; + break; + } + break; + + case (int)ScriptBaseClass.PRIM_COLOR: + case (int)ScriptBaseClass.PRIM_TEXT: + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + case (int)ScriptBaseClass.PRIM_OMEGA: + if (remain < 3) + return null; + idx += 3; + break; + + case (int)ScriptBaseClass.PRIM_TEXTURE: + case (int)ScriptBaseClass.PRIM_POINT_LIGHT: + case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: + if (remain < 5) + return null; + idx += 5; + break; + + case (int)ScriptBaseClass.PRIM_FLEXIBLE: + if (remain < 7) + return null; + + idx += 7; + break; + + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return null; + + return rules.GetSublist(idx, -1); + } + } + } + + finally + { + if (positionChanged) + { + av.OffsetPosition = finalPos; +// av.SendAvatarDataToAllAgents(); + av.SendTerseUpdateToAllClients(); + positionChanged = false; + } + } + return null; + } + + protected LSL_List SetPrimParams(SceneObjectPart part, LSL_List rules) { if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) return null; int idx = 0; - int idxStart = 0; SceneObjectGroup parentgrp = part.ParentGroup; @@ -7844,11 +8083,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { while (idx < rules.Length) { - ++rulesParsed; int code = rules.GetLSLIntegerItem(idx++); int remain = rules.Length - idx; - idxStart = idx; int face; LSL_Vector v; @@ -7878,17 +8115,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return null; LSL_Rotation q = rules.GetQuaternionItem(idx++); + SceneObjectPart rootPart = parentgrp.RootPart; // try to let this work as in SL... - if (part.ParentID == 0) + if (rootPart == part) { // special case: If we are root, rotate complete SOG to new rotation - SetRot(part, q); + SetRot(part, Rot2Quaternion(q)); } else { // we are a child. The rotation values will be set to the one of root modified by rot, as in SL. Don't ask. - SceneObjectPart rootPart = part.ParentGroup.RootPart; - SetRot(part, rootPart.RotationOffset * (Quaternion)q); + // sounds like sl bug that we need to replicate + SetRot(part, rootPart.RotationOffset * Rot2Quaternion(q)); } break; @@ -8062,7 +8300,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Vector color=rules.GetVector3Item(idx++); double alpha=(double)rules.GetLSLFloatItem(idx++); - part.SetFaceColorAlpha(face, color, alpha); + part.SetFaceColor(new Vector3((float)color.x, (float)color.y, (float)color.z), face); + SetAlpha(part, alpha, face); break; @@ -8210,7 +8449,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api string primText = rules.GetLSLStringItem(idx++); LSL_Vector primTextColor = rules.GetVector3Item(idx++); LSL_Float primTextAlpha = rules.GetLSLFloatItem(idx++); - Vector3 av3 = Util.Clip(primTextColor, 0.0f, 1.0f); + Vector3 av3 = new Vector3(Util.Clip((float)primTextColor.x, 0.0f, 1.0f), + Util.Clip((float)primTextColor.y, 0.0f, 1.0f), + Util.Clip((float)primTextColor.z, 0.0f, 1.0f)); part.SetText(primText, av3, Util.Clip((float)primTextAlpha, 0.0f, 1.0f)); break; @@ -8229,7 +8470,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_ROT_LOCAL: if (remain < 1) return null; - SetRot(part, rules.GetQuaternionItem(idx++)); + LSL_Rotation lr = rules.GetQuaternionItem(idx++); + SetRot(part, Rot2Quaternion(lr)); break; case (int)ScriptBaseClass.PRIM_OMEGA: if (remain < 3) @@ -8239,12 +8481,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api LSL_Float gain = rules.GetLSLFloatItem(idx++); TargetOmega(part, axis, (double)spinrate, (double)gain); break; - case (int)ScriptBaseClass.PRIM_SLICE: - if (remain < 1) - return null; - LSL_Vector slice = rules.GetVector3Item(idx++); - part.UpdateSlice((float)slice.x, (float)slice.y); - break; + case (int)ScriptBaseClass.PRIM_LINK_TARGET: if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. return null; @@ -8253,12 +8490,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - catch (InvalidCastException e) - { - ShoutError(string.Format( - "{0} error running rule #{1}: arg #{2} ", - originFunc, rulesParsed, idx - idxStart) + e.Message); - } finally { if (positionChanged) @@ -8267,12 +8498,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { SceneObjectGroup parent = part.ParentGroup; Util.FireAndForget(delegate(object x) { - parent.UpdateGroupPosition(currentPosition); + parent.UpdateGroupPosition(new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z)); }); } else { - part.OffsetPosition = currentPosition; + part.OffsetPosition = new Vector3((float)currentPosition.x, (float)currentPosition.y, (float)currentPosition.z); SceneObjectGroup parent = part.ParentGroup; parent.HasGroupChanged = true; parent.ScheduleGroupForTerseUpdate(); @@ -8561,7 +8792,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // and standing avatar since server 1.36 LSL_Vector lower; LSL_Vector upper; - if (presence.Animator.Animations.ImplicitDefaultAnimation.AnimID + if (presence.Animator.Animations.DefaultAnimation.AnimID == DefaultAvatarAnimations.AnimsUUID["SIT_GROUND_CONSTRAINED"]) { // This is for ground sitting avatars @@ -8650,22 +8881,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetPrimitiveParams(LSL_List rules) { m_host.AddScriptLPS(1); - - LSL_List result = new LSL_List(); - - LSL_List remaining = GetPrimParams(m_host, rules, ref result); - - while (remaining != null && remaining.Length > 2) - { - int linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); - List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - remaining = GetPrimParams(part, rules, ref result); - } - - return result; + return GetLinkPrimitiveParams(m_host, rules); } public LSL_List llGetLinkPrimitiveParams(int linknumber, LSL_List rules) @@ -8675,39 +8891,294 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // acording to SL wiki this must indicate a single link number or link_root or link_this. // keep other options as before - List parts; - List avatars; - + List parts = GetLinkParts(linknumber); + List avatars = GetLinkAvatars(linknumber); + LSL_List res = new LSL_List(); - LSL_List remaining = null; - while (rules.Length > 0) + if (parts.Count > 0) { - parts = GetLinkParts(linknumber); - avatars = GetLinkAvatars(linknumber); - - remaining = null; - foreach (SceneObjectPart part in parts) + foreach (var part in parts) { - remaining = GetPrimParams(part, rules, ref res); - } - foreach (ScenePresence avatar in avatars) - { - remaining = GetPrimParams(avatar, rules, ref res); - } - - if (remaining != null && remaining.Length > 0) - { - linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); + LSL_List partRes = GetLinkPrimitiveParams(part, rules); + res += partRes; + } + } + if (avatars.Count > 0) + { + foreach (ScenePresence avatar in avatars) + { + LSL_List avaRes = GetLinkPrimitiveParams(avatar, rules); + res += avaRes; } } - return res; } - public LSL_List GetPrimParams(SceneObjectPart part, LSL_List rules, ref LSL_List res) + public LSL_List GetLinkPrimitiveParams(ScenePresence avatar, LSL_List rules) { + // avatars case + // replies as SL wiki + + LSL_List res = new LSL_List(); +// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed + SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? + + int idx = 0; + while (idx < rules.Length) + { + int code = (int)rules.GetLSLIntegerItem(idx++); + int remain = rules.Length - idx; + + switch (code) + { + case (int)ScriptBaseClass.PRIM_MATERIAL: + res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); + break; + + case (int)ScriptBaseClass.PRIM_PHYSICS: + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_PHANTOM: + res.Add(new LSL_Integer(0)); + break; + + case (int)ScriptBaseClass.PRIM_POSITION: + + Vector3 pos = avatar.OffsetPosition; + + Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); + pos -= sitOffset; + + if( sitPart != null) + pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); + + res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); + break; + + case (int)ScriptBaseClass.PRIM_SIZE: + // as in llGetAgentSize above + res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); + break; + + case (int)ScriptBaseClass.PRIM_ROTATION: + Quaternion rot = avatar.Rotation; + if (sitPart != null) + { + rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation + } + + res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); + break; + + case (int)ScriptBaseClass.PRIM_TYPE: + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); + res.Add(new LSL_Vector(0f,1.0f,0f)); + res.Add(new LSL_Float(0.0f)); + res.Add(new LSL_Vector(0, 0, 0)); + res.Add(new LSL_Vector(1.0f,1.0f,0f)); + res.Add(new LSL_Vector(0, 0, 0)); + break; + + case (int)ScriptBaseClass.PRIM_TEXTURE: + if (remain < 1) + return res; + + int face = (int)rules.GetLSLIntegerItem(idx++); + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0.0)); + } + } + else + { + if (face >= 0 && face < 21) + { + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0.0)); + } + } + break; + + case (int)ScriptBaseClass.PRIM_COLOR: + if (remain < 1) + return res; + + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0)); + } + } + else + { + res.Add(new LSL_Vector(0,0,0)); + res.Add(new LSL_Float(0)); + } + break; + + case (int)ScriptBaseClass.PRIM_BUMP_SHINY: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); + } + break; + + case (int)ScriptBaseClass.PRIM_FULLBRIGHT: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); + } + break; + + case (int)ScriptBaseClass.PRIM_FLEXIBLE: + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Integer(0));// softness + res.Add(new LSL_Float(0.0f)); // gravity + res.Add(new LSL_Float(0.0f)); // friction + res.Add(new LSL_Float(0.0f)); // wind + res.Add(new LSL_Float(0.0f)); // tension + res.Add(new LSL_Vector(0f,0f,0f)); + break; + + case (int)ScriptBaseClass.PRIM_TEXGEN: + // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + } + else + { + res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); + } + break; + + case (int)ScriptBaseClass.PRIM_POINT_LIGHT: + res.Add(new LSL_Integer(0)); + res.Add(new LSL_Vector(0f,0f,0f)); + res.Add(new LSL_Float(0f)); // intensity + res.Add(new LSL_Float(0f)); // radius + res.Add(new LSL_Float(0f)); // falloff + break; + + case (int)ScriptBaseClass.PRIM_GLOW: + if (remain < 1) + return res; + face = (int)rules.GetLSLIntegerItem(idx++); + + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < 21; face++) + { + res.Add(new LSL_Float(0f)); + } + } + else + { + res.Add(new LSL_Float(0f)); + } + break; + + case (int)ScriptBaseClass.PRIM_TEXT: + res.Add(new LSL_String("")); + res.Add(new LSL_Vector(0f,0f,0f)); + res.Add(new LSL_Float(1.0f)); + break; + + case (int)ScriptBaseClass.PRIM_NAME: + res.Add(new LSL_String(avatar.Name)); + break; + + case (int)ScriptBaseClass.PRIM_DESC: + res.Add(new LSL_String("")); + break; + + case (int)ScriptBaseClass.PRIM_ROT_LOCAL: + Quaternion lrot = avatar.Rotation; + + if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) + { + lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset + } + res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); + break; + + case (int)ScriptBaseClass.PRIM_POS_LOCAL: + Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part + Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); + lpos -= lsitOffset; + + if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) + { + lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim + } + res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); + break; + + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return res; + LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); + LSL_List new_rules = rules.GetSublist(idx, -1); + + res += llGetLinkPrimitiveParams((int)new_linknumber, new_rules); + return res; + } + } + return res; + } + + public LSL_List GetLinkPrimitiveParams(SceneObjectPart part, LSL_List rules) + { + LSL_List res = new LSL_List(); int idx=0; while (idx < rules.Length) { @@ -8845,7 +9316,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXTURE: if (remain < 1) - return null; + return res; int face = (int)rules.GetLSLIntegerItem(idx++); Primitive.TextureEntry tex = part.Shape.Textures; @@ -8885,7 +9356,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_COLOR: if (remain < 1) - return null; + return res; face=(int)rules.GetLSLIntegerItem(idx++); @@ -8914,8 +9385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_BUMP_SHINY: if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -8971,8 +9441,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_FULLBRIGHT: if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9026,8 +9495,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_TEXGEN: // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9075,8 +9543,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_GLOW: if (remain < 1) - return null; - + return res; face = (int)rules.GetLSLIntegerItem(idx++); tex = part.Shape.Textures; @@ -9120,24 +9587,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PRIM_POS_LOCAL: res.Add(new LSL_Vector(GetPartLocalPos(part))); break; - case (int)ScriptBaseClass.PRIM_SLICE: - PrimType prim_type = part.GetPrimType(); - bool useProfileBeginEnd = (prim_type == PrimType.SPHERE || prim_type == PrimType.TORUS || prim_type == PrimType.TUBE || prim_type == PrimType.RING); - res.Add(new LSL_Vector( - (useProfileBeginEnd ? part.Shape.ProfileBegin : part.Shape.PathBegin) / 50000.0, - 1 - (useProfileBeginEnd ? part.Shape.ProfileEnd : part.Shape.PathEnd) / 50000.0, - 0 - )); - break; - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if(remain < 3) - return null; - return rules.GetSublist(idx, -1); + case (int)ScriptBaseClass.PRIM_LINK_TARGET: + if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. + return res; + LSL_Integer new_linknumber = rules.GetLSLIntegerItem(idx++); + LSL_List new_rules = rules.GetSublist(idx, -1); + LSL_List tres = llGetLinkPrimitiveParams((int)new_linknumber, new_rules); + res += tres; + return res; } } - - return null; + return res; } public LSL_List llGetPrimMediaParams(int face, LSL_List rules) @@ -10050,10 +10511,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api GridRegion info; - if (World.RegionInfo.RegionName == simulator) - info = new GridRegion(World.RegionInfo); + if (m_ScriptEngine.World.RegionInfo.RegionName == simulator) //Det data for this simulator? + + info = new GridRegion(m_ScriptEngine.World.RegionInfo); else - info = World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); + info = m_ScriptEngine.World.GridService.GetRegionByName(m_ScriptEngine.World.RegionInfo.ScopeID, simulator); switch (data) { @@ -10063,24 +10525,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(1000); return UUID.Zero.ToString(); } - - bool isHypergridRegion = false; - - if (World.RegionInfo.RegionName != simulator && info.RegionSecret != "") - { - // Hypergrid is currently placing real destination region co-ords into RegionSecret. - // But other code can also use this field for a genuine RegionSecret! Therefore, if - // anything is present we need to disambiguate. - // - // FIXME: Hypergrid should be storing this data in a different field. - RegionFlags regionFlags - = (RegionFlags)m_ScriptEngine.World.GridService.GetRegionFlags( - info.ScopeID, info.RegionID); - isHypergridRegion = (regionFlags & RegionFlags.Hyperlink) != 0; - } - - if (isHypergridRegion) + if (m_ScriptEngine.World.RegionInfo.RegionName != simulator) { + //Hypergrid Region co-ordinates uint rx = 0, ry = 0; Utils.LongToUInts(Convert.ToUInt64(info.RegionSecret), out rx, out ry); @@ -10091,7 +10538,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - // Local grid co-oridnates + //Local-cooridnates reply = new LSL_Vector( info.RegionLocX, info.RegionLocY, @@ -10545,20 +10992,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch ((ParcelMediaCommandEnum) Convert.ToInt32(aList.Data[i].ToString())) { case ParcelMediaCommandEnum.Url: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaURL)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaURL)); break; case ParcelMediaCommandEnum.Desc: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).Description)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).Description)); break; case ParcelMediaCommandEnum.Texture: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaID.ToString())); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaID.ToString())); break; case ParcelMediaCommandEnum.Type: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaType)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaType)); break; case ParcelMediaCommandEnum.Size: - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaWidth)); - list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition).MediaHeight)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaWidth)); + list.Add(new LSL_String(World.GetLandData(m_host.AbsolutePosition.X, m_host.AbsolutePosition.Y).MediaHeight)); break; default: ParcelMediaCommandEnum mediaCommandEnum = ParcelMediaCommandEnum.Url; @@ -10728,8 +11175,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence avatar = World.GetScenePresence(detectedParams.Key); if (avatar != null) { - avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, - simname, pos, lookAt); + avatar.ControllingClient.SendScriptTeleportRequest(m_host.Name, simname, + new Vector3((float)pos.x, (float)pos.y, (float)pos.z), + new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z)); } ScriptSleep(1000); @@ -10914,30 +11362,31 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float llListStatistics(int operation, LSL_List src) { m_host.AddScriptLPS(1); + LSL_List nums = LSL_List.ToDoubleList(src); switch (operation) { case ScriptBaseClass.LIST_STAT_RANGE: - return src.Range(); + return nums.Range(); case ScriptBaseClass.LIST_STAT_MIN: - return src.Min(); + return nums.Min(); case ScriptBaseClass.LIST_STAT_MAX: - return src.Max(); + return nums.Max(); case ScriptBaseClass.LIST_STAT_MEAN: - return src.Mean(); + return nums.Mean(); case ScriptBaseClass.LIST_STAT_MEDIAN: - return LSL_List.ToDoubleList(src).Median(); + return nums.Median(); case ScriptBaseClass.LIST_STAT_NUM_COUNT: - return src.NumericLength(); + return nums.NumericLength(); case ScriptBaseClass.LIST_STAT_STD_DEV: - return src.StdDev(); + return nums.StdDev(); case ScriptBaseClass.LIST_STAT_SUM: - return src.Sum(); + return nums.Sum(); case ScriptBaseClass.LIST_STAT_SUM_SQUARES: - return src.SumSqrs(); + return nums.SumSqrs(); case ScriptBaseClass.LIST_STAT_GEOMETRIC_MEAN: - return src.GeometricMean(); + return nums.GeometricMean(); case ScriptBaseClass.LIST_STAT_HARMONIC_MEAN: - return src.HarmonicMean(); + return nums.HarmonicMean(); default: return 0.0; } @@ -11295,7 +11744,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List llGetParcelDetails(LSL_Vector pos, LSL_List param) { m_host.AddScriptLPS(1); - LandData land = World.GetLandData(pos); + LandData land = World.GetLandData((float)pos.x, (float)pos.y); if (land == null) { return new LSL_List(0); @@ -11463,12 +11912,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else rot = obj.GetWorldRotation(); - LSL_Rotation objrot = new LSL_Rotation(rot); + LSL_Rotation objrot = new LSL_Rotation(rot.X, rot.Y, rot.Z, rot.W); ret.Add(objrot); } break; case ScriptBaseClass.OBJECT_VELOCITY: - ret.Add(new LSL_Vector(obj.Velocity)); + Vector3 ovel = obj.Velocity; + ret.Add(new LSL_Vector(ovel.X, ovel.Y, ovel.Z)); break; case ScriptBaseClass.OBJECT_OWNER: ret.Add(new LSL_String(obj.OwnerID.ToString())); @@ -11555,12 +12005,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void Deprecated(string command) { - throw new ScriptException("Command deprecated: " + command); + throw new Exception("Command deprecated: " + command); } internal void LSLError(string msg) { - throw new ScriptException("LSL Runtime Error: " + msg); + throw new Exception("LSL Runtime Error: " + msg); } public delegate void AssetRequestCallback(UUID assetID, AssetBase asset); @@ -11681,7 +12131,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return tid.ToString(); } - public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc) + public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); if (obj == null) @@ -11690,41 +12140,28 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (obj.OwnerID != m_host.OwnerID) return; - uint rulesParsed = 0; - LSL_List remaining = SetPrimParams(obj, rules, originFunc, ref rulesParsed); + LSL_List remaining = SetPrimParams(obj, rules); while ((object)remaining != null && remaining.Length > 2) { LSL_Integer newLink = remaining.GetLSLIntegerItem(0); LSL_List newrules = remaining.GetSublist(1, -1); foreach(SceneObjectPart part in GetLinkParts(obj, newLink)){ - remaining = SetPrimParams(part, newrules, originFunc, ref rulesParsed); + remaining = SetPrimParams(part, newrules); } } } - public LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) { SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); + if (obj == null) + return new LSL_List(); - LSL_List result = new LSL_List(); + if (obj.OwnerID != m_host.OwnerID) + return new LSL_List(); - if (obj != null && obj.OwnerID != m_host.OwnerID) - { - LSL_List remaining = GetPrimParams(obj, rules, ref result); - - while (remaining != null && remaining.Length > 2) - { - int linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); - List parts = GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - remaining = GetPrimParams(part, rules, ref result); - } - } - - return result; + return GetLinkPrimitiveParams(obj, rules); } public LSL_Integer llGetLinkNumberOfSides(LSL_Integer link) @@ -12087,8 +12524,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); - Vector3 rayStart = start; - Vector3 rayEnd = end; + Vector3 rayStart = new Vector3((float)start.x, (float)start.y, (float)start.z); + Vector3 rayEnd = new Vector3((float)end.x, (float)end.y, (float)end.z); Vector3 dir = rayEnd - rayStart; float dist = Vector3.Mag(dir); @@ -12662,455 +13099,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - - protected LSL_List SetPrimParams(ScenePresence av, LSL_List rules, string originFunc, ref uint rulesParsed) - { - //This is a special version of SetPrimParams to deal with avatars which are sat on the linkset. - - int idx = 0; - int idxStart = 0; - - bool positionChanged = false; - Vector3 finalPos = Vector3.Zero; - - try - { - while (idx < rules.Length) - { - ++rulesParsed; - int code = rules.GetLSLIntegerItem(idx++); - - int remain = rules.Length - idx; - idxStart = idx; - - switch (code) - { - case (int)ScriptBaseClass.PRIM_POSITION: - case (int)ScriptBaseClass.PRIM_POS_LOCAL: - { - if (remain < 1) - return null; - - LSL_Vector v; - v = rules.GetVector3Item(idx++); - - SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); - if (part == null) - break; - - LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; - LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; - if (part.LinkNum > 1) - { - localRot = GetPartLocalRot(part); - localPos = GetPartLocalPos(part); - } - - v -= localPos; - v /= localRot; - - LSL_Vector sitOffset = (llRot2Up(new LSL_Rotation(av.Rotation.X, av.Rotation.Y, av.Rotation.Z, av.Rotation.W)) * av.Appearance.AvatarHeight * 0.02638f); - - v = v + 2 * sitOffset; - - av.OffsetPosition = new Vector3((float)v.x, (float)v.y, (float)v.z); - av.SendAvatarDataToAllAgents(); - - } - break; - - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - case (int)ScriptBaseClass.PRIM_ROTATION: - { - if (remain < 1) - return null; - - LSL_Rotation r; - r = rules.GetQuaternionItem(idx++); - - SceneObjectPart part = World.GetSceneObjectPart(av.ParentID); - if (part == null) - break; - - LSL_Rotation localRot = ScriptBaseClass.ZERO_ROTATION; - LSL_Vector localPos = ScriptBaseClass.ZERO_VECTOR; - - if (part.LinkNum > 1) - localRot = GetPartLocalRot(part); - - r = r * llGetRootRotation() / localRot; - av.Rotation = new Quaternion((float)r.x, (float)r.y, (float)r.z, (float)r.s); - av.SendAvatarDataToAllAgents(); - } - break; - - // parse rest doing nothing but number of parameters error check - case (int)ScriptBaseClass.PRIM_SIZE: - case (int)ScriptBaseClass.PRIM_MATERIAL: - case (int)ScriptBaseClass.PRIM_PHANTOM: - case (int)ScriptBaseClass.PRIM_PHYSICS: - case (int)ScriptBaseClass.PRIM_PHYSICS_SHAPE_TYPE: - case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - case (int)ScriptBaseClass.PRIM_NAME: - case (int)ScriptBaseClass.PRIM_DESC: - if (remain < 1) - return null; - idx++; - break; - - case (int)ScriptBaseClass.PRIM_GLOW: - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - case (int)ScriptBaseClass.PRIM_TEXGEN: - if (remain < 2) - return null; - idx += 2; - break; - - case (int)ScriptBaseClass.PRIM_TYPE: - if (remain < 3) - return null; - code = (int)rules.GetLSLIntegerItem(idx++); - remain = rules.Length - idx; - switch (code) - { - case (int)ScriptBaseClass.PRIM_TYPE_BOX: - case (int)ScriptBaseClass.PRIM_TYPE_CYLINDER: - case (int)ScriptBaseClass.PRIM_TYPE_PRISM: - if (remain < 6) - return null; - idx += 6; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_SPHERE: - if (remain < 5) - return null; - idx += 5; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_TORUS: - case (int)ScriptBaseClass.PRIM_TYPE_TUBE: - case (int)ScriptBaseClass.PRIM_TYPE_RING: - if (remain < 11) - return null; - idx += 11; - break; - - case (int)ScriptBaseClass.PRIM_TYPE_SCULPT: - if (remain < 2) - return null; - idx += 2; - break; - } - break; - - case (int)ScriptBaseClass.PRIM_COLOR: - case (int)ScriptBaseClass.PRIM_TEXT: - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - case (int)ScriptBaseClass.PRIM_OMEGA: - if (remain < 3) - return null; - idx += 3; - break; - - case (int)ScriptBaseClass.PRIM_TEXTURE: - case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - case (int)ScriptBaseClass.PRIM_PHYSICS_MATERIAL: - if (remain < 5) - return null; - idx += 5; - break; - - case (int)ScriptBaseClass.PRIM_FLEXIBLE: - if (remain < 7) - return null; - - idx += 7; - break; - - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return null; - - return rules.GetSublist(idx, -1); - } - } - } - catch (InvalidCastException e) - { - ShoutError(string.Format( - "{0} error running rule #{1}: arg #{2} ", - originFunc, rulesParsed, idx - idxStart) + e.Message); - } - finally - { - if (positionChanged) - { - av.OffsetPosition = finalPos; -// av.SendAvatarDataToAllAgents(); - av.SendTerseUpdateToAllClients(); - positionChanged = false; - } - } - return null; - } - - public LSL_List GetPrimParams(ScenePresence avatar, LSL_List rules, ref LSL_List res) - { - // avatars case - // replies as SL wiki - -// SceneObjectPart sitPart = avatar.ParentPart; // most likelly it will be needed - SceneObjectPart sitPart = World.GetSceneObjectPart(avatar.ParentID); // maybe better do this expensive search for it in case it's gone?? - - int idx = 0; - while (idx < rules.Length) - { - int code = (int)rules.GetLSLIntegerItem(idx++); - int remain = rules.Length - idx; - - switch (code) - { - case (int)ScriptBaseClass.PRIM_MATERIAL: - res.Add(new LSL_Integer((int)SOPMaterialData.SopMaterial.Flesh)); - break; - - case (int)ScriptBaseClass.PRIM_PHYSICS: - res.Add(new LSL_Integer(0)); - break; - - case (int)ScriptBaseClass.PRIM_TEMP_ON_REZ: - res.Add(new LSL_Integer(0)); - break; - - case (int)ScriptBaseClass.PRIM_PHANTOM: - res.Add(new LSL_Integer(0)); - break; - - case (int)ScriptBaseClass.PRIM_POSITION: - - Vector3 pos = avatar.OffsetPosition; - - Vector3 sitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f *2.0f); - pos -= sitOffset; - - if( sitPart != null) - pos = sitPart.GetWorldPosition() + pos * sitPart.GetWorldRotation(); - - res.Add(new LSL_Vector(pos.X,pos.Y,pos.Z)); - break; - - case (int)ScriptBaseClass.PRIM_SIZE: - // as in llGetAgentSize above - res.Add(new LSL_Vector(0.45f, 0.6f, avatar.Appearance.AvatarHeight)); - break; - - case (int)ScriptBaseClass.PRIM_ROTATION: - Quaternion rot = avatar.Rotation; - if (sitPart != null) - { - rot = sitPart.GetWorldRotation() * rot; // apply sit part world rotation - } - - res.Add(new LSL_Rotation (rot.X, rot.Y, rot.Z, rot.W)); - break; - - case (int)ScriptBaseClass.PRIM_TYPE: - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TYPE_BOX)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_HOLE_DEFAULT)); - res.Add(new LSL_Vector(0f,1.0f,0f)); - res.Add(new LSL_Float(0.0f)); - res.Add(new LSL_Vector(0, 0, 0)); - res.Add(new LSL_Vector(1.0f,1.0f,0f)); - res.Add(new LSL_Vector(0, 0, 0)); - break; - - case (int)ScriptBaseClass.PRIM_TEXTURE: - if (remain < 1) - return null; - - int face = (int)rules.GetLSLIntegerItem(idx++); - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0.0)); - } - } - else - { - if (face >= 0 && face < 21) - { - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0.0)); - } - } - break; - - case (int)ScriptBaseClass.PRIM_COLOR: - if (remain < 1) - return null; - - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0)); - } - } - else - { - res.Add(new LSL_Vector(0,0,0)); - res.Add(new LSL_Float(0)); - } - break; - - case (int)ScriptBaseClass.PRIM_BUMP_SHINY: - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); - } - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_SHINY_NONE)); - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_BUMP_NONE)); - } - break; - - case (int)ScriptBaseClass.PRIM_FULLBRIGHT: - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); - } - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.FALSE)); - } - break; - - case (int)ScriptBaseClass.PRIM_FLEXIBLE: - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Integer(0));// softness - res.Add(new LSL_Float(0.0f)); // gravity - res.Add(new LSL_Float(0.0f)); // friction - res.Add(new LSL_Float(0.0f)); // wind - res.Add(new LSL_Float(0.0f)); // tension - res.Add(new LSL_Vector(0f,0f,0f)); - break; - - case (int)ScriptBaseClass.PRIM_TEXGEN: - // (PRIM_TEXGEN_DEFAULT, PRIM_TEXGEN_PLANAR) - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - } - else - { - res.Add(new LSL_Integer(ScriptBaseClass.PRIM_TEXGEN_DEFAULT)); - } - break; - - case (int)ScriptBaseClass.PRIM_POINT_LIGHT: - res.Add(new LSL_Integer(0)); - res.Add(new LSL_Vector(0f,0f,0f)); - res.Add(new LSL_Float(0f)); // intensity - res.Add(new LSL_Float(0f)); // radius - res.Add(new LSL_Float(0f)); // falloff - break; - - case (int)ScriptBaseClass.PRIM_GLOW: - if (remain < 1) - return null; - face = (int)rules.GetLSLIntegerItem(idx++); - - if (face == ScriptBaseClass.ALL_SIDES) - { - for (face = 0; face < 21; face++) - { - res.Add(new LSL_Float(0f)); - } - } - else - { - res.Add(new LSL_Float(0f)); - } - break; - - case (int)ScriptBaseClass.PRIM_TEXT: - res.Add(new LSL_String("")); - res.Add(new LSL_Vector(0f,0f,0f)); - res.Add(new LSL_Float(1.0f)); - break; - - case (int)ScriptBaseClass.PRIM_NAME: - res.Add(new LSL_String(avatar.Name)); - break; - - case (int)ScriptBaseClass.PRIM_DESC: - res.Add(new LSL_String("")); - break; - - case (int)ScriptBaseClass.PRIM_ROT_LOCAL: - Quaternion lrot = avatar.Rotation; - - if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) - { - lrot = sitPart.RotationOffset * lrot; // apply sit part rotation offset - } - res.Add(new LSL_Rotation(lrot.X, lrot.Y, lrot.Z, lrot.W)); - break; - - case (int)ScriptBaseClass.PRIM_POS_LOCAL: - Vector3 lpos = avatar.OffsetPosition; // pos relative to sit part - Vector3 lsitOffset = (Zrot(avatar.Rotation)) * (avatar.Appearance.AvatarHeight * 0.02638f * 2.0f); - lpos -= lsitOffset; - - if (sitPart != null && sitPart != sitPart.ParentGroup.RootPart) - { - lpos = sitPart.OffsetPosition + (lpos * sitPart.RotationOffset); // make it relative to root prim - } - res.Add(new LSL_Vector(lpos.X,lpos.Y,lpos.Z)); - break; - - case (int)ScriptBaseClass.PRIM_LINK_TARGET: - if (remain < 3) // setting to 3 on the basis that parsing any usage of PRIM_LINK_TARGET that has nothing following it is pointless. - return null; - - return rules.GetSublist(idx, -1); - } - } - - return null; - } } public class NotecardCache diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index ceb4660f96..795de802bb 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -304,7 +304,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_DETAIL_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudDetailXYDensity = iV; + wl.cloudDetailXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_CLOUD_SCALE: idx++; @@ -329,7 +329,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_CLOUD_XY_DENSITY: idx++; iV = rules.GetVector3Item(idx); - wl.cloudXYDensity = iV; + wl.cloudXYDensity = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_DENSITY_MULTIPLIER: idx++; @@ -384,7 +384,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_REFLECTION_WAVELET_SCALE: idx++; iV = rules.GetVector3Item(idx); - wl.reflectionWaveletScale = iV; + wl.reflectionWaveletScale = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_REFRACT_SCALE_ABOVE: idx++; @@ -422,7 +422,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.WL_WATER_COLOR: idx++; iV = rules.GetVector3Item(idx); - wl.waterColor = iV; + wl.waterColor = new Vector3((float)iV.x, (float)iV.y, (float)iV.z); break; case (int)ScriptBaseClass.WL_WATER_FOG_DENSITY_EXPONENT: idx++; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs index 8f348332b6..7844c75155 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/MOD_Api.cs @@ -95,13 +95,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal void MODError(string msg) { - throw new ScriptException("MOD Runtime Error: " + msg); + throw new Exception("MOD Runtime Error: " + msg); } - /// - /// Dumps an error message on the debug console. - /// - /// + // + //Dumps an error message on the debug console. + // + internal void MODShoutError(string message) { if (message.Length > 1023) @@ -254,7 +254,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api object[] convertedParms = new object[parms.Length]; for (int i = 0; i < parms.Length; i++) - convertedParms[i] = ConvertFromLSL(parms[i],signature[i], fname); + convertedParms[i] = ConvertFromLSL(parms[i],signature[i]); // now call the function, the contract with the function is that it will always return // non-null but don't trust it completely @@ -294,7 +294,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// - protected object ConvertFromLSL(object lslparm, Type type, string fname) + protected object ConvertFromLSL(object lslparm, Type type) { // ---------- String ---------- if (lslparm is LSL_String) @@ -310,7 +310,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // ---------- Integer ---------- else if (lslparm is LSL_Integer) { - if (type == typeof(int) || type == typeof(float)) + if (type == typeof(int)) return (int)(LSL_Integer)lslparm; } @@ -333,7 +333,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Quaternion)) { - return (OpenMetaverse.Quaternion)((LSL_Rotation)lslparm); + LSL_Rotation rot = (LSL_Rotation)lslparm; + return new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); } } @@ -342,7 +343,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { if (type == typeof(OpenMetaverse.Vector3)) { - return (OpenMetaverse.Vector3)((LSL_Vector)lslparm); + LSL_Vector vect = (LSL_Vector)lslparm; + return new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); } } @@ -359,27 +361,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api result[i] = (string)(LSL_String)plist[i]; else if (plist[i] is LSL_Integer) result[i] = (int)(LSL_Integer)plist[i]; - // The int check exists because of the many plain old int script constants in ScriptBase which - // are not LSL_Integers. - else if (plist[i] is int) - result[i] = plist[i]; else if (plist[i] is LSL_Float) result[i] = (float)(LSL_Float)plist[i]; else if (plist[i] is LSL_Key) result[i] = new UUID((LSL_Key)plist[i]); else if (plist[i] is LSL_Rotation) - result[i] = (Quaternion)((LSL_Rotation)plist[i]); + { + LSL_Rotation rot = (LSL_Rotation)plist[i]; + result[i] = new OpenMetaverse.Quaternion((float)rot.x,(float)rot.y,(float)rot.z,(float)rot.s); + } else if (plist[i] is LSL_Vector) - result[i] = (Vector3)((LSL_Vector)plist[i]); + { + LSL_Vector vect = (LSL_Vector)plist[i]; + result[i] = new OpenMetaverse.Vector3((float)vect.x,(float)vect.y,(float)vect.z); + } else - MODError(String.Format("{0}: unknown LSL list element type", fname)); + MODError("unknown LSL list element type"); } return result; } } - MODError(String.Format("{1}: parameter type mismatch; expecting {0}",type.Name, fname)); + MODError(String.Format("parameter type mismatch; expecting {0}",type.Name)); return null; } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 51c8c7ed89..80111f980c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -141,8 +141,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api internal bool m_debuggerSafe = false; internal Dictionary m_FunctionPerms = new Dictionary(); - protected IUrlModule m_UrlModule = null; - public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, TaskInventoryItem item) { m_ScriptEngine = ScriptEngine; @@ -150,8 +148,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_item = item; m_debuggerSafe = m_ScriptEngine.Config.GetBoolean("DebuggerSafe", false); - m_UrlModule = m_ScriptEngine.World.RequestModuleInterface(); - if (m_ScriptEngine.Config.GetBoolean("AllowOSFunctions", false)) m_OSFunctionsEnabled = true; @@ -218,7 +214,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - throw new ScriptException("OSSL Runtime Error: " + msg); + throw new Exception("OSSL Runtime Error: " + msg); } } @@ -786,9 +782,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // 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(o => World.RequestTeleportLocation( - presence.ControllingClient, regionName, position, - lookat, (uint)TPFlags.ViaLocation)); + Util.FireAndForget( + o => World.RequestTeleportLocation(presence.ControllingClient, regionName, + new Vector3((float)position.x, (float)position.y, (float)position.z), + new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -831,9 +828,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // 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(o => World.RequestTeleportLocation( - presence.ControllingClient, regionHandle, - position, lookat, (uint)TPFlags.ViaLocation)); + Util.FireAndForget( + o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle, + new Vector3((float)position.x, (float)position.y, (float)position.z), + new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation)); ScriptSleep(5000); @@ -1682,11 +1680,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - MessageObject(objUUID, message); - } - - private void MessageObject(UUID objUUID, string message) - { object[] resobj = new object[] { new LSL_Types.LSLString(m_host.UUID.ToString()), new LSL_Types.LSLString(message) }; SceneObjectPart sceneOP = World.GetSceneObjectPart(objUUID); @@ -1789,24 +1782,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api protected string LoadNotecard(string notecardNameOrUuid) { UUID assetID = CacheNotecard(notecardNameOrUuid); + StringBuilder notecardData = new StringBuilder(); - if (assetID != UUID.Zero) + for (int count = 0; count < NotecardCache.GetLines(assetID); count++) { - StringBuilder notecardData = new StringBuilder(); - - for (int count = 0; count < NotecardCache.GetLines(assetID); count++) - { - string line = NotecardCache.GetLine(assetID, count) + "\n"; - - // m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); - - notecardData.Append(line); - } - - return notecardData.ToString(); + string line = NotecardCache.GetLine(assetID, count) + "\n"; + +// m_log.DebugFormat("[OSSL]: From notecard {0} loading line {1}", notecardNameOrUuid, line); + + notecardData.Append(line); } - return null; + return notecardData.ToString(); } /// @@ -2272,25 +2259,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.High, "osGetLinkPrimitiveParams"); m_host.AddScriptLPS(1); InitLSL(); - // One needs to cast m_LSL_Api because we're using functions not - // on the ILSL_Api interface. - LSL_Api LSL_Api = (LSL_Api)m_LSL_Api; LSL_List retVal = new LSL_List(); - LSL_List remaining = null; - List parts = LSL_Api.GetLinkParts(linknumber); + List parts = ((LSL_Api)m_LSL_Api).GetLinkParts(linknumber); foreach (SceneObjectPart part in parts) { - remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); - } - - while (remaining != null && remaining.Length > 2) - { - linknumber = remaining.GetLSLIntegerItem(0); - rules = remaining.GetSublist(1, -1); - parts = LSL_Api.GetLinkParts(linknumber); - - foreach (SceneObjectPart part in parts) - remaining = LSL_Api.GetPrimParams(part, rules, ref retVal); + retVal += ((LSL_Api)m_LSL_Api).GetLinkPrimitiveParams(part, rules); } return retVal; } @@ -2379,18 +2352,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return UUID.Zero.ToString(); } } - else - { - OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); - } } + 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, - position, + new Vector3((float) position.x, (float) position.y, (float) position.z), ownerID, senseAsAgent, World, @@ -2453,10 +2425,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; string appearanceSerialized = LoadNotecard(notecard); - - if (appearanceSerialized == null) - OSSLError(string.Format("osNpcCreate: Notecard reference '{0}' not found.", notecard)); - OSDMap appearanceOsd = (OSDMap)OSDParser.DeserializeLLSDXml(appearanceSerialized); // OSD a = OSDParser.DeserializeLLSDXml(appearanceSerialized); // Console.WriteLine("appearanceSerialized {0}", appearanceSerialized); @@ -2517,7 +2485,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Vector(0, 0, 0); } - public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) + public void osNpcMoveTo(LSL_Key npc, LSL_Vector position) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); m_host.AddScriptLPS(1); @@ -2532,6 +2500,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api 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, false); } } @@ -2551,10 +2520,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api 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), World, - target, + pos, (options & ScriptBaseClass.OS_NPC_NO_FLY) != 0, (options & ScriptBaseClass.OS_NPC_LAND_AT_TARGET) != 0, (options & ScriptBaseClass.OS_NPC_RUNNING) != 0); @@ -2606,7 +2576,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence sp = World.GetScenePresence(npcId); if (sp != null) - sp.Rotation = rotation; + sp.Rotation = LSL_Api.Rot2Quaternion(rotation); } } @@ -2966,7 +2936,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api avatar.SpeedModifier = (float)SpeedModifier; } - public void osKickAvatar(string FirstName, string SurName, string alert) + public void osKickAvatar(string FirstName,string SurName,string alert) { CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); m_host.AddScriptLPS(1); @@ -2980,21 +2950,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api sp.ControllingClient.Kick(alert); // ...and close on our side - sp.Scene.IncomingCloseAgent(sp.UUID, false); + sp.Scene.IncomingCloseAgent(sp.UUID); } }); } - - public LSL_Float osGetHealth(string avatar) - { - CheckThreatLevel(ThreatLevel.None, "osGetHealth"); - m_host.AddScriptLPS(1); - - LSL_Float health = new LSL_Float(-1); - ScenePresence presence = World.GetScenePresence(new UUID(avatar)); - if (presence != null) health = presence.Health; - return health; - } public void osCauseDamage(string avatar, double damage) { @@ -3007,7 +2966,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScenePresence presence = World.GetScenePresence(avatarId); if (presence != null) { - LandData land = World.GetLandData(pos); + LandData land = World.GetLandData((float)pos.X, (float)pos.Y); if ((land.Flags & (uint)ParcelFlags.AllowDamage) == (uint)ParcelFlags.AllowDamage) { float health = presence.Health; @@ -3054,7 +3013,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); + return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); } public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) @@ -3063,7 +3022,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); InitLSL(); - m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); + m_LSL_Api.SetPrimitiveParamsEx(prim, rules); } /// @@ -3295,8 +3254,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - #region Attachment commands - public void osForceAttachToAvatar(int attachmentPoint) { CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); @@ -3386,175 +3343,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ((LSL_Api)m_LSL_Api).DetachFromAvatar(); } - public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) - { - CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments"); - - m_host.AddScriptLPS(1); - - UUID targetUUID; - ScenePresence target; - LSL_List resp = new LSL_List(); - - if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) - { - foreach (object point in attachmentPoints.Data) - { - LSL_Integer ipoint = new LSL_Integer( - (point is LSL_Integer || point is int || point is uint) ? - (int)point : - 0 - ); - resp.Add(ipoint); - if (ipoint == 0) - { - // indicates zero attachments - resp.Add(new LSL_Integer(0)); - } - else - { - // gets the number of attachments on the attachment point - resp.Add(new LSL_Integer(target.GetAttachments((uint)ipoint).Count)); - } - } - } - - return resp; - } - - public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options) - { - CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments"); - m_host.AddScriptLPS(1); - - UUID targetUUID; - ScenePresence target; - - if (attachmentPoints.Length >= 1 && UUID.TryParse(avatar.ToString(), out targetUUID) && World.TryGetScenePresence(targetUUID, out target)) - { - List aps = new List(); - foreach (object point in attachmentPoints.Data) - { - int ipoint; - if (int.TryParse(point.ToString(), out ipoint)) - { - aps.Add(ipoint); - } - } - - List attachments = new List(); - - bool msgAll = aps.Contains(ScriptBaseClass.OS_ATTACH_MSG_ALL); - bool invertPoints = (options & ScriptBaseClass.OS_ATTACH_MSG_INVERT_POINTS) != 0; - - if (msgAll && invertPoints) - { - return; - } - else if (msgAll || invertPoints) - { - attachments = target.GetAttachments(); - } - else - { - foreach (int point in aps) - { - if (point > 0) - { - attachments.AddRange(target.GetAttachments((uint)point)); - } - } - } - - // if we have no attachments at this point, exit now - if (attachments.Count == 0) - { - return; - } - - List ignoreThese = new List(); - - if (invertPoints) - { - foreach (SceneObjectGroup attachment in attachments) - { - if (aps.Contains((int)attachment.AttachmentPoint)) - { - ignoreThese.Add(attachment); - } - } - } - - foreach (SceneObjectGroup attachment in ignoreThese) - { - attachments.Remove(attachment); - } - ignoreThese.Clear(); - - // if inverting removed all attachments to check, exit now - if (attachments.Count < 1) - { - return; - } - - if ((options & ScriptBaseClass.OS_ATTACH_MSG_OBJECT_CREATOR) != 0) - { - foreach (SceneObjectGroup attachment in attachments) - { - if (attachment.RootPart.CreatorID != m_host.CreatorID) - { - ignoreThese.Add(attachment); - } - } - - foreach (SceneObjectGroup attachment in ignoreThese) - { - attachments.Remove(attachment); - } - ignoreThese.Clear(); - - // if filtering by same object creator removed all - // attachments to check, exit now - if (attachments.Count == 0) - { - return; - } - } - - if ((options & ScriptBaseClass.OS_ATTACH_MSG_SCRIPT_CREATOR) != 0) - { - foreach (SceneObjectGroup attachment in attachments) - { - if (attachment.RootPart.CreatorID != m_item.CreatorID) - { - ignoreThese.Add(attachment); - } - } - - foreach (SceneObjectGroup attachment in ignoreThese) - { - attachments.Remove(attachment); - } - ignoreThese.Clear(); - - // if filtering by object creator must match originating - // script creator removed all attachments to check, - // exit now - if (attachments.Count == 0) - { - return; - } - } - - foreach (SceneObjectGroup attachment in attachments) - { - MessageObject(attachment.RootPart.UUID, message); - } - } - } - - #endregion - /// /// Checks if thing is a UUID. /// @@ -3604,166 +3392,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_Key(m_host.ParentGroup.FromPartID.ToString()); } - - /// - /// Sets the response type for an HTTP request/response - /// - /// - public void osSetContentType(LSL_Key id, string type) - { - CheckThreatLevel(ThreatLevel.High, "osSetContentType"); - - if (m_UrlModule != null) - m_UrlModule.HttpContentType(new UUID(id),type); - } - - /// Shout an error if the object owner did not grant the script the specified permissions. - /// - /// - /// boolean indicating whether an error was shouted. - protected bool ShoutErrorOnLackingOwnerPerms(int perms, string errorPrefix) - { - m_host.AddScriptLPS(1); - bool fail = false; - if (m_item.PermsGranter != m_host.OwnerID) - { - fail = true; - OSSLShoutError(string.Format("{0}. Permissions not granted to owner.", errorPrefix)); - } - else if ((m_item.PermsMask & perms) == 0) - { - fail = true; - OSSLShoutError(string.Format("{0}. Permissions not granted.", errorPrefix)); - } - - return fail; - } - - protected void DropAttachment(bool checkPerms) - { - if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) - { - return; - } - - IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; - ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); - - if (attachmentsModule != null && sp != null) - { - attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId); - } - } - - protected void DropAttachmentAt(bool checkPerms, LSL_Vector pos, LSL_Rotation rot) - { - if (checkPerms && ShoutErrorOnLackingOwnerPerms(ScriptBaseClass.PERMISSION_ATTACH, "Cannot drop attachment")) - { - return; - } - - IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; - ScenePresence sp = attachmentsModule == null ? null : m_host.ParentGroup.Scene.GetScenePresence(m_host.ParentGroup.OwnerID); - - if (attachmentsModule != null && sp != null) - { - attachmentsModule.DetachSingleAttachmentToGround(sp, m_host.ParentGroup.LocalId, pos, rot); - } - } - - public void osDropAttachment() - { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); - m_host.AddScriptLPS(1); - - DropAttachment(true); - } - - public void osForceDropAttachment() - { - CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment"); - m_host.AddScriptLPS(1); - - DropAttachment(false); - } - - public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) - { - CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); - m_host.AddScriptLPS(1); - - DropAttachmentAt(true, pos, rot); - } - - public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) - { - CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); - m_host.AddScriptLPS(1); - - DropAttachmentAt(false, pos, rot); - } - - public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) - { - CheckThreatLevel(ThreatLevel.Low, "osListenRegex"); - m_host.AddScriptLPS(1); - UUID keyID; - UUID.TryParse(ID, out keyID); - - // if we want the name to be used as a regular expression, ensure it is valid first. - if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_NAME) == ScriptBaseClass.OS_LISTEN_REGEX_NAME) - { - try - { - Regex.IsMatch("", name); - } - catch (Exception) - { - OSSLShoutError("Name regex is invalid."); - return -1; - } - } - - // if we want the msg to be used as a regular expression, ensure it is valid first. - if ((regexBitfield & ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) == ScriptBaseClass.OS_LISTEN_REGEX_MESSAGE) - { - try - { - Regex.IsMatch("", msg); - } - catch (Exception) - { - OSSLShoutError("Message regex is invalid."); - return -1; - } - } - - IWorldComm wComm = m_ScriptEngine.World.RequestModuleInterface(); - return (wComm == null) ? -1 : wComm.Listen( - m_host.LocalId, - m_item.ItemID, - m_host.UUID, - channelID, - name, - keyID, - msg, - regexBitfield - ); - } - - public LSL_Integer osRegexIsMatch(string input, string pattern) - { - CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch"); - m_host.AddScriptLPS(1); - try - { - return Regex.IsMatch(input, pattern) ? 1 : 0; - } - catch (Exception) - { - OSSLShoutError("Possible invalid regular expression detected."); - return 0; - } - } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 4dd795da10..678f9d54fe 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -352,7 +352,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); @@ -429,8 +429,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins try { Vector3 diff = toRegionPos - fromRegionPos; - double dot = LSL_Types.Vector3.Dot(forward_dir, diff); - double mag_obj = LSL_Types.Vector3.Mag(diff); + LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); + double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); + double mag_obj = LSL_Types.Vector3.Mag(obj_dir); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); } catch @@ -482,7 +483,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins q = avatar.Rotation; } - LSL_Types.Quaternion r = new LSL_Types.Quaternion(q); + LSL_Types.Quaternion r = new LSL_Types.Quaternion(q.X, q.Y, q.Z, q.W); LSL_Types.Vector3 forward_dir = (new LSL_Types.Vector3(1, 0, 0) * r); double mag_fwd = LSL_Types.Vector3.Mag(forward_dir); bool attached = (SensePoint.ParentGroup.AttachmentPoint != 0); @@ -563,8 +564,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins double ang_obj = 0; try { - LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3( - toRegionPos - fromRegionPos); + Vector3 diff = toRegionPos - fromRegionPos; + LSL_Types.Vector3 obj_dir = new LSL_Types.Vector3(diff.X, diff.Y, diff.Z); double dot = LSL_Types.Vector3.Dot(forward_dir, obj_dir); double mag_obj = LSL_Types.Vector3.Mag(obj_dir); ang_obj = Math.Acos(dot / (mag_fwd * mag_obj)); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 05c20f9978..af352589ff 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -429,8 +429,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Integer llGetLinkNumberOfSides(LSL_Integer link); void llSetPhysicsMaterial(int material_bits, float material_gravity_modifier, float material_restitution, float material_friction, float material_density); - void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules, string originFunc); + void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); void llSetKeyframedMotion(LSL_List frames, LSL_List options); - LSL_List GetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index c447d1f6e3..8c34ed3648 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -40,75 +40,16 @@ using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { - /// - /// To permit region owners to enable the extended scripting functionality - /// of OSSL, without allowing malicious scripts to access potentially - /// troublesome functions, each OSSL function is assigned a threat level, - /// and access to the functions is granted or denied based on a default - /// threshold set in OpenSim.ini (which can be overridden for individual - /// functions on a case-by-case basis) - /// public enum ThreatLevel { - // Not documented, presumably means permanently disabled ? NoAccess = -1, - - /// - /// Function is no threat at all. It doesn't constitute a threat to - /// either users or the system and has no known side effects. - /// None = 0, - - /// - /// Abuse of this command can cause a nuisance to the region operator, - /// such as log message spew. - /// Nuisance = 1, - - /// - /// Extreme levels of abuse of this function can cause impaired - /// functioning of the region, or very gullible users can be tricked - /// into experiencing harmless effects. - /// VeryLow = 2, - - /// - /// Intentional abuse can cause crashes or malfunction under certain - /// circumstances, which can be easily rectified; or certain users can - /// be tricked into certain situations in an avoidable manner. - /// Low = 3, - - /// - /// Intentional abuse can cause denial of service and crashes with - /// potential of data or state loss; or trusting users can be tricked - /// into embarrassing or uncomfortable situations. - /// Moderate = 4, - - /// - /// Casual abuse can cause impaired functionality or temporary denial - /// of service conditions. Intentional abuse can easily cause crashes - /// with potential data loss, or can be used to trick experienced and - /// cautious users into unwanted situations, or changes global data - /// permanently and without undo ability. - /// High = 5, - - /// - /// Even normal use may, depending on the number of instances, or - /// frequency of use, result in severe service impairment or crash - /// with loss of data, or can be used to cause unwanted or harmful - /// effects on users without giving the user a means to avoid it. - /// VeryHigh = 6, - - /// - /// Even casual use is a danger to region stability, or function allows - /// console or OS command execution, or function allows taking money - /// without consent, or allows deletion or modification of user data, - /// or allows the compromise of sensitive data by design. - /// Severe = 7 }; @@ -157,7 +98,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osAvatarPlayAnimation(string avatar, string animation); void osAvatarStopAnimation(string avatar, string animation); - #region Attachment commands + // Attachment commands /// /// Attach the object containing this script to the avatar that owns it without asking for PERMISSION_ATTACH @@ -192,29 +133,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// Nothing happens if the object is not attached. void osForceDetachFromAvatar(); - /// - /// Returns a strided list of the specified attachment points and the number of attachments on those points. - /// - /// avatar UUID - /// list of ATTACH_* constants - /// - LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints); - - /// - /// Sends a specified message to the specified avatar's attachments on - /// the specified attachment points. - /// - /// - /// Behaves as osMessageObject(), without the sending script needing to know the attachment keys in advance. - /// - /// avatar UUID - /// message string - /// list of ATTACH_* constants, or -1 for all attachments. If -1 is specified and OS_ATTACH_MSG_INVERT_POINTS is present in flags, no action is taken. - /// flags further constraining the attachments to deliver the message to. - void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags); - - #endregion - //texture draw functions string osMovePen(string drawList, int x, int y); string osDrawLine(string drawList, int startX, int startY, int endX, int endY); @@ -340,7 +258,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces int osGetSimulatorMemory(); void osKickAvatar(string FirstName,string SurName,string alert); void osSetSpeed(string UUID, LSL_Float SpeedModifier); - LSL_Float osGetHealth(string avatar); void osCauseHealing(string avatar, double healing); void osCauseDamage(string avatar, double damage); LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); @@ -388,59 +305,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// /// Rezzing object key or NULL_KEY if rezzed by agent or otherwise unknown. LSL_Key osGetRezzingObject(); - - /// - /// Sets the response type for an HTTP request/response - /// - /// - void osSetContentType(LSL_Key id, string type); - - /// - /// Attempts to drop an attachment to the ground - /// - void osDropAttachment(); - - /// - /// Attempts to drop an attachment to the ground while bypassing the script permissions - /// - void osForceDropAttachment(); - - /// - /// Attempts to drop an attachment at the specified coordinates. - /// - /// - /// - void osDropAttachmentAt(vector pos, rotation rot); - - /// - /// Attempts to drop an attachment at the specified coordinates while bypassing the script permissions - /// - /// - /// - void osForceDropAttachmentAt(vector pos, rotation rot); - - /// - /// Identical to llListen except for a bitfield which indicates which - /// string parameters should be parsed as regex patterns. - /// - /// - /// - /// - /// - /// - /// OS_LISTEN_REGEX_NAME - /// OS_LISTEN_REGEX_MESSAGE - /// - /// - LSL_Integer osListenRegex(int channelID, string name, string ID, - string msg, int regexBitfield); - - /// - /// Wraps to bool Regex.IsMatch(string input, string pattern) - /// - /// string to test for match - /// string to use as pattern - /// boolean - LSL_Integer osRegexIsMatch(string input, string pattern); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 0dd5a57383..f989cc654a 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -237,58 +237,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int ATTACH_HUD_BOTTOM = 37; public const int ATTACH_HUD_BOTTOM_RIGHT = 38; - #region osMessageAttachments constants - - /// - /// Instructs osMessageAttachements to send the message to attachments - /// on every point. - /// - /// - /// One might expect this to be named OS_ATTACH_ALL, but then one might - /// also expect functions designed to attach or detach or get - /// attachments to work with it too. Attaching a no-copy item to - /// many attachments could be dangerous. - /// when combined with OS_ATTACH_MSG_INVERT_POINTS, will prevent the - /// message from being sent. - /// if combined with OS_ATTACH_MSG_OBJECT_CREATOR or - /// OS_ATTACH_MSG_SCRIPT_CREATOR, could result in no message being - /// sent- this is expected behaviour. - /// - public const int OS_ATTACH_MSG_ALL = -65535; - - /// - /// Instructs osMessageAttachements to invert how the attachment points - /// list should be treated (e.g. go from inclusive operation to - /// exclusive operation). - /// - /// - /// This might be used if you want to deliver a message to one set of - /// attachments and a different message to everything else. With - /// this flag, you only need to build one explicit list for both calls. - /// - public const int OS_ATTACH_MSG_INVERT_POINTS = 1; - - /// - /// Instructs osMessageAttachments to only send the message to - /// attachments with a CreatorID that matches the host object CreatorID - /// - /// - /// This would be used if distributed in an object vendor/updater server. - /// - public const int OS_ATTACH_MSG_OBJECT_CREATOR = 2; - - /// - /// Instructs osMessageAttachments to only send the message to - /// attachments with a CreatorID that matches the sending script CreatorID - /// - /// - /// This might be used if the script is distributed independently of a - /// containing object. - /// - public const int OS_ATTACH_MSG_SCRIPT_CREATOR = 4; - - #endregion - public const int LAND_LEVEL = 0; public const int LAND_RAISE = 1; public const int LAND_LOWER = 2; @@ -381,7 +329,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PRIM_OMEGA = 32; public const int PRIM_POS_LOCAL = 33; public const int PRIM_LINK_TARGET = 34; - public const int PRIM_SLICE = 35; public const int PRIM_TEXGEN_DEFAULT = 0; public const int PRIM_TEXGEN_PLANAR = 1; @@ -613,7 +560,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int CLICK_ACTION_OPEN = 4; public const int CLICK_ACTION_PLAY = 5; public const int CLICK_ACTION_OPEN_MEDIA = 6; - public const int CLICK_ACTION_ZOOM = 7; // constants for the llDetectedTouch* functions public const int TOUCH_INVALID_FACE = -1; @@ -741,15 +687,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int KFM_CMD_PLAY = 0; public const int KFM_CMD_STOP = 1; public const int KFM_CMD_PAUSE = 2; - - /// - /// process name parameter as regex - /// - public const int OS_LISTEN_REGEX_NAME = 0x1; - - /// - /// process message parameter as regex - /// - public const int OS_LISTEN_REGEX_MESSAGE = 0x2; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index afa9ae0431..94405d2b5d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -289,7 +289,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osAvatarStopAnimation(avatar, animation); } - #region Attachment commands + // Avatar functions public void osForceAttachToAvatar(int attachmentPoint) { @@ -311,18 +311,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osForceDetachFromAvatar(); } - public LSL_List osGetNumberOfAttachments(LSL_Key avatar, LSL_List attachmentPoints) - { - return m_OSSL_Functions.osGetNumberOfAttachments(avatar, attachmentPoints); - } - - public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int flags) - { - m_OSSL_Functions.osMessageAttachments(avatar, message, attachmentPoints, flags); - } - - #endregion - // Texture Draw functions public string osMovePen(string drawList, int x, int y) @@ -877,12 +865,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osSetSpeed(UUID, SpeedModifier); } - - public LSL_Float osGetHealth(string avatar) - { - return m_OSSL_Functions.osGetHealth(avatar); - } - + public void osCauseDamage(string avatar, double damage) { m_OSSL_Functions.osCauseDamage(avatar, damage); @@ -967,40 +950,5 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osGetRezzingObject(); } - - public void osSetContentType(LSL_Key id, string type) - { - m_OSSL_Functions.osSetContentType(id,type); - } - - public void osDropAttachment() - { - m_OSSL_Functions.osDropAttachment(); - } - - public void osForceDropAttachment() - { - m_OSSL_Functions.osForceDropAttachment(); - } - - public void osDropAttachmentAt(vector pos, rotation rot) - { - m_OSSL_Functions.osDropAttachmentAt(pos, rot); - } - - public void osForceDropAttachmentAt(vector pos, rotation rot) - { - m_OSSL_Functions.osForceDropAttachmentAt(pos, rot); - } - - public LSL_Integer osListenRegex(int channelID, string name, string ID, string msg, int regexBitfield) - { - return m_OSSL_Functions.osListenRegex(channelID, name, ID, msg, regexBitfield); - } - - public LSL_Integer osRegexIsMatch(string input, string pattern) - { - return m_OSSL_Functions.osRegexIsMatch(input, pattern); - } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index 03be2abf07..17a0d69838 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -546,8 +546,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools "OpenSim.Region.ScriptEngine.Shared.dll")); parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, "OpenSim.Region.ScriptEngine.Shared.Api.Runtime.dll")); - parameters.ReferencedAssemblies.Add(Path.Combine(rootPath, - "OpenMetaverseTypes.dll")); if (lang == enumCompileType.yp) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs index 22804f50c6..9e5fb2420d 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Helpers.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Helpers.cs @@ -164,11 +164,11 @@ namespace OpenSim.Region.ScriptEngine.Shared else { // Set the values from the touch data provided by the client - touchST = new LSL_Types.Vector3(value.STCoord); - touchUV = new LSL_Types.Vector3(value.UVCoord); - touchNormal = new LSL_Types.Vector3(value.Normal); - touchBinormal = new LSL_Types.Vector3(value.Binormal); - touchPos = new LSL_Types.Vector3(value.Position); + touchST = new LSL_Types.Vector3(value.STCoord.X, value.STCoord.Y, value.STCoord.Z); + touchUV = new LSL_Types.Vector3(value.UVCoord.X, value.UVCoord.Y, value.UVCoord.Z); + touchNormal = new LSL_Types.Vector3(value.Normal.X, value.Normal.Y, value.Normal.Z); + touchBinormal = new LSL_Types.Vector3(value.Binormal.X, value.Binormal.Y, value.Binormal.Z); + touchPos = new LSL_Types.Vector3(value.Position.X, value.Position.Y, value.Position.Z); touchFace = value.FaceIndex; } } @@ -189,13 +189,19 @@ namespace OpenSim.Region.ScriptEngine.Shared Country = account.UserCountry; Owner = Key; - Position = new LSL_Types.Vector3(presence.AbsolutePosition); + Position = new LSL_Types.Vector3( + presence.AbsolutePosition.X, + presence.AbsolutePosition.Y, + presence.AbsolutePosition.Z); Rotation = new LSL_Types.Quaternion( presence.Rotation.X, presence.Rotation.Y, presence.Rotation.Z, presence.Rotation.W); - Velocity = new LSL_Types.Vector3(presence.Velocity); + Velocity = new LSL_Types.Vector3( + presence.Velocity.X, + presence.Velocity.Y, + presence.Velocity.Z); Type = 0x01; // Avatar if (presence.PresenceType == PresenceType.Npc) @@ -248,12 +254,16 @@ namespace OpenSim.Region.ScriptEngine.Shared } } - Position = new LSL_Types.Vector3(part.AbsolutePosition); + Position = new LSL_Types.Vector3(part.AbsolutePosition.X, + part.AbsolutePosition.Y, + part.AbsolutePosition.Z); Quaternion wr = part.ParentGroup.GroupRotation; Rotation = new LSL_Types.Quaternion(wr.X, wr.Y, wr.Z, wr.W); - Velocity = new LSL_Types.Vector3(part.Velocity); + Velocity = new LSL_Types.Vector3(part.Velocity.X, + part.Velocity.Y, + part.Velocity.Z); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index c9c4753195..8adf4c5bc8 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -31,11 +31,6 @@ using System.Globalization; using System.Text.RegularExpressions; using OpenSim.Framework; -using OpenMetaverse; -using OMV_Vector3 = OpenMetaverse.Vector3; -using OMV_Vector3d = OpenMetaverse.Vector3d; -using OMV_Quaternion = OpenMetaverse.Quaternion; - namespace OpenSim.Region.ScriptEngine.Shared { [Serializable] @@ -59,20 +54,6 @@ namespace OpenSim.Region.ScriptEngine.Shared z = (float)vector.z; } - public Vector3(OMV_Vector3 vector) - { - x = vector.X; - y = vector.Y; - z = vector.Z; - } - - public Vector3(OMV_Vector3d vector) - { - x = vector.X; - y = vector.Y; - z = vector.Z; - } - public Vector3(double X, double Y, double Z) { x = X; @@ -128,26 +109,6 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { vec }); } - public static implicit operator OMV_Vector3(Vector3 vec) - { - return new OMV_Vector3((float)vec.x, (float)vec.y, (float)vec.z); - } - - public static implicit operator Vector3(OMV_Vector3 vec) - { - return new Vector3(vec); - } - - public static implicit operator OMV_Vector3d(Vector3 vec) - { - return new OMV_Vector3d(vec.x, vec.y, vec.z); - } - - public static implicit operator Vector3(OMV_Vector3d vec) - { - return new Vector3(vec); - } - public static bool operator ==(Vector3 lhs, Vector3 rhs) { return (lhs.x == rhs.x && lhs.y == rhs.y && lhs.z == rhs.z); @@ -361,14 +322,6 @@ namespace OpenSim.Region.ScriptEngine.Shared s = 1; } - public Quaternion(OMV_Quaternion rot) - { - x = rot.X; - y = rot.Y; - z = rot.Z; - s = rot.W; - } - #endregion #region Overriders @@ -415,21 +368,6 @@ namespace OpenSim.Region.ScriptEngine.Shared return new list(new object[] { r }); } - public static implicit operator OMV_Quaternion(Quaternion rot) - { - // LSL quaternions can normalize to 0, normal Quaternions can't. - if (rot.s == 0 && rot.x == 0 && rot.y == 0 && rot.z == 0) - rot.z = 1; // ZERO_ROTATION = 0,0,0,1 - OMV_Quaternion omvrot = new OMV_Quaternion((float)rot.x, (float)rot.y, (float)rot.z, (float)rot.s); - omvrot.Normalize(); - return omvrot; - } - - public static implicit operator Quaternion(OMV_Quaternion rot) - { - return new Quaternion(rot); - } - public static bool operator ==(Quaternion lhs, Quaternion rhs) { // Return true if the fields match: @@ -624,23 +562,12 @@ namespace OpenSim.Region.ScriptEngine.Shared else if (m_data[itemIndex] is LSL_Types.LSLString) return new LSLInteger(m_data[itemIndex].ToString()); else - throw new InvalidCastException(string.Format( - "{0} expected but {1} given", - typeof(LSL_Types.LSLInteger).Name, - m_data[itemIndex] != null ? - m_data[itemIndex].GetType().Name : "null")); + throw new InvalidCastException(); } public LSL_Types.Vector3 GetVector3Item(int itemIndex) { - if(m_data[itemIndex] is LSL_Types.Vector3) - return (LSL_Types.Vector3)m_data[itemIndex]; - else - throw new InvalidCastException(string.Format( - "{0} expected but {1} given", - typeof(LSL_Types.Vector3).Name, - m_data[itemIndex] != null ? - m_data[itemIndex].GetType().Name : "null")); + return (LSL_Types.Vector3)m_data[itemIndex]; } public LSL_Types.Quaternion GetQuaternionItem(int itemIndex) diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs deleted file mode 100644 index dd23be8857..0000000000 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiListTests.cs +++ /dev/null @@ -1,134 +0,0 @@ -/* - * 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 NUnit.Framework; -using OpenSim.Framework; -using OpenSim.Tests.Common; -using OpenSim.Region.ScriptEngine.Shared; -using OpenSim.Region.Framework.Scenes; -using Nini.Config; -using OpenSim.Region.ScriptEngine.Shared.Api; -using OpenSim.Region.ScriptEngine.Shared.ScriptBase; -using OpenMetaverse; -using OpenSim.Tests.Common.Mock; - -using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; -using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; -using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; -using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; - -namespace OpenSim.Region.ScriptEngine.Shared.Tests -{ - [TestFixture] - public class LSL_ApiListTests - { - private LSL_Api m_lslApi; - - [SetUp] - public void SetUp() - { - IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); - config.Set("Enabled", "true"); - - Scene scene = new SceneHelpers().SetupScene(); - SceneObjectPart part = SceneHelpers.AddSceneObject(scene).RootPart; - - XEngine.XEngine engine = new XEngine.XEngine(); - engine.Initialise(initConfigSource); - engine.AddRegion(scene); - - m_lslApi = new LSL_Api(); - m_lslApi.Initialize(engine, part, null); - } - - [Test] - public void TestllListFindList() - { - TestHelpers.InMethod(); - - LSL_List src = new LSL_List(new LSL_Integer(1), new LSL_Integer(2), new LSL_Integer(3)); - - { - // Test for a single item that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for a single item that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2))); - Assert.That(result, Is.EqualTo(1)); - } - - { - // Test for a constant that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(ScriptBaseClass.AGENT)); - Assert.That(result, Is.EqualTo(0)); - } - - { - // Test for a list that should be found - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3))); - Assert.That(result, Is.EqualTo(1)); - } - - { - // Test for a single item not in the list - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for something that should not be cast - int result = m_lslApi.llListFindList(src, new LSL_List(new LSL_String("4"))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - // Test for a list not in the list - int result - = m_lslApi.llListFindList( - src, new LSL_List(new LSL_Integer(2), new LSL_Integer(3), new LSL_Integer(4))); - Assert.That(result, Is.EqualTo(-1)); - } - - { - LSL_List srcWithConstants - = new LSL_List(new LSL_Integer(3), ScriptBaseClass.AGENT, ScriptBaseClass.OS_NPC_LAND_AT_TARGET); - - // Test for constants that appears in the source list that should be found - int result - = m_lslApi.llListFindList(srcWithConstants, new LSL_List(new LSL_Integer(1), new LSL_Integer(2))); - - Assert.That(result, Is.EqualTo(1)); - } - } - } - } \ No newline at end of file diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs index c40179456d..c8718d9603 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiAppearanceTest.cs @@ -75,6 +75,76 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests m_engine.AddRegion(m_scene); } + /// + /// Test creation of an NPC where the appearance data comes from a notecard + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromNotecard() + { + 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, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the appearance in the notecard. + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + + /// + /// Test creation of an NPC where the appearance data comes from an avatar already in the region. + /// + [Test] + public void TestOsNpcCreateUsingAppearanceFromAvatar() + { + TestHelpers.InMethod(); +// TestHelpers.EnableLogging(); + + // 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, 0x10); + SceneObjectPart part = so.RootPart; + m_scene.AddSceneObject(so); + + OSSL_Api osslApi = new OSSL_Api(); + osslApi.Initialize(m_engine, part, null); + + string notecardName = "appearanceNc"; + osslApi.osOwnerSaveAppearance(notecardName); + + // Try creating a bot using the existing avatar's appearance + string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); + Assert.That(npcRaw, Is.Not.Null); + + UUID npcId = new UUID(npcRaw); + ScenePresence npc = m_scene.GetScenePresence(npcId); + Assert.That(npc, Is.Not.Null); + Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); + } + [Test] public void TestOsOwnerSaveAppearance() { diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs index b49bcc2000..25679a65c0 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/OSSL_ApiNpcTests.cs @@ -36,7 +36,6 @@ using OpenMetaverse; using OpenMetaverse.Assets; using OpenMetaverse.StructuredData; using OpenSim.Framework; -using OpenSim.Region.CoreModules.Avatar.Attachments; using OpenSim.Region.CoreModules.Avatar.AvatarFactory; using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Region.Framework.Scenes; @@ -72,193 +71,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests config.Set("Enabled", "true"); m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules( - m_scene, initConfigSource, new AvatarFactoryModule(), new AttachmentsModule(), new NPCModule()); + SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new AvatarFactoryModule(), new NPCModule()); m_engine = new XEngine.XEngine(); m_engine.Initialise(initConfigSource); m_engine.AddRegion(m_scene); } - /// - /// Test creation of an NPC where the appearance data comes from a notecard - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromNotecard() - { - TestHelpers.InMethod(); - - // 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, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the appearance in the notecard. - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), notecardName); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - [Test] - public void TestOsNpcCreateNotExistingNotecard() - { - TestHelpers.InMethod(); - - UUID userId = TestHelpers.ParseTail(0x1); - - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, so.RootPart, null); - - string npcRaw; - bool gotExpectedException = false; - try - { - npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), "not existing notecard name"); - } - catch (ScriptException) - { - gotExpectedException = true; - } - - Assert.That(gotExpectedException, Is.True); - } - - /// - /// Test creation of an NPC where the appearance data comes from an avatar already in the region. - /// - [Test] - public void TestOsNpcCreateUsingAppearanceFromAvatar() - { - TestHelpers.InMethod(); -// TestHelpers.EnableLogging(); - - // 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, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - string notecardName = "appearanceNc"; - osslApi.osOwnerSaveAppearance(notecardName); - - // Try creating a bot using the existing avatar's appearance - string npcRaw = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), sp.UUID.ToString()); - Assert.That(npcRaw, Is.Not.Null); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(newHeight)); - } - - [Test] - public void TestOsNpcLoadAppearance() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float firstHeight = 1.9f; - float secondHeight = 2.1f; - string firstAppearanceNcName = "appearanceNc1"; - string secondAppearanceNcName = "appearanceNc2"; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = firstHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - osslApi.osOwnerSaveAppearance(firstAppearanceNcName); - - string npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); - - // Create a second appearance notecard with a different height - sp.Appearance.AvatarHeight = secondHeight; - osslApi.osOwnerSaveAppearance(secondAppearanceNcName); - - osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(secondHeight)); - } - - [Test] - public void TestOsNpcLoadAppearanceNotExistingNotecard() - { - TestHelpers.InMethod(); - - // Store an avatar with a different height from default in a notecard. - UUID userId = TestHelpers.ParseTail(0x1); - float firstHeight = 1.9f; - float secondHeight = 2.1f; - string firstAppearanceNcName = "appearanceNc1"; - string secondAppearanceNcName = "appearanceNc2"; - - ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, userId); - sp.Appearance.AvatarHeight = firstHeight; - SceneObjectGroup so = SceneHelpers.CreateSceneObject(1, userId, 0x10); - SceneObjectPart part = so.RootPart; - m_scene.AddSceneObject(so); - - OSSL_Api osslApi = new OSSL_Api(); - osslApi.Initialize(m_engine, part, null); - - osslApi.osOwnerSaveAppearance(firstAppearanceNcName); - - string npcRaw - = osslApi.osNpcCreate("Jane", "Doe", new LSL_Types.Vector3(128, 128, 128), firstAppearanceNcName); - - bool gotExpectedException = false; - try - { - osslApi.osNpcLoadAppearance(npcRaw, secondAppearanceNcName); - } - catch (ScriptException) - { - gotExpectedException = true; - } - - Assert.That(gotExpectedException, Is.True); - - UUID npcId = new UUID(npcRaw); - ScenePresence npc = m_scene.GetScenePresence(npcId); - Assert.That(npc, Is.Not.Null); - Assert.That(npc.Appearance.AvatarHeight, Is.EqualTo(firstHeight)); - } - /// /// Test removal of an owned NPC. /// @@ -266,6 +85,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests 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); diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 9405075e51..5c4174e4e7 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -96,12 +96,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (part == null) return; - if ((part.ScriptEvents & scriptEvents.money) == 0) - part = part.ParentGroup.RootPart; - m_log.Debug("Paid: " + objectID + " from " + agentID + ", amount " + amount); -// part = part.ParentGroup.RootPart; + part = part.ParentGroup.RootPart; money(part.LocalId, agentID, amount); } @@ -155,7 +152,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine det[0] = new DetectParams(); det[0].Key = remoteClient.AgentId; det[0].Populate(myScriptEngine.World); - det[0].OffsetPos = offsetPos; + det[0].OffsetPos = new LSL_Types.Vector3(offsetPos.X, + offsetPos.Y, + offsetPos.Z); if (originalID == 0) { @@ -299,7 +298,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = detobj.posVector; + d.Position = new LSL_Types.Vector3(detobj.posVector.X, + detobj.posVector.Y, + detobj.posVector.Z); d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -317,7 +318,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = detobj.posVector; + d.Position = new LSL_Types.Vector3(detobj.posVector.X, + detobj.posVector.Y, + detobj.posVector.Z); d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -334,7 +337,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine foreach (DetectedObject detobj in col.Colliders) { DetectParams d = new DetectParams(); - d.Position = detobj.posVector; + d.Position = new LSL_Types.Vector3(detobj.posVector.X, + detobj.posVector.Y, + detobj.posVector.Z); d.Populate(myScriptEngine.World); det.Add(d); myScriptEngine.PostObjectEvent(localID, new EventParams( @@ -376,8 +381,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Vector3(targetpos), - new LSL_Types.Vector3(atpos) }, + new LSL_Types.Vector3(targetpos.X,targetpos.Y,targetpos.Z), + new LSL_Types.Vector3(atpos.X,atpos.Y,atpos.Z) }, new DetectParams[0])); } @@ -394,8 +399,8 @@ namespace OpenSim.Region.ScriptEngine.XEngine myScriptEngine.PostObjectEvent(localID, new EventParams( "at_rot_target", new object[] { new LSL_Types.LSLInteger(handle), - new LSL_Types.Quaternion(targetrot), - new LSL_Types.Quaternion(atrot) }, + new LSL_Types.Quaternion(targetrot.X,targetrot.Y,targetrot.Z,targetrot.W), + new LSL_Types.Quaternion(atrot.X,atrot.Y,atrot.Z,atrot.W) }, new DetectParams[0])); } diff --git a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs index f331658662..f247a0be42 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/Tests/XEngineTest.cs @@ -90,7 +90,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests // log4net.Config.XmlConfigurator.Configure(); UUID userId = TestHelpers.ParseTail(0x1); -// UUID objectId = TestHelpers.ParseTail(0x100); +// UUID objectId = TestHelpers.ParseTail(0x2); // UUID itemId = TestHelpers.ParseTail(0x3); string itemName = "TestStartScript() Item"; @@ -105,18 +105,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine.Tests m_scene.EventManager.OnChatFromWorld += OnChatFromWorld; - SceneObjectPart partWhereRezzed = m_scene.RezNewScript(userId, itemTemplate); + m_scene.RezNewScript(userId, itemTemplate); m_chatEvent.WaitOne(60000); Assert.That(m_osChatMessageReceived, Is.Not.Null, "No chat message received in TestStartScript()"); Assert.That(m_osChatMessageReceived.Message, Is.EqualTo("Script running")); - - bool running; - TaskInventoryItem scriptItem = partWhereRezzed.Inventory.GetInventoryItem(itemName); - Assert.That( - SceneObjectPartInventory.TryGetScriptInstanceRunning(m_scene, scriptItem, out running), Is.True); - Assert.That(running, Is.True); } private void OnChatFromWorld(object sender, OSChatMessage oscm) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 9f05666d7e..f6cb7dfa95 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -656,19 +656,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (m_Assemblies.ContainsKey(instance.AssetID)) { string assembly = m_Assemblies[instance.AssetID]; - - try - { - instance.SaveState(assembly); - } - catch (Exception e) - { - m_log.Error( - string.Format( - "[XEngine]: Failed final state save for script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", - instance.PrimName, instance.ScriptName, instance.ItemID, instance.ObjectID, World.Name) - , e); - } + instance.SaveState(assembly); } // Clear the event queue and abort the instance thread @@ -790,18 +778,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine assembly = m_Assemblies[i.AssetID]; - try - { - i.SaveState(assembly); - } - catch (Exception e) - { - m_log.Error( - string.Format( - "[XEngine]: Failed to save state of script {0}.{1}, item UUID {2}, prim UUID {3} in {4}. Exception ", - i.PrimName, i.ScriptName, i.ItemID, i.ObjectID, World.Name) - , e); - } + i.SaveState(assembly); } instances.Clear(); @@ -994,8 +971,6 @@ namespace OpenSim.Region.ScriptEngine.XEngine // This delay exists to stop mono problems where script compilation and startup would stop the sim // working properly for the session. System.Threading.Thread.Sleep(m_StartDelay); - - m_log.InfoFormat("[XEngine]: Performing initial script startup on {0}", m_Scene.Name); } object[] o; @@ -1011,13 +986,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (m_InitialStartup) if (scriptsStarted % 50 == 0) m_log.InfoFormat( - "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); + "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); } } if (m_InitialStartup) m_log.InfoFormat( - "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.Name); + "[XEngine]: Completed starting {0} scripts on {1}", scriptsStarted, m_Scene.RegionInfo.RegionName); // NOTE: Despite having a lockless queue, this lock is required // to make sure there is never no compile thread while there @@ -1078,13 +1053,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine return false; } - m_log.DebugFormat( - "[XEngine] Loading script {0}.{1}, item UUID {2}, prim UUID {3} @ {4}.{5}", - part.ParentGroup.RootPart.Name, item.Name, itemID, part.UUID, - part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); - UUID assetID = item.AssetID; + //m_log.DebugFormat("[XEngine] Compiling script {0} ({1} on object {2})", + // item.Name, itemID.ToString(), part.ParentGroup.RootPart.Name); + ScenePresence presence = m_Scene.GetScenePresence(item.OwnerID); string assembly = ""; @@ -1262,10 +1235,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine item.Name, startParam, postOnRez, stateSource, m_MaxScriptQueue); -// m_log.DebugFormat( -// "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", -// part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, -// part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); + m_log.DebugFormat( + "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", + part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, + part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); if (presence != null) { @@ -1581,9 +1554,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); + lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); + lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else @@ -1607,9 +1580,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine else if (p[i] is string) lsl_p[i] = new LSL_Types.LSLString((string)p[i]); else if (p[i] is Vector3) - lsl_p[i] = new LSL_Types.Vector3((Vector3)p[i]); + lsl_p[i] = new LSL_Types.Vector3(((Vector3)p[i]).X, ((Vector3)p[i]).Y, ((Vector3)p[i]).Z); else if (p[i] is Quaternion) - lsl_p[i] = new LSL_Types.Quaternion((Quaternion)p[i]); + lsl_p[i] = new LSL_Types.Quaternion(((Quaternion)p[i]).X, ((Quaternion)p[i]).Y, ((Quaternion)p[i]).Z, ((Quaternion)p[i]).W); else if (p[i] is float) lsl_p[i] = new LSL_Types.LSLFloat((float)p[i]); else diff --git a/OpenSim/Region/UserStatistics/WebStatsModule.cs b/OpenSim/Region/UserStatistics/WebStatsModule.cs index 625eba4b0a..c11ea0225a 100644 --- a/OpenSim/Region/UserStatistics/WebStatsModule.cs +++ b/OpenSim/Region/UserStatistics/WebStatsModule.cs @@ -61,7 +61,7 @@ namespace OpenSim.Region.UserStatistics /// /// User statistics sessions keyed by agent ID /// - private Dictionary m_sessions = new Dictionary(); + private Dictionary m_sessions = new Dictionary(); private List m_scenes = new List(); private Dictionary reports = new Dictionary(); @@ -319,18 +319,14 @@ namespace OpenSim.Region.UserStatistics private void OnMakeRootAgent(ScenePresence agent) { -// m_log.DebugFormat( -// "[WEB STATS MODULE]: Looking for session {0} for {1} in {2}", -// agent.ControllingClient.SessionId, agent.Name, agent.Scene.Name); - lock (m_sessions) { - UserSession uid; + UserSessionID uid; if (!m_sessions.ContainsKey(agent.UUID)) { UserSessionData usd = UserSessionUtil.newUserSessionData(); - uid = new UserSession(); + uid = new UserSessionID(); uid.name_f = agent.Firstname; uid.name_l = agent.Lastname; uid.session_data = usd; @@ -415,9 +411,9 @@ namespace OpenSim.Region.UserStatistics return String.Empty; } - private UserSession ParseViewerStats(string request, UUID agentID) + private UserSessionID ParseViewerStats(string request, UUID agentID) { - UserSession uid = new UserSession(); + UserSessionID uid = new UserSessionID(); UserSessionData usd; OSD message = OSDParser.DeserializeLLSDXml(request); OSDMap mmap; @@ -429,25 +425,22 @@ namespace OpenSim.Region.UserStatistics if (!m_sessions.ContainsKey(agentID)) { m_log.WarnFormat("[WEB STATS MODULE]: no session for stat disclosure for agent {0}", agentID); - return new UserSession(); + return new UserSessionID(); } - uid = m_sessions[agentID]; - -// m_log.DebugFormat("[WEB STATS MODULE]: Got session {0} for {1}", uid.session_id, agentID); } else { // parse through the beginning to locate the session if (message.Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); mmap = (OSDMap)message; { UUID sessionID = mmap["session_id"].AsUUID(); if (sessionID == UUID.Zero) - return new UserSession(); + return new UserSessionID(); // search through each session looking for the owner @@ -466,7 +459,7 @@ namespace OpenSim.Region.UserStatistics // can't find a session if (agentID == UUID.Zero) { - return new UserSession(); + return new UserSessionID(); } } } @@ -475,12 +468,12 @@ namespace OpenSim.Region.UserStatistics usd = uid.session_data; if (message.Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); mmap = (OSDMap)message; { if (mmap["agent"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap agent_map = (OSDMap)mmap["agent"]; usd.agent_id = agentID; usd.name_f = uid.name_f; @@ -500,18 +493,17 @@ namespace OpenSim.Region.UserStatistics (float)agent_map["fps"].AsReal()); if (mmap["downloads"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap downloads_map = (OSDMap)mmap["downloads"]; usd.d_object_kb = (float)downloads_map["object_kbytes"].AsReal(); usd.d_texture_kb = (float)downloads_map["texture_kbytes"].AsReal(); usd.d_world_kb = (float)downloads_map["workd_kbytes"].AsReal(); -// m_log.DebugFormat("[WEB STATS MODULE]: mmap[\"session_id\"] = [{0}]", mmap["session_id"].AsUUID()); usd.session_id = mmap["session_id"].AsUUID(); if (mmap["system"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap system_map = (OSDMap)mmap["system"]; usd.s_cpu = system_map["cpu"].AsString(); @@ -520,13 +512,13 @@ namespace OpenSim.Region.UserStatistics usd.s_ram = system_map["ram"].AsInteger(); if (mmap["stats"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap stats_map = (OSDMap)mmap["stats"]; { if (stats_map["failures"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap stats_failures = (OSDMap)stats_map["failures"]; usd.f_dropped = stats_failures["dropped"].AsInteger(); usd.f_failed_resends = stats_failures["failed_resends"].AsInteger(); @@ -535,18 +527,18 @@ namespace OpenSim.Region.UserStatistics usd.f_send_packet = stats_failures["send_packet"].AsInteger(); if (stats_map["net"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap stats_net = (OSDMap)stats_map["net"]; { if (stats_net["in"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap net_in = (OSDMap)stats_net["in"]; usd.n_in_kb = (float)net_in["kbytes"].AsReal(); usd.n_in_pk = net_in["packets"].AsInteger(); if (stats_net["out"].Type != OSDType.Map) - return new UserSession(); + return new UserSessionID(); OSDMap net_out = (OSDMap)stats_net["out"]; usd.n_out_kb = (float)net_out["kbytes"].AsReal(); @@ -557,18 +549,11 @@ namespace OpenSim.Region.UserStatistics uid.session_data = usd; m_sessions[agentID] = uid; - -// m_log.DebugFormat( -// "[WEB STATS MODULE]: Parse data for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); - return uid; } - private void UpdateUserStats(UserSession uid, SqliteConnection db) + private void UpdateUserStats(UserSessionID uid, SqliteConnection db) { -// m_log.DebugFormat( -// "[WEB STATS MODULE]: Updating user stats for {0} {1}, session {2}", uid.name_f, uid.name_l, uid.session_id); - if (uid.session_id == UUID.Zero) return; @@ -755,6 +740,7 @@ VALUES s.min_ping = ArrayMin_f(__ping); s.max_ping = ArrayMax_f(__ping); s.mode_ping = ArrayMode_f(__ping); + } #region Statistics @@ -999,7 +985,7 @@ VALUES } #region structs - public class UserSession + public struct UserSessionID { public UUID session_id; public UUID region_id; diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 0cff6ed5df..b137c05889 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -26,7 +26,6 @@ */ using System; -using System.Collections.Generic; using System.IO; using System.Reflection; using System.Threading; @@ -72,17 +71,10 @@ namespace OpenSim.Server.Base // private string m_pidFile = String.Empty; - /// - /// Time at which this server was started - /// - protected DateTime m_startuptime; - // Handle all the automagical stuff // public ServicesServerBase(string prompt, string[] args) { - m_startuptime = DateTime.Now; - // Save raw arguments // m_Arguments = args; @@ -258,10 +250,6 @@ namespace OpenSim.Server.Base "command-script