diff --git a/.nant/local.include b/.nant/local.include index 5ff96446c5..be79d1cfce 100644 --- a/.nant/local.include +++ b/.nant/local.include @@ -145,7 +145,12 @@ - + + + + + + @@ -260,6 +265,11 @@ + + + + + @@ -271,6 +281,7 @@ + diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index 0e3a1729b5..5b76e0a5b8 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -787,7 +787,7 @@ namespace OpenSim.Groups remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, false); + SendAgentGroupDataUpdate(remoteClient, true); } else remoteClient.SendCreateGroupReply(groupID, false, reason); diff --git a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs index af007709be..51f3ec15e0 100644 --- a/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Hypergrid/HGGroupsServiceRobustConnector.cs @@ -115,9 +115,10 @@ namespace OpenSim.Groups protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs index 598e7a5a9d..8502bb5bda 100644 --- a/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs +++ b/OpenSim/Addons/Groups/Remote/GroupsServiceRobustConnector.cs @@ -91,9 +91,10 @@ namespace OpenSim.Groups protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 597b4397c5..510905f64e 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -359,6 +359,42 @@ namespace OpenSim.ApplicationPlugins.RemoteController notice = false; } + if (startupConfig.GetBoolean("SkipDelayOnEmptyRegion", false)) + { + m_log.Info("[RADMIN]: Counting affected avatars"); + int agents = 0; + + if (restartAll) + { + foreach (Scene s in m_application.SceneManager.Scenes) + { + foreach (ScenePresence sp in s.GetScenePresences()) + { + if (!sp.IsChildAgent && !sp.IsNPC) + agents++; + } + } + } + else + { + foreach (ScenePresence sp in rebootedScene.GetScenePresences()) + { + if (!sp.IsChildAgent && !sp.IsNPC) + agents++; + } + } + + m_log.InfoFormat("[RADMIN]: Avatars in region: {0}", agents); + + if (agents == 0) + { + m_log.Info("[RADMIN]: No avatars detected, shutting down without delay"); + + times.Clear(); + times.Add(0); + } + } + List restartList; if (restartAll) @@ -376,10 +412,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController } catch (Exception e) { -// m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace); + m_log.ErrorFormat("[RADMIN]: Restart region: failed: {0} {1}", e.Message, e.StackTrace); responseData["rebooting"] = false; - throw e; + throw; } m_log.Info("[RADMIN]: Restart Region request complete"); @@ -3051,15 +3087,13 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// private void ApplyNextOwnerPermissions(InventoryItemBase item) { - if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) + if (item.InvType == (int)InventoryType.Object) { - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Modify; + uint perms = item.CurrentPermissions; + PermissionsUtil.ApplyFoldedPermissions(item.CurrentPermissions, ref perms); + item.CurrentPermissions = perms; } + item.CurrentPermissions &= item.NextPermissions; item.BasePermissions &= item.NextPermissions; item.EveryOnePermissions &= item.NextPermissions; diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs index 062a842748..e73cf9eca0 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureHandler.cs @@ -362,8 +362,6 @@ namespace OpenSim.Capabilities.Handlers { // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data - imgstream = new MemoryStream(); - // Decode image to System.Drawing.Image if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image) && image != null) { @@ -404,10 +402,7 @@ namespace OpenSim.Capabilities.Handlers if(managedImage != null) managedImage.Clear(); if (imgstream != null) - { - imgstream.Close(); imgstream.Dispose(); - } } return data; diff --git a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs index d5df7a29bd..c339ec5d7e 100644 --- a/OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs +++ b/OpenSim/Capabilities/Handlers/GetTexture/GetTextureRobustHandler.cs @@ -368,9 +368,6 @@ namespace OpenSim.Capabilities.Handlers try { // Taking our jpeg2000 data, decoding it, then saving it to a byte array with regular data - - imgstream = new MemoryStream(); - // Decode image to System.Drawing.Image if (OpenJPEG.DecodeToImage(texture.Data, out managedImage, out image) && image != null) { @@ -412,10 +409,7 @@ namespace OpenSim.Capabilities.Handlers managedImage.Clear(); if (imgstream != null) - { - imgstream.Close(); imgstream.Dispose(); - } } return data; diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs index 80b83069e2..48274c1ae5 100644 --- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureHandler.cs @@ -26,24 +26,12 @@ */ using System; -using System.Collections; -using System.Collections.Generic; -using System.Collections.Specialized; -using System.Drawing; -using System.Drawing.Imaging; using System.Reflection; -using System.IO; -using System.Web; using log4net; -using Nini.Config; using OpenMetaverse; -using OpenMetaverse.StructuredData; -using OpenMetaverse.Imaging; using OpenSim.Framework; using OpenSim.Framework.Capabilities; -using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; -using OpenSim.Region.Framework.Interfaces; using OpenSim.Services.Interfaces; using Caps = OpenSim.Framework.Capabilities.Caps; @@ -56,13 +44,11 @@ namespace OpenSim.Capabilities.Handlers private Caps m_HostCapsObj; private IAssetService m_assetService; - private bool m_persistBakedTextures; - public UploadBakedTextureHandler(Caps caps, IAssetService assetService, bool persistBakedTextures) + public UploadBakedTextureHandler(Caps caps, IAssetService assetService) { m_HostCapsObj = caps; m_assetService = assetService; - m_persistBakedTextures = persistBakedTextures; } /// @@ -125,9 +111,8 @@ namespace OpenSim.Capabilities.Handlers asset = new AssetBase(assetID, "Baked Texture", (sbyte)AssetType.Texture, m_HostCapsObj.AgentID.ToString()); asset.Data = data; asset.Temporary = true; - asset.Local = !m_persistBakedTextures; // Local assets aren't persisted, non-local are + asset.Local = true; m_assetService.Store(asset); - } } @@ -151,8 +136,6 @@ namespace OpenSim.Capabilities.Handlers // m_log.InfoFormat("[CAPS] baked texture upload starting for {0}",newAssetID); } - - /// /// Handle raw uploaded baked texture data. /// diff --git a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs index 10ea8eefe6..fd484bad8e 100644 --- a/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs +++ b/OpenSim/Capabilities/Handlers/UploadBakedTexture/UploadBakedTextureServerConnector.cs @@ -67,7 +67,7 @@ namespace OpenSim.Capabilities.Handlers server.AddStreamHandler(new RestStreamHandler( "POST", "/CAPS/UploadBakedTexture/", - new UploadBakedTextureHandler(caps, m_AssetService, true).UploadBakedTexture, + new UploadBakedTextureHandler(caps, m_AssetService).UploadBakedTexture, "UploadBakedTexture", "Upload Baked Texture Capability")); diff --git a/OpenSim/Capabilities/LLSD.cs b/OpenSim/Capabilities/LLSD.cs index c59cede3f4..76e439f9e7 100644 --- a/OpenSim/Capabilities/LLSD.cs +++ b/OpenSim/Capabilities/LLSD.cs @@ -566,7 +566,7 @@ namespace OpenSim.Framework.Capabilities endPos = FindEnd(llsd, 1); if (Double.TryParse(llsd.Substring(1, endPos - 1), NumberStyles.Float, - Utils.EnUsCulture.NumberFormat, out value)) + Culture.NumberFormatInfo, out value)) return value; else throw new LLSDParseException("Failed to parse double value type"); diff --git a/OpenSim/Capabilities/LLSDHelpers.cs b/OpenSim/Capabilities/LLSDHelpers.cs index 8f1a40e632..d5822675ae 100644 --- a/OpenSim/Capabilities/LLSDHelpers.cs +++ b/OpenSim/Capabilities/LLSDHelpers.cs @@ -157,6 +157,11 @@ namespace OpenSim.Framework.Capabilities // the LLSD map/array types in the array need to be deserialised // but first we need to know the right class to deserialise them into. } + else if(enumerator.Value is Boolean && field.FieldType == typeof(int) ) + { + int i = (bool)enumerator.Value ? 1 : 0; + field.SetValue(obj, (object)i); + } else { field.SetValue(obj, enumerator.Value); diff --git a/OpenSim/Data/MySQL/MySQLAssetData.cs b/OpenSim/Data/MySQL/MySQLAssetData.cs index f16cd913e7..8569c903a6 100644 --- a/OpenSim/Data/MySQL/MySQLAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLAssetData.cs @@ -75,6 +75,7 @@ namespace OpenSim.Data.MySQL dbcon.Open(); Migration m = new Migration(dbcon, Assembly, "AssetStore"); m.Update(); + dbcon.Close(); } } @@ -144,6 +145,7 @@ namespace OpenSim.Data.MySQL string.Format("[ASSETS DB]: MySql failure fetching asset {0}. Exception ", assetID), e); } } + dbcon.Close(); } return asset; @@ -156,28 +158,27 @@ namespace OpenSim.Data.MySQL /// On failure : Throw an exception and attempt to reconnect to database override public bool StoreAsset(AssetBase asset) { + string assetName = asset.Name; + if (asset.Name.Length > AssetBase.MAX_ASSET_NAME) + { + assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME); + m_log.WarnFormat( + "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add", + asset.Name, asset.ID, asset.Name.Length, assetName.Length); + } + + string assetDescription = asset.Description; + if (asset.Description.Length > AssetBase.MAX_ASSET_DESC) + { + assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC); + m_log.WarnFormat( + "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add", + asset.Description, asset.ID, asset.Description.Length, assetDescription.Length); + } + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); - - string assetName = asset.Name; - if (asset.Name.Length > AssetBase.MAX_ASSET_NAME) - { - assetName = asset.Name.Substring(0, AssetBase.MAX_ASSET_NAME); - m_log.WarnFormat( - "[ASSET DB]: Name '{0}' for asset {1} truncated from {2} to {3} characters on add", - asset.Name, asset.ID, asset.Name.Length, assetName.Length); - } - - string assetDescription = asset.Description; - if (asset.Description.Length > AssetBase.MAX_ASSET_DESC) - { - assetDescription = asset.Description.Substring(0, AssetBase.MAX_ASSET_DESC); - m_log.WarnFormat( - "[ASSET DB]: Description '{0}' for asset {1} truncated from {2} to {3} characters on add", - asset.Description, asset.ID, asset.Description.Length, assetDescription.Length); - } - using (MySqlCommand cmd = new MySqlCommand( "replace INTO assets(id, name, description, assetType, local, temporary, create_time, access_time, asset_flags, CreatorID, data)" + @@ -200,15 +201,17 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?asset_flags", (int)asset.Flags); cmd.Parameters.AddWithValue("?data", asset.Data); cmd.ExecuteNonQuery(); + dbcon.Close(); return true; } catch (Exception e) { m_log.ErrorFormat("[ASSET DB]: MySQL failure creating asset {0} with name \"{1}\". Error: {2}", asset.FullID, asset.Name, e.Message); + dbcon.Close(); return false; } - } + } } } @@ -238,6 +241,7 @@ namespace OpenSim.Data.MySQL e); } } + dbcon.Close(); } } @@ -270,6 +274,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } bool[] results = new bool[uuids.Length]; @@ -334,6 +339,7 @@ namespace OpenSim.Data.MySQL e); } } + dbcon.Close(); } return retList; @@ -350,6 +356,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?id", id); cmd.ExecuteNonQuery(); } + dbcon.Close(); } return true; diff --git a/OpenSim/Data/MySQL/MySQLAuthenticationData.cs b/OpenSim/Data/MySQL/MySQLAuthenticationData.cs index af6be75bf7..fef582e809 100644 --- a/OpenSim/Data/MySQL/MySQLAuthenticationData.cs +++ b/OpenSim/Data/MySQL/MySQLAuthenticationData.cs @@ -59,6 +59,7 @@ namespace OpenSim.Data.MySQL dbcon.Open(); Migration m = new Migration(dbcon, Assembly, "AuthStore"); m.Update(); + dbcon.Close(); } } @@ -76,27 +77,30 @@ namespace OpenSim.Data.MySQL { cmd.Parameters.AddWithValue("?principalID", principalID.ToString()); - IDataReader result = cmd.ExecuteReader(); - - if (result.Read()) + using(IDataReader result = cmd.ExecuteReader()) { - ret.PrincipalID = principalID; - - CheckColumnNames(result); - - foreach (string s in m_ColumnNames) + if(result.Read()) { - if (s == "UUID") - continue; + ret.PrincipalID = principalID; - ret.Data[s] = result[s].ToString(); + CheckColumnNames(result); + + foreach(string s in m_ColumnNames) + { + if(s == "UUID") + continue; + + ret.Data[s] = result[s].ToString(); + } + + dbcon.Close(); + return ret; + } + else + { + dbcon.Close(); + return null; } - - return ret; - } - else - { - return null; } } } diff --git a/OpenSim/Data/MySQL/MySQLEstateData.cs b/OpenSim/Data/MySQL/MySQLEstateData.cs index a5c8d24de5..eeedf02b29 100644 --- a/OpenSim/Data/MySQL/MySQLEstateData.cs +++ b/OpenSim/Data/MySQL/MySQLEstateData.cs @@ -82,6 +82,7 @@ namespace OpenSim.Data.MySQL Migration m = new Migration(dbcon, Assembly, "EstateStore"); m.Update(); + dbcon.Close(); Type t = typeof(EstateSettings); m_Fields = t.GetFields(BindingFlags.NonPublic | @@ -143,7 +144,6 @@ namespace OpenSim.Data.MySQL using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); - cmd.Connection = dbcon; bool found = false; @@ -171,6 +171,8 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); + cmd.Connection = null; if (!found && create) { @@ -231,6 +233,7 @@ namespace OpenSim.Data.MySQL es.Save(); } + dbcon.Close(); } } @@ -263,6 +266,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } SaveBanList(es); @@ -300,6 +304,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } @@ -329,6 +334,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.Clear(); } } + dbcon.Close(); } } @@ -358,6 +364,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.Clear(); } } + dbcon.Close(); } } @@ -383,6 +390,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } return uuids.ToArray(); @@ -437,7 +445,6 @@ namespace OpenSim.Data.MySQL reader.Close(); } } - dbcon.Close(); } @@ -466,7 +473,6 @@ namespace OpenSim.Data.MySQL reader.Close(); } } - dbcon.Close(); } diff --git a/OpenSim/Data/MySQL/MySQLFSAssetData.cs b/OpenSim/Data/MySQL/MySQLFSAssetData.cs index 2837ce31be..6c486077d3 100644 --- a/OpenSim/Data/MySQL/MySQLFSAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLFSAssetData.cs @@ -78,6 +78,7 @@ namespace OpenSim.Data.MySQL conn.Open(); Migration m = new Migration(conn, Assembly, "FSAssetStore"); m.Update(); + conn.Close(); } } catch (MySqlException e) @@ -121,9 +122,13 @@ namespace OpenSim.Data.MySQL } catch (MySqlException e) { + cmd.Connection = null; + conn.Close(); m_log.ErrorFormat("[FSASSETS]: Query {0} failed with {1}", cmd.CommandText, e.ToString()); return false; } + conn.Close(); + cmd.Connection = null; } return true; @@ -175,7 +180,7 @@ namespace OpenSim.Data.MySQL UpdateAccessTime(id, AccessTime); } } - + conn.Close(); } return meta; @@ -206,6 +211,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?id", AssetID); cmd.ExecuteNonQuery(); } + conn.Close(); } } @@ -299,6 +305,7 @@ namespace OpenSim.Data.MySQL } } } + conn.Close(); } for (int i = 0; i < uuids.Length; i++) @@ -333,6 +340,7 @@ namespace OpenSim.Data.MySQL count = Convert.ToInt32(reader["count"]); } } + conn.Close(); } return count; @@ -413,8 +421,8 @@ namespace OpenSim.Data.MySQL imported++; } } - } + importConn.Close(); } MainConsole.Instance.Output(String.Format("Import done, {0} assets imported", imported)); diff --git a/OpenSim/Data/MySQL/MySQLFramework.cs b/OpenSim/Data/MySQL/MySQLFramework.cs index 34791cf6be..98106f0057 100644 --- a/OpenSim/Data/MySQL/MySQLFramework.cs +++ b/OpenSim/Data/MySQL/MySQLFramework.cs @@ -36,7 +36,7 @@ using MySql.Data.MySqlClient; namespace OpenSim.Data.MySQL { /// - /// A database interface class to a user profile storage system + /// Common code for a number of database modules /// public class MySqlFramework { @@ -44,14 +44,24 @@ namespace OpenSim.Data.MySQL log4net.LogManager.GetLogger( System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - protected string m_connectionString; - protected object m_dbLock = new object(); + protected string m_connectionString = String.Empty; + protected MySqlTransaction m_trans = null; + // Constructor using a connection string. Instances constructed + // this way will open a new connection for each call. protected MySqlFramework(string connectionString) { m_connectionString = connectionString; } + // Constructor using a connection object. Instances constructed + // this way will use the connection object and never create + // new connections. + protected MySqlFramework(MySqlTransaction trans) + { + m_trans = trans; + } + ////////////////////////////////////////////////////////////// // // All non queries are funneled through one connection @@ -59,33 +69,53 @@ namespace OpenSim.Data.MySQL // protected int ExecuteNonQuery(MySqlCommand cmd) { - lock (m_dbLock) + if (m_trans == null) { using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - try - { - dbcon.Open(); - cmd.Connection = dbcon; - - try - { - return cmd.ExecuteNonQuery(); - } - catch (Exception e) - { - m_log.Error(e.Message, e); - m_log.Error(Environment.StackTrace.ToString()); - return 0; - } - } - catch (Exception e) - { - m_log.Error(e.Message, e); - return 0; - } + dbcon.Open(); + int ret = ExecuteNonQueryWithConnection(cmd, dbcon); + dbcon.Close(); + return ret; } } + else + { + return ExecuteNonQueryWithTransaction(cmd, m_trans); + } + } + + private int ExecuteNonQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans) + { + cmd.Transaction = trans; + return ExecuteNonQueryWithConnection(cmd, trans.Connection); + } + + private int ExecuteNonQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon) + { + try + { + cmd.Connection = dbcon; + + try + { + int ret = cmd.ExecuteNonQuery(); + cmd.Connection = null; + return ret; + } + catch (Exception e) + { + m_log.Error(e.Message, e); + m_log.Error(Environment.StackTrace.ToString()); + cmd.Connection = null; + return 0; + } + } + catch (Exception e) + { + m_log.Error(e.Message, e); + return 0; + } } } -} \ No newline at end of file +} diff --git a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs index 6aae9c644b..9bd3c0cc26 100644 --- a/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs +++ b/OpenSim/Data/MySQL/MySQLGenericTableHandler.cs @@ -53,14 +53,27 @@ namespace OpenSim.Data.MySQL get { return GetType().Assembly; } } + public MySQLGenericTableHandler(MySqlTransaction trans, + string realm, string storeName) : base(trans) + { + m_Realm = realm; + + CommonConstruct(storeName); + } + public MySQLGenericTableHandler(string connectionString, string realm, string storeName) : base(connectionString) { m_Realm = realm; - m_connectionString = connectionString; + CommonConstruct(storeName); + } + + protected void CommonConstruct(string storeName) + { if (storeName != String.Empty) { + // We always use a new connection for any Migrations using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); @@ -110,6 +123,11 @@ namespace OpenSim.Data.MySQL } public virtual T[] Get(string[] fields, string[] keys) + { + return Get(fields, keys, String.Empty); + } + + public virtual T[] Get(string[] fields, string[] keys, string options) { if (fields.Length != keys.Length) return new T[0]; @@ -126,8 +144,8 @@ namespace OpenSim.Data.MySQL string where = String.Join(" and ", terms.ToArray()); - string query = String.Format("select * from {0} where {1}", - m_Realm, where); + string query = String.Format("select * from {0} where {1} {2}", + m_Realm, where, options); cmd.CommandText = query; @@ -137,75 +155,96 @@ namespace OpenSim.Data.MySQL protected T[] DoQuery(MySqlCommand cmd) { - List result = new List(); - - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + if (m_trans == null) { - dbcon.Open(); - cmd.Connection = dbcon; - - using (IDataReader reader = cmd.ExecuteReader()) + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { - if (reader == null) - return new T[0]; - - CheckColumnNames(reader); - - while (reader.Read()) - { - T row = new T(); - - foreach (string name in m_Fields.Keys) - { - if (reader[name] is DBNull) - { - continue; - } - if (m_Fields[name].FieldType == typeof(bool)) - { - int v = Convert.ToInt32(reader[name]); - m_Fields[name].SetValue(row, v != 0 ? true : false); - } - else if (m_Fields[name].FieldType == typeof(UUID)) - { - m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name])); - } - else if (m_Fields[name].FieldType == typeof(int)) - { - int v = Convert.ToInt32(reader[name]); - m_Fields[name].SetValue(row, v); - } - else if (m_Fields[name].FieldType == typeof(uint)) - { - uint v = Convert.ToUInt32(reader[name]); - m_Fields[name].SetValue(row, v); - } - else - { - m_Fields[name].SetValue(row, reader[name]); - } - } - - if (m_DataField != null) - { - Dictionary data = - new Dictionary(); - - foreach (string col in m_ColumnNames) - { - data[col] = reader[col].ToString(); - if (data[col] == null) - data[col] = String.Empty; - } - - m_DataField.SetValue(row, data); - } - - result.Add(row); - } + dbcon.Open(); + T[] ret = DoQueryWithConnection(cmd, dbcon); + dbcon.Close(); + return ret; } } + else + { + return DoQueryWithTransaction(cmd, m_trans); + } + } + protected T[] DoQueryWithTransaction(MySqlCommand cmd, MySqlTransaction trans) + { + cmd.Transaction = trans; + + return DoQueryWithConnection(cmd, trans.Connection); + } + + protected T[] DoQueryWithConnection(MySqlCommand cmd, MySqlConnection dbcon) + { + List result = new List(); + + cmd.Connection = dbcon; + + using (IDataReader reader = cmd.ExecuteReader()) + { + if (reader == null) + return new T[0]; + + CheckColumnNames(reader); + + while (reader.Read()) + { + T row = new T(); + + foreach (string name in m_Fields.Keys) + { + if (reader[name] is DBNull) + { + continue; + } + if (m_Fields[name].FieldType == typeof(bool)) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v != 0 ? true : false); + } + else if (m_Fields[name].FieldType == typeof(UUID)) + { + m_Fields[name].SetValue(row, DBGuid.FromDB(reader[name])); + } + else if (m_Fields[name].FieldType == typeof(int)) + { + int v = Convert.ToInt32(reader[name]); + m_Fields[name].SetValue(row, v); + } + else if (m_Fields[name].FieldType == typeof(uint)) + { + uint v = Convert.ToUInt32(reader[name]); + m_Fields[name].SetValue(row, v); + } + else + { + m_Fields[name].SetValue(row, reader[name]); + } + } + + if (m_DataField != null) + { + Dictionary data = + new Dictionary(); + + foreach (string col in m_ColumnNames) + { + data[col] = reader[col].ToString(); + if (data[col] == null) + data[col] = String.Empty; + } + + m_DataField.SetValue(row, data); + } + + result.Add(row); + } + } + cmd.Connection = null; return result.ToArray(); } @@ -357,14 +396,26 @@ namespace OpenSim.Data.MySQL public object DoQueryScalar(MySqlCommand cmd) { - using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + if (m_trans == null) { - dbcon.Open(); - cmd.Connection = dbcon; + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) + { + dbcon.Open(); + cmd.Connection = dbcon; + + Object ret = cmd.ExecuteScalar(); + cmd.Connection = null; + dbcon.Close(); + return ret; + } + } + else + { + cmd.Connection = m_trans.Connection; + cmd.Transaction = m_trans; return cmd.ExecuteScalar(); } } - } } diff --git a/OpenSim/Data/MySQL/MySQLInventoryData.cs b/OpenSim/Data/MySQL/MySQLInventoryData.cs index 382d4a5c33..cc787ccde8 100644 --- a/OpenSim/Data/MySQL/MySQLInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLInventoryData.cs @@ -78,6 +78,7 @@ namespace OpenSim.Data.MySQL dbcon.Open(); Migration m = new Migration(dbcon, assem, "InventoryStore"); m.Update(); + dbcon.Close(); } } @@ -130,6 +131,7 @@ namespace OpenSim.Data.MySQL items.Add(item); } + dbcon.Close(); return items; } } @@ -170,6 +172,7 @@ namespace OpenSim.Data.MySQL while (reader.Read()) items.Add(readInventoryFolder(reader)); + dbcon.Close(); return items; } } @@ -221,6 +224,7 @@ namespace OpenSim.Data.MySQL if (items.Count > 0) rootFolder = items[0]; + dbcon.Close(); return rootFolder; } } @@ -261,6 +265,7 @@ namespace OpenSim.Data.MySQL while (reader.Read()) items.Add(readInventoryFolder(reader)); + dbcon.Close(); return items; } } @@ -352,6 +357,7 @@ namespace OpenSim.Data.MySQL if (reader.Read()) item = readInventoryItem(reader); + dbcon.Close(); return item; } } @@ -417,6 +423,7 @@ namespace OpenSim.Data.MySQL if (reader.Read()) folder = readInventoryFolder(reader); + dbcon.Close(); return folder; } } @@ -504,6 +511,7 @@ namespace OpenSim.Data.MySQL lock (m_dbLock) result.ExecuteNonQuery(); } + dbcon.Close(); } } catch (MySqlException e) @@ -540,6 +548,7 @@ namespace OpenSim.Data.MySQL lock (m_dbLock) cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (MySqlException e) @@ -600,6 +609,7 @@ namespace OpenSim.Data.MySQL m_log.Error(e.ToString()); } } + dbcon.Close(); } } @@ -643,6 +653,7 @@ namespace OpenSim.Data.MySQL m_log.Error(e.ToString()); } } + dbcon.Close(); } } @@ -806,6 +817,7 @@ namespace OpenSim.Data.MySQL lock (m_dbLock) cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (MySqlException e) @@ -833,6 +845,7 @@ namespace OpenSim.Data.MySQL lock (m_dbLock) cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (MySqlException e) @@ -886,6 +899,7 @@ namespace OpenSim.Data.MySQL if (item != null) list.Add(item); } + dbcon.Close(); return list; } } diff --git a/OpenSim/Data/MySQL/MySQLRegionData.cs b/OpenSim/Data/MySQL/MySQLRegionData.cs index 0e55285451..46df421352 100644 --- a/OpenSim/Data/MySQL/MySQLRegionData.cs +++ b/OpenSim/Data/MySQL/MySQLRegionData.cs @@ -60,6 +60,7 @@ namespace OpenSim.Data.MySQL dbcon.Open(); Migration m = new Migration(dbcon, Assembly, "GridStore"); m.Update(); + dbcon.Close(); } } @@ -260,6 +261,8 @@ namespace OpenSim.Data.MySQL retList.Add(ret); } } + cmd.Connection = null; + dbcon.Close(); } return retList; diff --git a/OpenSim/Data/MySQL/MySQLSimulationData.cs b/OpenSim/Data/MySQL/MySQLSimulationData.cs index 8278c0ec20..e754522f44 100644 --- a/OpenSim/Data/MySQL/MySQLSimulationData.cs +++ b/OpenSim/Data/MySQL/MySQLSimulationData.cs @@ -88,6 +88,7 @@ namespace OpenSim.Data.MySQL // Migration m = new Migration(dbcon, Assembly, "RegionStore"); m.Update(); + dbcon.Close(); } } @@ -187,7 +188,7 @@ namespace OpenSim.Data.MySQL "LinkNumber, MediaURL, KeyframeMotion, AttachedPosX, " + "AttachedPosY, AttachedPosZ, " + "PhysicsShapeType, Density, GravityModifier, " + - "Friction, Restitution, Vehicle, DynAttrs, " + + "Friction, Restitution, Vehicle, PhysInertia, DynAttrs, " + "RotationAxisLocks" + ") values (" + "?UUID, " + "?CreationDate, ?Name, ?Text, " + @@ -224,7 +225,7 @@ namespace OpenSim.Data.MySQL "?LinkNumber, ?MediaURL, ?KeyframeMotion, ?AttachedPosX, " + "?AttachedPosY, ?AttachedPosZ, " + "?PhysicsShapeType, ?Density, ?GravityModifier, " + - "?Friction, ?Restitution, ?Vehicle, ?DynAttrs," + + "?Friction, ?Restitution, ?Vehicle, ?PhysInertia, ?DynAttrs," + "?RotationAxisLocks)"; FillPrimCommand(cmd, prim, obj.UUID, regionUUID); @@ -261,6 +262,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } } + dbcon.Close(); } } } @@ -300,6 +302,7 @@ namespace OpenSim.Data.MySQL cmd.CommandText = "delete from prims where SceneGroupID= ?UUID"; ExecuteNonQuery(cmd); } + dbcon.Close(); } } @@ -334,6 +337,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } + dbcon.Close(); } } } @@ -372,6 +376,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } + dbcon.Close(); } } } @@ -411,6 +416,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } + dbcon.Close(); } } } @@ -460,6 +466,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } @@ -535,6 +542,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } @@ -580,6 +588,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } prim.Inventory.RestoreInventoryItems(inventory); @@ -598,6 +607,10 @@ namespace OpenSim.Data.MySQL { m_log.Info("[REGION DB]: Storing terrain"); + int terrainDBRevision; + Array terrainDBblob; + terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); + lock (m_dbLock) { using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) @@ -617,10 +630,6 @@ namespace OpenSim.Data.MySQL "Revision, Heightfield) values (?RegionUUID, " + "?Revision, ?Heightfield)"; - int terrainDBRevision; - Array terrainDBblob; - terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); - cmd2.Parameters.AddWithValue("RegionUUID", regionID.ToString()); cmd2.Parameters.AddWithValue("Revision", terrainDBRevision); cmd2.Parameters.AddWithValue("Heightfield", terrainDBblob); @@ -634,6 +643,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } }); @@ -645,6 +655,10 @@ namespace OpenSim.Data.MySQL { m_log.Info("[REGION DB]: Storing Baked terrain"); + int terrainDBRevision; + Array terrainDBblob; + terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); + lock (m_dbLock) { using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) @@ -664,10 +678,6 @@ namespace OpenSim.Data.MySQL "Revision, Heightfield) values (?RegionUUID, " + "?Revision, ?Heightfield)"; - int terrainDBRevision; - Array terrainDBblob; - terrData.GetDatabaseBlob(out terrainDBRevision, out terrainDBblob); - cmd2.Parameters.AddWithValue("RegionUUID", regionID.ToString()); cmd2.Parameters.AddWithValue("Revision", terrainDBRevision); cmd2.Parameters.AddWithValue("Heightfield", terrainDBblob); @@ -681,6 +691,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } }); @@ -700,9 +711,12 @@ namespace OpenSim.Data.MySQL public TerrainData LoadTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) { TerrainData terrData = null; + byte[] blob = null; + int rev = 0; lock (m_dbLock) { + using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { dbcon.Open(); @@ -718,24 +732,29 @@ namespace OpenSim.Data.MySQL { while (reader.Read()) { - int rev = Convert.ToInt32(reader["Revision"]); + rev = Convert.ToInt32(reader["Revision"]); if ((reader["Heightfield"] != DBNull.Value)) { - byte[] blob = (byte[])reader["Heightfield"]; - terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); + blob = (byte[])reader["Heightfield"]; } } } } + dbcon.Close(); } } + if(blob != null) + terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); + return terrData; } public TerrainData LoadBakedTerrain(UUID regionID, int pSizeX, int pSizeY, int pSizeZ) { TerrainData terrData = null; + byte[] blob = null; + int rev = 0; lock (m_dbLock) { @@ -753,17 +772,19 @@ namespace OpenSim.Data.MySQL { while (reader.Read()) { - int rev = Convert.ToInt32(reader["Revision"]); + rev = Convert.ToInt32(reader["Revision"]); if ((reader["Heightfield"] != DBNull.Value)) { - byte[] blob = (byte[])reader["Heightfield"]; - terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); + blob = (byte[])reader["Heightfield"]; } } } } + dbcon.Close(); } } + if(blob != null) + terrData = TerrainData.CreateFromDatabaseBlobFactory(pSizeX, pSizeY, pSizeZ, rev, blob); return terrData; } @@ -783,6 +804,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } + dbcon.Close(); } } } @@ -842,6 +864,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.Clear(); } } + dbcon.Close(); } } } @@ -863,82 +886,85 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?regionID", regionUUID.ToString()); - IDataReader result = ExecuteReader(cmd); - if (!result.Read()) + using(IDataReader result = ExecuteReader(cmd)) { - //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; + 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; + } } } + dbcon.Close(); } return nWP; @@ -947,6 +973,7 @@ namespace OpenSim.Data.MySQL public virtual RegionSettings LoadRegionSettings(UUID regionUUID) { RegionSettings rs = null; + bool needStore = false; lock (m_dbLock) { @@ -972,13 +999,17 @@ namespace OpenSim.Data.MySQL rs.RegionUUID = regionUUID; rs.OnSave += StoreRegionSettings; - StoreRegionSettings(rs); + needStore = true; } } } + dbcon.Close(); } } + if(needStore) + StoreRegionSettings(rs); + LoadSpawnPoints(rs); return rs; @@ -992,31 +1023,32 @@ namespace OpenSim.Data.MySQL 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.CommandText = "REPLACE INTO `regionwindlight` (`region_id`, `water_color_r`, `water_color_g`, " + + "`water_color_b`, `water_fog_density_exponent`, `underwater_fog_modifier`, " + + "`reflection_wavelet_scale_1`, `reflection_wavelet_scale_2`, `reflection_wavelet_scale_3`, " + + "`fresnel_scale`, `fresnel_offset`, `refract_scale_above`, `refract_scale_below`, " + + "`blur_multiplier`, `big_wave_direction_x`, `big_wave_direction_y`, `little_wave_direction_x`, " + + "`little_wave_direction_y`, `normal_map_texture`, `horizon_r`, `horizon_g`, `horizon_b`, " + + "`horizon_i`, `haze_horizon`, `blue_density_r`, `blue_density_g`, `blue_density_b`, " + + "`blue_density_i`, `haze_density`, `density_multiplier`, `distance_multiplier`, `max_altitude`, " + + "`sun_moon_color_r`, `sun_moon_color_g`, `sun_moon_color_b`, `sun_moon_color_i`, `sun_moon_position`, " + + "`ambient_r`, `ambient_g`, `ambient_b`, `ambient_i`, `east_angle`, `sun_glow_focus`, `sun_glow_size`, " + + "`scene_gamma`, `star_brightness`, `cloud_color_r`, `cloud_color_g`, `cloud_color_b`, `cloud_color_i`, " + + "`cloud_x`, `cloud_y`, `cloud_density`, `cloud_coverage`, `cloud_scale`, `cloud_detail_x`, " + + "`cloud_detail_y`, `cloud_detail_density`, `cloud_scroll_x`, `cloud_scroll_x_lock`, `cloud_scroll_y`, " + + "`cloud_scroll_y_lock`, `draw_classic_clouds`) VALUES (?region_id, ?water_color_r, " + + "?water_color_g, ?water_color_b, ?water_fog_density_exponent, ?underwater_fog_modifier, ?reflection_wavelet_scale_1, " + + "?reflection_wavelet_scale_2, ?reflection_wavelet_scale_3, ?fresnel_scale, ?fresnel_offset, ?refract_scale_above, " + + "?refract_scale_below, ?blur_multiplier, ?big_wave_direction_x, ?big_wave_direction_y, ?little_wave_direction_x, " + + "?little_wave_direction_y, ?normal_map_texture, ?horizon_r, ?horizon_g, ?horizon_b, ?horizon_i, ?haze_horizon, " + + "?blue_density_r, ?blue_density_g, ?blue_density_b, ?blue_density_i, ?haze_density, ?density_multiplier, " + + "?distance_multiplier, ?max_altitude, ?sun_moon_color_r, ?sun_moon_color_g, ?sun_moon_color_b, " + + "?sun_moon_color_i, ?sun_moon_position, ?ambient_r, ?ambient_g, ?ambient_b, ?ambient_i, ?east_angle, " + + "?sun_glow_focus, ?sun_glow_size, ?scene_gamma, ?star_brightness, ?cloud_color_r, ?cloud_color_g, " + + "?cloud_color_b, ?cloud_color_i, ?cloud_x, ?cloud_y, ?cloud_density, ?cloud_coverage, ?cloud_scale, " + + "?cloud_detail_x, ?cloud_detail_y, ?cloud_detail_density, ?cloud_scroll_x, ?cloud_scroll_x_lock, " + + "?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); @@ -1084,6 +1116,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } + dbcon.Close(); } } @@ -1099,6 +1132,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?regionID", regionID.ToString()); ExecuteNonQuery(cmd); } + dbcon.Close(); } } @@ -1117,14 +1151,19 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); - IDataReader result = ExecuteReader(cmd); - if (!result.Read()) + using(IDataReader result = ExecuteReader(cmd)) { - return String.Empty; - } - else - { - return Convert.ToString(result["llsd_settings"]); + if(!result.Read()) + { + dbcon.Close(); + return String.Empty; + } + else + { + string ret = Convert.ToString(result["llsd_settings"]); + dbcon.Close(); + return ret; + } } } } @@ -1145,6 +1184,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } + dbcon.Close(); } } @@ -1160,6 +1200,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?region_id", regionUUID.ToString()); ExecuteNonQuery(cmd); } + dbcon.Close(); } } #endregion @@ -1212,7 +1253,7 @@ namespace OpenSim.Data.MySQL FillRegionSettingsCommand(cmd, rs); ExecuteNonQuery(cmd); } - + dbcon.Close(); SaveSpawnPoints(rs); } } @@ -1259,6 +1300,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } @@ -1452,6 +1494,11 @@ namespace OpenSim.Data.MySQL prim.VehicleParams = vehicle; } + PhysicsInertiaData pdata = null; + if (row["PhysInertia"].ToString() != String.Empty) + pdata = PhysicsInertiaData.FromXml2(row["PhysInertia"].ToString()); + prim.PhysicsInertia = pdata; + return prim; } @@ -1810,6 +1857,11 @@ namespace OpenSim.Data.MySQL else cmd.Parameters.AddWithValue("KeyframeMotion", new Byte[0]); + if (prim.PhysicsInertia != null) + cmd.Parameters.AddWithValue("PhysInertia", prim.PhysicsInertia.ToXml2()); + else + cmd.Parameters.AddWithValue("PhysInertia", String.Empty); + if (prim.VehicleParams != null) cmd.Parameters.AddWithValue("Vehicle", prim.VehicleParams.ToXml2()); else @@ -2113,6 +2165,7 @@ namespace OpenSim.Data.MySQL ExecuteNonQuery(cmd); } } + dbcon.Close(); } } } @@ -2142,6 +2195,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } @@ -2177,6 +2231,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } } @@ -2211,6 +2266,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.Clear(); } } + dbcon.Close(); } } } @@ -2230,6 +2286,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } @@ -2247,6 +2304,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } @@ -2270,6 +2328,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } return ret; diff --git a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs index 8af2a3ef29..c98e0173a2 100644 --- a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs +++ b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs @@ -69,6 +69,7 @@ namespace OpenSim.Data.MySQL Migration m = new Migration(dbcon, Assembly, "UserProfiles"); m.Update(); + dbcon.Close(); } } #endregion Member Functions @@ -89,7 +90,7 @@ namespace OpenSim.Data.MySQL using (MySqlConnection dbcon = new MySqlConnection(ConnectionString)) { - string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = ?Id"; + const string query = "SELECT classifieduuid, name FROM classifieds WHERE creatoruuid = ?Id"; dbcon.Open(); using (MySqlCommand cmd = new MySqlCommand(query, dbcon)) { @@ -121,58 +122,58 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } return data; } public bool UpdateClassifiedRecord(UserClassifiedAdd ad, ref string result) { - string query = string.Empty; - - - query += "INSERT INTO classifieds ("; - query += "`classifieduuid`,"; - query += "`creatoruuid`,"; - query += "`creationdate`,"; - query += "`expirationdate`,"; - query += "`category`,"; - query += "`name`,"; - query += "`description`,"; - query += "`parceluuid`,"; - query += "`parentestate`,"; - query += "`snapshotuuid`,"; - query += "`simname`,"; - query += "`posglobal`,"; - query += "`parcelname`,"; - query += "`classifiedflags`,"; - query += "`priceforlisting`) "; - query += "VALUES ("; - query += "?ClassifiedId,"; - query += "?CreatorId,"; - query += "?CreatedDate,"; - query += "?ExpirationDate,"; - query += "?Category,"; - query += "?Name,"; - query += "?Description,"; - query += "?ParcelId,"; - query += "?ParentEstate,"; - query += "?SnapshotId,"; - query += "?SimName,"; - query += "?GlobalPos,"; - query += "?ParcelName,"; - query += "?Flags,"; - query += "?ListingPrice ) "; - query += "ON DUPLICATE KEY UPDATE "; - query += "category=?Category, "; - query += "expirationdate=?ExpirationDate, "; - query += "name=?Name, "; - query += "description=?Description, "; - query += "parentestate=?ParentEstate, "; - query += "posglobal=?GlobalPos, "; - query += "parcelname=?ParcelName, "; - query += "classifiedflags=?Flags, "; - query += "priceforlisting=?ListingPrice, "; - query += "snapshotuuid=?SnapshotId"; + const string query = + "INSERT INTO classifieds (" + + "`classifieduuid`," + + "`creatoruuid`," + + "`creationdate`," + + "`expirationdate`," + + "`category`," + + "`name`," + + "`description`," + + "`parceluuid`," + + "`parentestate`," + + "`snapshotuuid`," + + "`simname`," + + "`posglobal`," + + "`parcelname`," + + "`classifiedflags`," + + "`priceforlisting`) " + + "VALUES (" + + "?ClassifiedId," + + "?CreatorId," + + "?CreatedDate," + + "?ExpirationDate," + + "?Category," + + "?Name," + + "?Description," + + "?ParcelId," + + "?ParentEstate," + + "?SnapshotId," + + "?SimName," + + "?GlobalPos," + + "?ParcelName," + + "?Flags," + + "?ListingPrice ) " + + "ON DUPLICATE KEY UPDATE " + + "category=?Category, " + + "expirationdate=?ExpirationDate, " + + "name=?Name, " + + "description=?Description, " + + "parentestate=?ParentEstate, " + + "posglobal=?GlobalPos, " + + "parcelname=?ParcelName, " + + "classifiedflags=?Flags, " + + "priceforlisting=?ListingPrice, " + + "snapshotuuid=?SnapshotId" + ; if(string.IsNullOrEmpty(ad.ParcelName)) ad.ParcelName = "Unknown"; @@ -228,6 +229,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) @@ -242,10 +244,7 @@ namespace OpenSim.Data.MySQL public bool DeleteClassifiedRecord(UUID recordId) { - string query = string.Empty; - - query += "DELETE FROM classifieds WHERE "; - query += "classifieduuid = ?recordId"; + const string query = "DELETE FROM classifieds WHERE classifieduuid = ?recordId"; try { @@ -258,6 +257,7 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?recordId", recordId.ToString()); cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) @@ -271,10 +271,8 @@ namespace OpenSim.Data.MySQL public bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result) { - string query = string.Empty; - query += "SELECT * FROM classifieds WHERE "; - query += "classifieduuid = ?AdId"; + const string query = "SELECT * FROM classifieds WHERE classifieduuid = ?AdId"; try { @@ -322,10 +320,8 @@ namespace OpenSim.Data.MySQL #region Picks Queries public OSDArray GetAvatarPicks(UUID avatarId) { - string query = string.Empty; + const string query = "SELECT `pickuuid`,`name` FROM userpicks WHERE creatoruuid = ?Id"; - query += "SELECT `pickuuid`,`name` FROM userpicks WHERE "; - query += "creatoruuid = ?Id"; OSDArray data = new OSDArray(); try @@ -352,6 +348,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } catch (Exception e) @@ -364,12 +361,8 @@ namespace OpenSim.Data.MySQL public UserProfilePick GetPickInfo(UUID avatarId, UUID pickId) { - string query = string.Empty; UserProfilePick pick = new UserProfilePick(); - - query += "SELECT * FROM userpicks WHERE "; - query += "creatoruuid = ?CreatorId AND "; - query += "pickuuid = ?PickId"; + const string query = "SELECT * FROM userpicks WHERE creatoruuid = ?CreatorId AND pickuuid = ?PickId"; try { @@ -422,33 +415,33 @@ namespace OpenSim.Data.MySQL public bool UpdatePicksRecord(UserProfilePick pick) { - string query = string.Empty; - - query += "INSERT INTO userpicks VALUES ("; - query += "?PickId,"; - query += "?CreatorId,"; - query += "?TopPick,"; - query += "?ParcelId,"; - query += "?Name,"; - query += "?Desc,"; - query += "?SnapshotId,"; - query += "?User,"; - query += "?Original,"; - query += "?SimName,"; - query += "?GlobalPos,"; - query += "?SortOrder,"; - query += "?Enabled,"; - query += "?Gatekeeper)"; - query += "ON DUPLICATE KEY UPDATE "; - query += "parceluuid=?ParcelId,"; - query += "name=?Name,"; - query += "description=?Desc,"; - query += "user=?User,"; - query += "simname=?SimName,"; - query += "snapshotuuid=?SnapshotId,"; - query += "pickuuid=?PickId,"; - query += "posglobal=?GlobalPos,"; - query += "gatekeeper=?Gatekeeper"; + const string query = + "INSERT INTO userpicks VALUES (" + + "?PickId," + + "?CreatorId," + + "?TopPick," + + "?ParcelId," + + "?Name," + + "?Desc," + + "?SnapshotId," + + "?User," + + "?Original," + + "?SimName," + + "?GlobalPos," + + "?SortOrder," + + "?Enabled," + + "?Gatekeeper)" + + "ON DUPLICATE KEY UPDATE " + + "parceluuid=?ParcelId," + + "name=?Name," + + "description=?Desc," + + "user=?User," + + "simname=?SimName," + + "snapshotuuid=?SnapshotId," + + "pickuuid=?PickId," + + "posglobal=?GlobalPos," + + "gatekeeper=?Gatekeeper" + ; try { @@ -474,6 +467,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) @@ -487,10 +481,7 @@ namespace OpenSim.Data.MySQL public bool DeletePicksRecord(UUID pickId) { - string query = string.Empty; - - query += "DELETE FROM userpicks WHERE "; - query += "pickuuid = ?PickId"; + string query = "DELETE FROM userpicks WHERE pickuuid = ?PickId"; try { @@ -504,6 +495,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) @@ -519,11 +511,7 @@ namespace OpenSim.Data.MySQL #region Avatar Notes Queries public bool GetAvatarNotes(ref UserProfileNotes notes) { // WIP - string query = string.Empty; - - query += "SELECT `notes` FROM usernotes WHERE "; - query += "useruuid = ?Id AND "; - query += "targetuuid = ?TargetId"; + const string query = "SELECT `notes` FROM usernotes WHERE useruuid = ?Id AND targetuuid = ?TargetId"; try { @@ -548,6 +536,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } catch (Exception e) @@ -560,26 +549,25 @@ namespace OpenSim.Data.MySQL public bool UpdateAvatarNotes(ref UserProfileNotes note, ref string result) { - string query = string.Empty; + string query; bool remove; if(string.IsNullOrEmpty(note.Notes)) { remove = true; - query += "DELETE FROM usernotes WHERE "; - query += "useruuid=?UserId AND "; - query += "targetuuid=?TargetId"; + query = "DELETE FROM usernotes WHERE useruuid=?UserId AND targetuuid=?TargetId"; } else { remove = false; - query += "INSERT INTO usernotes VALUES ( "; - query += "?UserId,"; - query += "?TargetId,"; - query += "?Notes )"; - query += "ON DUPLICATE KEY "; - query += "UPDATE "; - query += "notes=?Notes"; + query = "INSERT INTO usernotes VALUES (" + + "?UserId," + + "?TargetId," + + "?Notes )" + + "ON DUPLICATE KEY " + + "UPDATE " + + "notes=?Notes" + ; } try @@ -596,6 +584,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) @@ -612,10 +601,7 @@ namespace OpenSim.Data.MySQL #region Avatar Properties public bool GetAvatarProperties(ref UserProfileProperties props, ref string result) { - string query = string.Empty; - - query += "SELECT * FROM userprofile WHERE "; - query += "useruuid = ?Id"; + string query = "SELECT * FROM userprofile WHERE useruuid = ?Id"; try { @@ -664,35 +650,36 @@ namespace OpenSim.Data.MySQL props.PublishProfile = false; props.PublishMature = false; - query = "INSERT INTO userprofile ("; - query += "useruuid, "; - query += "profilePartner, "; - query += "profileAllowPublish, "; - query += "profileMaturePublish, "; - query += "profileURL, "; - query += "profileWantToMask, "; - query += "profileWantToText, "; - query += "profileSkillsMask, "; - query += "profileSkillsText, "; - query += "profileLanguages, "; - query += "profileImage, "; - query += "profileAboutText, "; - query += "profileFirstImage, "; - query += "profileFirstText) VALUES ("; - query += "?userId, "; - query += "?profilePartner, "; - query += "?profileAllowPublish, "; - query += "?profileMaturePublish, "; - query += "?profileURL, "; - query += "?profileWantToMask, "; - query += "?profileWantToText, "; - query += "?profileSkillsMask, "; - query += "?profileSkillsText, "; - query += "?profileLanguages, "; - query += "?profileImage, "; - query += "?profileAboutText, "; - query += "?profileFirstImage, "; - query += "?profileFirstText)"; + query = "INSERT INTO userprofile (" + + "useruuid, " + + "profilePartner, " + + "profileAllowPublish, " + + "profileMaturePublish, " + + "profileURL, " + + "profileWantToMask, " + + "profileWantToText, " + + "profileSkillsMask, " + + "profileSkillsText, " + + "profileLanguages, " + + "profileImage, " + + "profileAboutText, " + + "profileFirstImage, " + + "profileFirstText) VALUES (" + + "?userId, " + + "?profilePartner, " + + "?profileAllowPublish, " + + "?profileMaturePublish, " + + "?profileURL, " + + "?profileWantToMask, " + + "?profileWantToText, " + + "?profileSkillsMask, " + + "?profileSkillsText, " + + "?profileLanguages, " + + "?profileImage, " + + "?profileAboutText, " + + "?profileFirstImage, " + + "?profileFirstText)" + ; dbcon.Close(); dbcon.Open(); @@ -719,6 +706,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } catch (Exception e) @@ -733,15 +721,10 @@ namespace OpenSim.Data.MySQL public bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result) { - string query = string.Empty; - - query += "UPDATE userprofile SET "; - query += "profileURL=?profileURL, "; - query += "profileImage=?image, "; - query += "profileAboutText=?abouttext,"; - query += "profileFirstImage=?firstlifeimage,"; - query += "profileFirstText=?firstlifetext "; - query += "WHERE useruuid=?uuid"; + const string query = "UPDATE userprofile SET profileURL=?profileURL," + + "profileImage=?image, profileAboutText=?abouttext," + + "profileFirstImage=?firstlifeimage, profileFirstText=?firstlifetext " + + "WHERE useruuid=?uuid"; try { @@ -759,6 +742,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) @@ -775,15 +759,13 @@ namespace OpenSim.Data.MySQL #region Avatar Interests public bool UpdateAvatarInterests(UserProfileProperties up, ref string result) { - string query = string.Empty; - - query += "UPDATE userprofile SET "; - query += "profileWantToMask=?WantMask, "; - query += "profileWantToText=?WantText,"; - query += "profileSkillsMask=?SkillsMask,"; - query += "profileSkillsText=?SkillsText, "; - query += "profileLanguages=?Languages "; - query += "WHERE useruuid=?uuid"; + const string query = "UPDATE userprofile SET " + + "profileWantToMask=?WantMask, " + + "profileWantToText=?WantText," + + "profileSkillsMask=?SkillsMask," + + "profileSkillsText=?SkillsText, " + + "profileLanguages=?Languages " + + "WHERE useruuid=?uuid"; try { @@ -817,18 +799,17 @@ namespace OpenSim.Data.MySQL public OSDArray GetUserImageAssets(UUID avatarId) { OSDArray data = new OSDArray(); - string query = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = ?Id"; + const string queryA = "SELECT `snapshotuuid` FROM {0} WHERE `creatoruuid` = ?Id"; // Get classified image assets - try { using (MySqlConnection dbcon = new MySqlConnection(ConnectionString)) { dbcon.Open(); - using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`classifieds`"), dbcon)) + using (MySqlCommand cmd = new MySqlCommand(string.Format (queryA,"`classifieds`"), dbcon)) { cmd.Parameters.AddWithValue("?Id", avatarId.ToString()); @@ -847,7 +828,7 @@ namespace OpenSim.Data.MySQL dbcon.Close(); dbcon.Open(); - using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon)) + using (MySqlCommand cmd = new MySqlCommand(string.Format (queryA,"`userpicks`"), dbcon)) { cmd.Parameters.AddWithValue("?Id", avatarId.ToString()); @@ -866,9 +847,9 @@ namespace OpenSim.Data.MySQL dbcon.Close(); dbcon.Open(); - query = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = ?Id"; + const string queryB = "SELECT `profileImage`, `profileFirstImage` FROM `userprofile` WHERE `useruuid` = ?Id"; - using (MySqlCommand cmd = new MySqlCommand(string.Format (query,"`userpicks`"), dbcon)) + using (MySqlCommand cmd = new MySqlCommand(string.Format (queryB,"`userpicks`"), dbcon)) { cmd.Parameters.AddWithValue("?Id", avatarId.ToString()); @@ -884,6 +865,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } catch (Exception e) @@ -897,11 +879,7 @@ namespace OpenSim.Data.MySQL #region User Preferences public bool GetUserPreferences(ref UserPreferences pref, ref string result) { - string query = string.Empty; - - query += "SELECT imviaemail,visible,email FROM "; - query += "usersettings WHERE "; - query += "useruuid = ?Id"; + const string query = "SELECT imviaemail,visible,email FROM usersettings WHERE useruuid = ?Id"; try { @@ -925,10 +903,9 @@ namespace OpenSim.Data.MySQL dbcon.Close(); dbcon.Open(); - query = "INSERT INTO usersettings VALUES "; - query += "(?uuid,'false','false', ?Email)"; + const string queryB = "INSERT INTO usersettings VALUES (?uuid,'false','false', ?Email)"; - using (MySqlCommand put = new MySqlCommand(query, dbcon)) + using (MySqlCommand put = new MySqlCommand(queryB, dbcon)) { put.Parameters.AddWithValue("?Email", pref.EMail); @@ -939,6 +916,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } catch (Exception e) @@ -953,13 +931,9 @@ namespace OpenSim.Data.MySQL public bool UpdateUserPreferences(ref UserPreferences pref, ref string result) { - string query = string.Empty; - - query += "UPDATE usersettings SET "; - query += "imviaemail=?ImViaEmail, "; - query += "visible=?Visible, "; - query += "email=?EMail "; - query += "WHERE useruuid=?uuid"; + const string query = "UPDATE usersettings SET imviaemail=?ImViaEmail," + + "visible=?Visible, email=?EMail " + + "WHERE useruuid=?uuid"; try { @@ -975,6 +949,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) @@ -991,11 +966,7 @@ namespace OpenSim.Data.MySQL #region Integration public bool GetUserAppData(ref UserAppData props, ref string result) { - string query = string.Empty; - - query += "SELECT * FROM `userdata` WHERE "; - query += "UserId = ?Id AND "; - query += "TagId = ?TagId"; + const string query = "SELECT * FROM `userdata` WHERE UserId = ?Id AND TagId = ?TagId"; try { @@ -1017,13 +988,8 @@ namespace OpenSim.Data.MySQL } else { - query += "INSERT INTO userdata VALUES ( "; - query += "?UserId,"; - query += "?TagId,"; - query += "?DataKey,"; - query += "?DataVal) "; - - using (MySqlCommand put = new MySqlCommand(query, dbcon)) + const string queryB = "INSERT INTO userdata VALUES (?UserId, ?TagId, ?DataKey, ?DataVal)"; + using (MySqlCommand put = new MySqlCommand(queryB, dbcon)) { put.Parameters.AddWithValue("?UserId", props.UserId.ToString()); put.Parameters.AddWithValue("?TagId", props.TagId.ToString()); @@ -1035,6 +1001,7 @@ namespace OpenSim.Data.MySQL } } } + dbcon.Close(); } } catch (Exception e) @@ -1049,14 +1016,7 @@ namespace OpenSim.Data.MySQL public bool SetUserAppData(UserAppData props, ref string result) { - string query = string.Empty; - - query += "UPDATE userdata SET "; - query += "TagId = ?TagId, "; - query += "DataKey = ?DataKey, "; - query += "DataVal = ?DataVal WHERE "; - query += "UserId = ?UserId AND "; - query += "TagId = ?TagId"; + const string query = "UPDATE userdata SET TagId = ?TagId, DataKey = ?DataKey, DataVal = ?DataVal WHERE UserId = ?UserId AND TagId = ?TagId"; try { @@ -1072,6 +1032,7 @@ namespace OpenSim.Data.MySQL cmd.ExecuteNonQuery(); } + dbcon.Close(); } } catch (Exception e) diff --git a/OpenSim/Data/MySQL/MySQLXAssetData.cs b/OpenSim/Data/MySQL/MySQLXAssetData.cs index 2c6acdef32..9f9c9cf4fa 100644 --- a/OpenSim/Data/MySQL/MySQLXAssetData.cs +++ b/OpenSim/Data/MySQL/MySQLXAssetData.cs @@ -97,6 +97,7 @@ namespace OpenSim.Data.MySQL dbcon.Open(); Migration m = new Migration(dbcon, Assembly, "XAssetStore"); m.Update(); + dbcon.Close(); } } @@ -130,6 +131,7 @@ namespace OpenSim.Data.MySQL // m_log.DebugFormat("[MYSQL XASSET DATA]: Looking for asset {0}", assetID); AssetBase asset = null; + int accessTime = 0; using (MySqlConnection dbcon = new MySqlConnection(m_connectionString)) { @@ -140,7 +142,6 @@ namespace OpenSim.Data.MySQL dbcon)) { cmd.Parameters.AddWithValue("?ID", assetID.ToString()); - try { using (MySqlDataReader dbReader = cmd.ExecuteReader(CommandBehavior.SingleRow)) @@ -159,23 +160,7 @@ namespace OpenSim.Data.MySQL asset.Temporary = Convert.ToBoolean(dbReader["Temporary"]); asset.Flags = (AssetFlags)Convert.ToInt32(dbReader["AssetFlags"]); - - if (m_enableCompression) - { - using (GZipStream decompressionStream = new GZipStream(new MemoryStream(asset.Data), CompressionMode.Decompress)) - { - MemoryStream outputStream = new MemoryStream(); - WebUtil.CopyStream(decompressionStream, outputStream, int.MaxValue); -// int compressedLength = asset.Data.Length; - asset.Data = outputStream.ToArray(); - -// m_log.DebugFormat( -// "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}", -// asset.ID, asset.Name, asset.Data.Length, compressedLength); - } - } - - UpdateAccessTime(asset.Metadata, (int)dbReader["AccessTime"]); + accessTime = (int)dbReader["AccessTime"]; } } } @@ -184,9 +169,38 @@ namespace OpenSim.Data.MySQL m_log.Error(string.Format("[MYSQL XASSET DATA]: Failure fetching asset {0}", assetID), e); } } + dbcon.Close(); } - return asset; + if(asset == null) + return asset; + + if(accessTime > 0) + { + try + { + UpdateAccessTime(asset.Metadata, accessTime); + } + catch { } + } + + if (m_enableCompression && asset.Data != null) + { + using(MemoryStream ms = new MemoryStream(asset.Data)) + using(GZipStream decompressionStream = new GZipStream(ms, CompressionMode.Decompress)) + { + using(MemoryStream outputStream = new MemoryStream()) + { + decompressionStream.CopyTo(outputStream, int.MaxValue); +// int compressedLength = asset.Data.Length; + asset.Data = outputStream.ToArray(); + } +// m_log.DebugFormat( +// "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}", +// asset.ID, asset.Name, asset.Data.Length, compressedLength); + } + } + return asset; } /// @@ -303,6 +317,7 @@ namespace OpenSim.Data.MySQL transaction.Commit(); } + dbcon.Close(); } } @@ -344,6 +359,7 @@ namespace OpenSim.Data.MySQL "[XASSET MYSQL DB]: Failure updating access_time for asset {0} with name {1}", assetMetadata.ID, assetMetadata.Name); } + dbcon.Close(); } } @@ -474,6 +490,7 @@ namespace OpenSim.Data.MySQL m_log.Error("[XASSETS DB]: MySql failure fetching asset set" + Environment.NewLine + e.ToString()); } } + dbcon.Close(); } return retList; @@ -492,9 +509,9 @@ namespace OpenSim.Data.MySQL cmd.Parameters.AddWithValue("?ID", id); cmd.ExecuteNonQuery(); } - // TODO: How do we deal with data from deleted assets? Probably not easily reapable unless we // keep a reference count (?) + dbcon.Close(); } return true; diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index 4e41fec9cd..501999425d 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -328,7 +328,6 @@ namespace OpenSim.Data.MySQL { return false; } - cmd.Dispose(); } dbcon.Close(); diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index c63cc95d22..0577392184 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -461,3 +461,9 @@ BEGIN; ALTER TABLE `prims` ADD COLUMN `RezzerID` char(36) DEFAULT NULL; COMMIT; + +:VERSION 57 #----- Add physics inertia data + +BEGIN; +ALTER TABLE `prims` ADD COLUMN `PhysInertia` TEXT default NULL; +COMMIT; diff --git a/OpenSim/Data/MySQL/Resources/os_groups_Store.migrations b/OpenSim/Data/MySQL/Resources/os_groups_Store.migrations index 1a499000fb..6ec89144b5 100644 --- a/OpenSim/Data/MySQL/Resources/os_groups_Store.migrations +++ b/OpenSim/Data/MySQL/Resources/os_groups_Store.migrations @@ -18,7 +18,7 @@ CREATE TABLE `os_groups_groups` ( PRIMARY KEY (`GroupID`), UNIQUE KEY `Name` (`Name`), FULLTEXT KEY `Name_2` (`Name`) -) ENGINE=InnoDB; +) ENGINE=MyISAM; CREATE TABLE `os_groups_membership` ( diff --git a/OpenSim/Data/PGSQL/PGSQLGroupsData.cs b/OpenSim/Data/PGSQL/PGSQLGroupsData.cs index 6ef576bccc..f398256863 100755 --- a/OpenSim/Data/PGSQL/PGSQLGroupsData.cs +++ b/OpenSim/Data/PGSQL/PGSQLGroupsData.cs @@ -435,7 +435,7 @@ namespace OpenSim.Data.PGSQL using (NpgsqlCommand cmd = new NpgsqlCommand()) { - cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < CURRENT_DATE - INTERVAL '2 week'", m_Realm); + cmd.CommandText = String.Format("delete from {0} where \"TMStamp\"::abstime::timestamp < now() - INTERVAL '2 week'", m_Realm); ExecuteNonQuery(cmd); } @@ -461,7 +461,7 @@ namespace OpenSim.Data.PGSQL using (NpgsqlCommand cmd = new NpgsqlCommand()) { - cmd.CommandText = String.Format("delete from {0} where \"TMStamp\" < CURRENT_DATE - INTERVAL '2 week'", m_Realm); + cmd.CommandText = String.Format("delete from {0} where \"TMStamp\"::abstime::timestamp < now() - INTERVAL '2 week'", m_Realm); ExecuteNonQuery(cmd); } diff --git a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs index 33d12bd71e..f4af40ba88 100755 --- a/OpenSim/Data/PGSQL/PGSQLSimulationData.cs +++ b/OpenSim/Data/PGSQL/PGSQLSimulationData.cs @@ -350,10 +350,11 @@ namespace OpenSim.Data.PGSQL ""CameraEyeOffsetY"" = :CameraEyeOffsetY, ""CameraEyeOffsetZ"" = :CameraEyeOffsetZ, ""CameraAtOffsetX"" = :CameraAtOffsetX, ""CameraAtOffsetY"" = :CameraAtOffsetY, ""CameraAtOffsetZ"" = :CameraAtOffsetZ, ""ForceMouselook"" = :ForceMouselook, ""ScriptAccessPin"" = :ScriptAccessPin, ""AllowedDrop"" = :AllowedDrop, ""DieAtEdge"" = :DieAtEdge, ""SalePrice"" = :SalePrice, - ""SaleType"" = :SaleType, ""ColorR"" = :ColorR, ""ColorG"" = :ColorG, ""ColorB"" = :ColorB, ""ColorA"" = :ColorA, ""ParticleSystem"" = :ParticleSystem, + ""PhysicsShapeType"" = :PhysicsShapeType, ""Density"" = :Density, ""GravityModifier"" = :GravityModifier, ""Friction"" = :Friction, ""Restitution"" = :Restitution, + ""PassCollisions"" = :PassCollisions, ""RotationAxisLocks"" = :RotationAxisLocks, ""RezzerID"" = :RezzerID, ""ClickAction"" = :ClickAction, ""Material"" = :Material, ""CollisionSound"" = :CollisionSound, ""CollisionSoundVolume"" = :CollisionSoundVolume, ""PassTouches"" = :PassTouches, ""LinkNumber"" = :LinkNumber, ""MediaURL"" = :MediaURL, ""DynAttrs"" = :DynAttrs, - ""PhysicsShapeType"" = :PhysicsShapeType, ""Density"" = :Density, ""GravityModifier"" = :GravityModifier, ""Friction"" = :Friction, ""Restitution"" = :Restitution + ""PhysInertia"" = :PhysInertia WHERE ""UUID"" = :UUID ; INSERT INTO @@ -367,7 +368,7 @@ namespace OpenSim.Data.PGSQL ""OmegaY"", ""OmegaZ"", ""CameraEyeOffsetX"", ""CameraEyeOffsetY"", ""CameraEyeOffsetZ"", ""CameraAtOffsetX"", ""CameraAtOffsetY"", ""CameraAtOffsetZ"", ""ForceMouselook"", ""ScriptAccessPin"", ""AllowedDrop"", ""DieAtEdge"", ""SalePrice"", ""SaleType"", ""ColorR"", ""ColorG"", ""ColorB"", ""ColorA"", ""ParticleSystem"", ""ClickAction"", ""Material"", ""CollisionSound"", ""CollisionSoundVolume"", ""PassTouches"", ""LinkNumber"", ""MediaURL"", ""DynAttrs"", - ""PhysicsShapeType"", ""Density"", ""GravityModifier"", ""Friction"", ""Restitution"" + ""PhysicsShapeType"", ""Density"", ""GravityModifier"", ""Friction"", ""Restitution"", ""PassCollisions"", ""RotationAxisLocks"", ""RezzerID"" , ""PhysInertia"" ) Select :UUID, :CreationDate, :Name, :Text, :Description, :SitName, :TouchName, :ObjectFlags, :OwnerMask, :NextOwnerMask, :GroupMask, :EveryoneMask, :BaseMask, :PositionX, :PositionY, :PositionZ, :GroupPositionX, :GroupPositionY, :GroupPositionZ, :VelocityX, @@ -378,7 +379,7 @@ namespace OpenSim.Data.PGSQL :OmegaY, :OmegaZ, :CameraEyeOffsetX, :CameraEyeOffsetY, :CameraEyeOffsetZ, :CameraAtOffsetX, :CameraAtOffsetY, :CameraAtOffsetZ, :ForceMouselook, :ScriptAccessPin, :AllowedDrop, :DieAtEdge, :SalePrice, :SaleType, :ColorR, :ColorG, :ColorB, :ColorA, :ParticleSystem, :ClickAction, :Material, :CollisionSound, :CollisionSoundVolume, :PassTouches, :LinkNumber, :MediaURL, :DynAttrs, - :PhysicsShapeType, :Density, :GravityModifier, :Friction, :Restitution + :PhysicsShapeType, :Density, :GravityModifier, :Friction, :Restitution, :PassCollisions, :RotationAxisLocks, :RezzerID, :PhysInertia where not EXISTS (SELECT ""UUID"" FROM prims WHERE ""UUID"" = :UUID); "; @@ -1678,6 +1679,12 @@ namespace OpenSim.Data.PGSQL prim.OwnerID = new UUID((Guid)primRow["OwnerID"]); prim.GroupID = new UUID((Guid)primRow["GroupID"]); prim.LastOwnerID = new UUID((Guid)primRow["LastOwnerID"]); + + if (primRow["RezzerID"] != DBNull.Value) + prim.RezzerID = new UUID((Guid)primRow["RezzerID"]); + else + prim.RezzerID = UUID.Zero; + prim.OwnerMask = Convert.ToUInt32(primRow["OwnerMask"]); prim.NextOwnerMask = Convert.ToUInt32(primRow["NextOwnerMask"]); prim.GroupMask = Convert.ToUInt32(primRow["GroupMask"]); @@ -1782,6 +1789,7 @@ namespace OpenSim.Data.PGSQL prim.CollisionSoundVolume = Convert.ToSingle(primRow["CollisionSoundVolume"]); prim.PassTouches = (bool)primRow["PassTouches"]; + prim.PassCollisions = (bool)primRow["PassCollisions"]; if (!(primRow["MediaURL"] is System.DBNull)) prim.MediaUrl = (string)primRow["MediaURL"]; @@ -1796,6 +1804,13 @@ namespace OpenSim.Data.PGSQL prim.GravityModifier = Convert.ToSingle(primRow["GravityModifier"]); prim.Friction = Convert.ToSingle(primRow["Friction"]); prim.Restitution = Convert.ToSingle(primRow["Restitution"]); + prim.RotationAxisLocks = Convert.ToByte(primRow["RotationAxisLocks"]); + + + PhysicsInertiaData pdata = null; + if (!(primRow["PhysInertia"] is System.DBNull)) + pdata = PhysicsInertiaData.FromXml2(primRow["PhysInertia"].ToString()); + prim.PhysicsInertia = pdata; return prim; } @@ -2097,6 +2112,7 @@ namespace OpenSim.Data.PGSQL parameters.Add(_Database.CreateParameter("OwnerID", prim.OwnerID)); parameters.Add(_Database.CreateParameter("GroupID", prim.GroupID)); parameters.Add(_Database.CreateParameter("LastOwnerID", prim.LastOwnerID)); + parameters.Add(_Database.CreateParameter("RezzerID", prim.RezzerID)); parameters.Add(_Database.CreateParameter("OwnerMask", prim.OwnerMask)); parameters.Add(_Database.CreateParameter("NextOwnerMask", prim.NextOwnerMask)); parameters.Add(_Database.CreateParameter("GroupMask", prim.GroupMask)); @@ -2196,10 +2212,28 @@ namespace OpenSim.Data.PGSQL parameters.Add(_Database.CreateParameter("CollisionSound", prim.CollisionSound)); parameters.Add(_Database.CreateParameter("CollisionSoundVolume", prim.CollisionSoundVolume)); - parameters.Add(_Database.CreateParameter("PassTouches", prim.PassTouches)); + parameters.Add(_Database.CreateParameter("PassTouches", (bool)prim.PassTouches)); + parameters.Add(_Database.CreateParameter("PassCollisions", (bool)prim.PassCollisions)); + + + if (prim.PassTouches) + parameters.Add(_Database.CreateParameter("PassTouches", true)); + else + parameters.Add(_Database.CreateParameter("PassTouches", false)); + + if (prim.PassCollisions) + parameters.Add(_Database.CreateParameter("PassCollisions", true)); + else + parameters.Add(_Database.CreateParameter("PassCollisions", false)); parameters.Add(_Database.CreateParameter("LinkNumber", prim.LinkNum)); parameters.Add(_Database.CreateParameter("MediaURL", prim.MediaUrl)); + + if (prim.PhysicsInertia != null) + parameters.Add(_Database.CreateParameter("PhysInertia", prim.PhysicsInertia.ToXml2())); + else + parameters.Add(_Database.CreateParameter("PhysInertia", String.Empty)); + if (prim.DynAttrs.CountNamespaces > 0) parameters.Add(_Database.CreateParameter("DynAttrs", prim.DynAttrs.ToXml())); @@ -2211,12 +2245,13 @@ namespace OpenSim.Data.PGSQL parameters.Add(_Database.CreateParameter("GravityModifier", (double)prim.GravityModifier)); parameters.Add(_Database.CreateParameter("Friction", (double)prim.Friction)); parameters.Add(_Database.CreateParameter("Restitution", (double)prim.Restitution)); + parameters.Add(_Database.CreateParameter("RotationAxisLocks", prim.RotationAxisLocks)); return parameters.ToArray(); } /// - /// Creates the primshape parameters for stroing in DB. + /// Creates the primshape parameters for storing in DB. /// /// Basic data of SceneObjectpart prim. /// The scene group ID. diff --git a/OpenSim/Data/PGSQL/PGSQLXAssetData.cs b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs index 6e884898f5..1798d20508 100644 --- a/OpenSim/Data/PGSQL/PGSQLXAssetData.cs +++ b/OpenSim/Data/PGSQL/PGSQLXAssetData.cs @@ -173,16 +173,18 @@ namespace OpenSim.Data.PGSQL if (m_enableCompression) { - using (GZipStream decompressionStream = new GZipStream(new MemoryStream(asset.Data), CompressionMode.Decompress)) + using(MemoryStream ms = new MemoryStream(asset.Data)) + using(GZipStream decompressionStream = new GZipStream(ms, CompressionMode.Decompress)) { - MemoryStream outputStream = new MemoryStream(); - WebUtil.CopyStream(decompressionStream, outputStream, int.MaxValue); - // int compressedLength = asset.Data.Length; - asset.Data = outputStream.ToArray(); - - // m_log.DebugFormat( - // "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}", - // asset.ID, asset.Name, asset.Data.Length, compressedLength); + using(MemoryStream outputStream = new MemoryStream()) + { + decompressionStream.CopyTo(outputStream,int.MaxValue); + // int compressedLength = asset.Data.Length; + asset.Data = outputStream.ToArray(); + } + // m_log.DebugFormat( + // "[XASSET DB]: Decompressed {0} {1} to {2} bytes from {3}", + // asset.ID, asset.Name, asset.Data.Length, compressedLength); } } diff --git a/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs b/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs index 55a1996f51..4c10ac99b7 100644 --- a/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs +++ b/OpenSim/Data/PGSQL/PGSQLXInventoryData.cs @@ -206,7 +206,7 @@ namespace OpenSim.Data.PGSQL cmd.CommandText = String.Format(@"select bit_or(""inventoryCurrentPermissions"") as ""inventoryCurrentPermissions"" from inventoryitems where ""avatarID""::uuid = :PrincipalID - and ""assetID"" = :AssetID + and ""assetID""::uuid = :AssetID group by ""assetID"" "); cmd.Parameters.Add(m_database.CreateParameter("PrincipalID", principalID)); diff --git a/OpenSim/Data/PGSQL/Resources/AgentPrefs.migrations b/OpenSim/Data/PGSQL/Resources/AgentPrefs.migrations new file mode 100644 index 0000000000..ca3cca21f6 --- /dev/null +++ b/OpenSim/Data/PGSQL/Resources/AgentPrefs.migrations @@ -0,0 +1,19 @@ +:VERSION 1 + +BEGIN TRANSACTION; + +CREATE TABLE IF NOT EXISTS "public"."agentprefs" ( + "PrincipalID" uuid NOT NULL, + "AccessPrefs" char(2) NOT NULL DEFAULT 'M'::bpchar COLLATE "default", + "HoverHeight" float8 NOT NULL DEFAULT 0, + "Language" char(5) NOT NULL DEFAULT 'en-us'::bpchar COLLATE "default", + "LanguageIsPublic" bool NOT NULL DEFAULT true, + "PermEveryone" int4 NOT NULL DEFAULT 0, + "PermGroup" int4 NOT NULL DEFAULT 0, + "PermNextOwner" int4 NOT NULL DEFAULT 532480 +) +WITH (OIDS=FALSE); + +ALTER TABLE "public"."agentprefs" ADD PRIMARY KEY ("PrincipalID") NOT DEFERRABLE INITIALLY IMMEDIATE; + +COMMIT; diff --git a/OpenSim/Data/PGSQL/Resources/EstateStore.migrations b/OpenSim/Data/PGSQL/Resources/EstateStore.migrations index 59270f8b01..63b70bd555 100644 --- a/OpenSim/Data/PGSQL/Resources/EstateStore.migrations +++ b/OpenSim/Data/PGSQL/Resources/EstateStore.migrations @@ -1,307 +1,112 @@ -:VERSION 1 +:VERSION 12 BEGIN TRANSACTION; -CREATE TABLE estate_managers( - "EstateID" int NOT NULL Primary Key, - uuid varchar(36) NOT NULL - ); - -CREATE TABLE estate_groups( - "EstateID" int NOT NULL, - uuid varchar(36) NOT NULL - ); +-- ---------------------------- +-- Table structure for estate_groups +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "public"."estate_groups" ( + "EstateID" int4 NOT NULL, + "uuid" uuid NOT NULL +) +WITH (OIDS=FALSE); +-- Indexes structure for table estate_groups +-- ---------------------------- +CREATE INDEX IF NOT EXISTS "ix_estate_groups" ON "public"."estate_groups" USING btree("EstateID" "pg_catalog"."int4_ops" ASC NULLS LAST); -CREATE TABLE estate_users( - "EstateID" int NOT NULL, - uuid varchar(36) NOT NULL - ); +-- ---------------------------- +-- Table structure for estate_managers +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "public"."estate_managers" ( + "EstateID" int4 NOT NULL, + "uuid" uuid NOT NULL +) +WITH (OIDS=FALSE); +-- Indexes structure for table estate_managers +-- ---------------------------- +CREATE INDEX IF NOT EXISTS "ix_estate_managers" ON "public"."estate_managers" USING btree("EstateID" "pg_catalog"."int4_ops" ASC NULLS LAST); -CREATE TABLE estateban( - "EstateID" int NOT NULL, - "bannedUUID" varchar(36) NOT NULL, - "bannedIp" varchar(16) NOT NULL, - "bannedIpHostMask" varchar(16) NOT NULL, - "bannedNameMask" varchar(64) NULL DEFAULT NULL - ); +-- ---------------------------- +-- Table structure for estate_map +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "public"."estate_map" ( + "RegionID" uuid NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'::uuid, + "EstateID" int4 NOT NULL +) +WITH (OIDS=FALSE); -Create Sequence estate_settings_id increment by 100 start with 100; +-- Primary key structure for table estate_map +-- ---------------------------- +ALTER TABLE "public"."estate_map" ADD PRIMARY KEY ("RegionID") NOT DEFERRABLE INITIALLY IMMEDIATE; -CREATE TABLE estate_settings( - "EstateID" integer DEFAULT nextval('estate_settings_id') NOT NULL, - "EstateName" varchar(64) NULL DEFAULT (NULL), - "AbuseEmailToEstateOwner" boolean NOT NULL, - "DenyAnonymous" boolean NOT NULL, - "ResetHomeOnTeleport" boolean NOT NULL, - "FixedSun" boolean NOT NULL, - "DenyTransacted" boolean NOT NULL, - "BlockDwell" boolean NOT NULL, - "DenyIdentified" boolean NOT NULL, - "AllowVoice" boolean NOT NULL, - "UseGlobalTime" boolean NOT NULL, - "PricePerMeter" int NOT NULL, - "TaxFree" boolean NOT NULL, - "AllowDirectTeleport" boolean NOT NULL, - "RedirectGridX" int NOT NULL, - "RedirectGridY" int NOT NULL, - "ParentEstateID" int NOT NULL, - "SunPosition" double precision NOT NULL, - "EstateSkipScripts" boolean NOT NULL, - "BillableFactor" double precision NOT NULL, - "PublicAccess" boolean NOT NULL, - "AbuseEmail" varchar(255) NOT NULL, - "EstateOwner" varchar(36) NOT NULL, - "DenyMinors" boolean NOT NULL - ); - - -CREATE TABLE estate_map( - "RegionID" varchar(36) NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'), - "EstateID" int NOT NULL - ); - -COMMIT; - -:VERSION 2 - -BEGIN TRANSACTION; - -CREATE INDEX IX_estate_managers ON estate_managers - ( - "EstateID" - ); - - -CREATE INDEX IX_estate_groups ON estate_groups - ( - "EstateID" - ); - - -CREATE INDEX IX_estate_users ON estate_users - ( - "EstateID" - ); - -COMMIT; - -:VERSION 3 - -BEGIN TRANSACTION; - -CREATE TABLE Tmp_estateban - ( - "EstateID" int NOT NULL, - "bannedUUID" varchar(36) NOT NULL, - "bannedIp" varchar(16) NULL, - "bannedIpHostMask" varchar(16) NULL, - "bannedNameMask" varchar(64) NULL - ); - - INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask") - SELECT "EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban; - -DROP TABLE estateban; - -Alter table Tmp_estateban - rename to estateban; - -CREATE INDEX IX_estateban ON estateban - ( - "EstateID" - ); - -COMMIT; - - -:VERSION 4 - -BEGIN TRANSACTION; - -CREATE TABLE Tmp_estate_managers - ( - "EstateID" int NOT NULL, - uuid uuid NOT NULL - ); - -INSERT INTO Tmp_estate_managers ("EstateID", uuid) - SELECT "EstateID", cast(uuid as uuid) FROM estate_managers; - -DROP TABLE estate_managers; - -Alter table Tmp_estate_managers - rename to estate_managers; - -CREATE INDEX IX_estate_managers ON estate_managers - ( - "EstateID" - ); - -COMMIT; - - -:VERSION 5 - -BEGIN TRANSACTION; - -CREATE TABLE Tmp_estate_groups - ( - "EstateID" int NOT NULL, - uuid uuid NOT NULL - ) ; - - INSERT INTO Tmp_estate_groups ("EstateID", uuid) - SELECT "EstateID", cast(uuid as uuid) FROM estate_groups; - -DROP TABLE estate_groups; - -Alter table Tmp_estate_groups - rename to estate_groups; - -CREATE INDEX IX_estate_groups ON estate_groups - ( - "EstateID" - ); - -COMMIT; - - -:VERSION 6 - -BEGIN TRANSACTION; - -CREATE TABLE Tmp_estate_users - ( - "EstateID" int NOT NULL, - uuid uuid NOT NULL - ); - -INSERT INTO Tmp_estate_users ("EstateID", uuid) - SELECT "EstateID", cast(uuid as uuid) FROM estate_users ; - -DROP TABLE estate_users; - -Alter table Tmp_estate_users - rename to estate_users; - -CREATE INDEX IX_estate_users ON estate_users - ( - "EstateID" - ); - -COMMIT; - - -:VERSION 7 - -BEGIN TRANSACTION; - -CREATE TABLE Tmp_estateban - ( - "EstateID" int NOT NULL, - "bannedUUID" uuid NOT NULL, - "bannedIp" varchar(16) NULL, - "bannedIpHostMask" varchar(16) NULL, - "bannedNameMask" varchar(64) NULL - ); - -INSERT INTO Tmp_estateban ("EstateID", "bannedUUID", "bannedIp", "bannedIpHostMask", "bannedNameMask") - SELECT "EstateID", cast("bannedUUID" as uuid), "bannedIp", "bannedIpHostMask", "bannedNameMask" FROM estateban ; - -DROP TABLE estateban; - -Alter table Tmp_estateban - rename to estateban; - -CREATE INDEX IX_estateban ON estateban - ( - "EstateID" - ); - -COMMIT; - - -:VERSION 8 - -BEGIN TRANSACTION; - -CREATE TABLE Tmp_estate_settings - ( - "EstateID" integer default nextval('estate_settings_id') NOT NULL, - "EstateName" varchar(64) NULL DEFAULT (NULL), - "AbuseEmailToEstateOwner" boolean NOT NULL, - "DenyAnonymous" boolean NOT NULL, - "ResetHomeOnTeleport" boolean NOT NULL, - "FixedSun" boolean NOT NULL, - "DenyTransacted" boolean NOT NULL, - "BlockDwell" boolean NOT NULL, - "DenyIdentified" boolean NOT NULL, - "AllowVoice" boolean NOT NULL, - "UseGlobalTime" boolean NOT NULL, - "PricePerMeter" int NOT NULL, - "TaxFree" boolean NOT NULL, - "AllowDirectTeleport" boolean NOT NULL, - "RedirectGridX" int NOT NULL, - "RedirectGridY" int NOT NULL, - "ParentEstateID" int NOT NULL, - "SunPosition" double precision NOT NULL, - "EstateSkipScripts" boolean NOT NULL, - "BillableFactor" double precision NOT NULL, - "PublicAccess" boolean NOT NULL, - "AbuseEmail" varchar(255) NOT NULL, +-- ---------------------------- +-- Table structure for estate_settings +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "public"."estate_settings" ( + "EstateID" int4 NOT NULL DEFAULT nextval('estate_settings_id'::regclass), + "EstateName" varchar(64) DEFAULT NULL::character varying COLLATE "default", + "AbuseEmailToEstateOwner" bool NOT NULL, + "DenyAnonymous" bool NOT NULL, + "ResetHomeOnTeleport" bool NOT NULL, + "FixedSun" bool NOT NULL, + "DenyTransacted" bool NOT NULL, + "BlockDwell" bool NOT NULL, + "DenyIdentified" bool NOT NULL, + "AllowVoice" bool NOT NULL, + "UseGlobalTime" bool NOT NULL, + "PricePerMeter" int4 NOT NULL, + "TaxFree" bool NOT NULL, + "AllowDirectTeleport" bool NOT NULL, + "RedirectGridX" int4 NOT NULL, + "RedirectGridY" int4 NOT NULL, + "ParentEstateID" int4 NOT NULL, + "SunPosition" float8 NOT NULL, + "EstateSkipScripts" bool NOT NULL, + "BillableFactor" float8 NOT NULL, + "PublicAccess" bool NOT NULL, + "AbuseEmail" varchar(255) NOT NULL COLLATE "default", "EstateOwner" uuid NOT NULL, - "DenyMinors" boolean NOT NULL - ); + "DenyMinors" bool NOT NULL, + "AllowLandmark" bool NOT NULL DEFAULT true, + "AllowParcelChanges" bool NOT NULL DEFAULT true, + "AllowSetHome" bool NOT NULL DEFAULT true +) +WITH (OIDS=FALSE); -INSERT INTO Tmp_estate_settings ("EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", "EstateOwner", "DenyMinors") - SELECT "EstateID", "EstateName", "AbuseEmailToEstateOwner", "DenyAnonymous", "ResetHomeOnTeleport", "FixedSun", "DenyTransacted", "BlockDwell", "DenyIdentified", "AllowVoice", "UseGlobalTime", "PricePerMeter", "TaxFree", "AllowDirectTeleport", "RedirectGridX", "RedirectGridY", "ParentEstateID", "SunPosition", "EstateSkipScripts", "BillableFactor", "PublicAccess", "AbuseEmail", cast("EstateOwner" as uuid), "DenyMinors" FROM estate_settings ; +-- Primary key structure for table estate_settings +-- ---------------------------- +ALTER TABLE "public"."estate_settings" ADD PRIMARY KEY ("EstateID") NOT DEFERRABLE INITIALLY IMMEDIATE; -DROP TABLE estate_settings; +-- ---------------------------- +-- Table structure for estate_users +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "public"."estate_users" ( + "EstateID" int4 NOT NULL, + "uuid" uuid NOT NULL +) +WITH (OIDS=FALSE); +-- Indexes structure for table estate_users +-- ---------------------------- +CREATE INDEX IF NOT EXISTS "ix_estate_users" ON "public"."estate_users" USING btree("EstateID" "pg_catalog"."int4_ops" ASC NULLS LAST); -Alter table Tmp_estate_settings - rename to estate_settings; +-- ---------------------------- +-- Table structure for estateban +-- ---------------------------- +CREATE TABLE IF NOT EXISTS "public"."estateban" ( + "EstateID" int4 NOT NULL, + "bannedUUID" uuid NOT NULL, + "bannedIp" varchar(16) COLLATE "default", + "bannedIpHostMask" varchar(16) COLLATE "default", + "bannedNameMask" varchar(64) COLLATE "default" +) +WITH (OIDS=FALSE); - -Create index on estate_settings (lower("EstateName")); +-- Indexes structure for table estateban +-- ---------------------------- +CREATE INDEX IF NOT EXISTS "ix_estateban" ON "public"."estateban" USING btree("EstateID" "pg_catalog"."int4_ops" ASC NULLS LAST); COMMIT; - -:VERSION 9 - -BEGIN TRANSACTION; - -CREATE TABLE Tmp_estate_map - ( - "RegionID" uuid NOT NULL DEFAULT ('00000000-0000-0000-0000-000000000000'), - "EstateID" int NOT NULL - ); - -INSERT INTO Tmp_estate_map ("RegionID", "EstateID") - SELECT cast("RegionID" as uuid), "EstateID" FROM estate_map ; - -DROP TABLE estate_map; - -Alter table Tmp_estate_map - rename to estate_map; - -COMMIT; - -:VERSION 10 - -BEGIN TRANSACTION; -ALTER TABLE estate_settings ADD COLUMN "AllowLandmark" boolean NOT NULL default true; -ALTER TABLE estate_settings ADD COLUMN "AllowParcelChanges" boolean NOT NULL default true; -ALTER TABLE estate_settings ADD COLUMN "AllowSetHome" boolean NOT NULL default true; -COMMIT; - -:VERSION 11 - -Begin transaction; - - -Commit; - diff --git a/OpenSim/Data/PGSQL/Resources/RegionStore.migrations b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations index c08593917d..fcefb6baa3 100644 --- a/OpenSim/Data/PGSQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/PGSQL/Resources/RegionStore.migrations @@ -1195,3 +1195,33 @@ CREATE TABLE bakedterrain ); COMMIT; + +:VERSION 45 #---- Add RezzerID filed in table prims + +BEGIN TRANSACTION; + +ALTER TABLE prims ADD "RezzerID" uuid NULL; + +COMMIT; + +:VERSION 46 #---- Add physics inertia data to table prims + +BEGIN TRANSACTION; + +ALTER TABLE prims ADD "PhysInertia" TEXT; + +COMMIT; + + +:VERSION 47 #---- Convert field PassCollisions in table prims to BOOLEAN + +BEGIN TRANSACTION; + +ALTER TABLE "public"."prims" ALTER COLUMN "PassCollisions" DROP DEFAULT; +ALTER TABLE "public"."prims" + ALTER COLUMN "PassCollisions" TYPE BOOLEAN + USING CASE WHEN "PassCollisions" = 0 THEN FALSE + WHEN "PassCollisions" = 1 THEN TRUE + ELSE NULL + END; +COMMIT; diff --git a/OpenSim/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations index eef14d6a46..fb154cf84a 100644 --- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations +++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations @@ -371,3 +371,9 @@ BEGIN; ALTER TABLE `prims` ADD COLUMN `RezzerID` char(36) DEFAULT NULL; COMMIT; + +:VERSION 36 #----- Add physics inertia data + +BEGIN; +ALTER TABLE `prims` ADD COLUMN `PhysInertia` TEXT default NULL; +COMMIT; diff --git a/OpenSim/Data/SQLite/SQLiteSimulationData.cs b/OpenSim/Data/SQLite/SQLiteSimulationData.cs index eec386fcb0..19880dec20 100644 --- a/OpenSim/Data/SQLite/SQLiteSimulationData.cs +++ b/OpenSim/Data/SQLite/SQLiteSimulationData.cs @@ -1843,6 +1843,12 @@ namespace OpenSim.Data.SQLite if (vehicle != null) prim.VehicleParams = vehicle; } + + PhysicsInertiaData pdata = null; + if (!(row["PhysInertia"] is DBNull) && row["PhysInertia"].ToString() != String.Empty) + pdata = PhysicsInertiaData.FromXml2(row["PhysInertia"].ToString()); + prim.PhysicsInertia = pdata; + return prim; } @@ -2266,6 +2272,11 @@ namespace OpenSim.Data.SQLite else row["Vehicle"] = String.Empty; + if (prim.PhysicsInertia != null) + row["PhysInertia"] = prim.PhysicsInertia.ToXml2(); + else + row["PhysInertia"] = String.Empty; + } /// diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index 7f44a651e9..4ef1f30a8d 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -305,17 +305,11 @@ namespace OpenSim.Data.SQLite using (SqliteCommand cmd = new SqliteCommand()) { - cmd.CommandText = "update inventoryfolders set version=version+1 where folderID = ?folderID"; + cmd.CommandText = "update inventoryfolders set version=version+1 where folderID = :folderID"; cmd.Parameters.Add(new SqliteParameter(":folderID", folderID)); - try - { - cmd.ExecuteNonQuery(); - } - catch (Exception) - { + if(ExecuteNonQuery(cmd, m_Connection) == 0) return false; - } } return true; diff --git a/OpenSim/Framework/AnimationSet.cs b/OpenSim/Framework/AnimationSet.cs index 87c4a78ea9..8753088cc7 100644 --- a/OpenSim/Framework/AnimationSet.cs +++ b/OpenSim/Framework/AnimationSet.cs @@ -31,7 +31,8 @@ using OpenMetaverse; namespace OpenSim.Framework { - public delegate bool AnimationSetValidator(UUID animID); +// public delegate bool AnimationSetValidator(UUID animID); + public delegate uint AnimationSetValidator(UUID animID); public class AnimationSet { @@ -141,7 +142,7 @@ namespace OpenSim.Framework assetData += String.Format("{0} {1} {2}\n", kvp.Key, kvp.Value.Value.ToString(), kvp.Value.Key); return System.Text.Encoding.ASCII.GetBytes(assetData); } - +/* public bool Validate(AnimationSetValidator val) { if (m_parseError) @@ -164,5 +165,22 @@ namespace OpenSim.Framework return allOk; } +*/ + public uint Validate(AnimationSetValidator val) + { + if (m_parseError) + return 0; + + uint ret = 0x7fffffff; + uint t; + foreach (KeyValuePair> kvp in m_animations) + { + t = val(kvp.Value.Value); + if (t == 0) + return 0; + ret &= t; + } + return ret; + } } } diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index d6d8dde6fe..ee5007abf8 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -375,6 +375,7 @@ namespace OpenSim.Framework public string ActiveGroupTitle = null; public UUID agentCOF; public byte CrossingFlags; + public byte CrossExtraFlags; public Dictionary ChildrenCapSeeds = null; public Animation[] Anims; @@ -454,6 +455,8 @@ namespace OpenSim.Framework args["agent_cof"] = OSD.FromUUID(agentCOF); args["crossingflags"] = OSD.FromInteger(CrossingFlags); + if(CrossingFlags != 0) + args["crossExtraFlags"] = OSD.FromInteger(CrossExtraFlags); args["active_group_id"] = OSD.FromUUID(ActiveGroupID); args["active_group_name"] = OSD.FromString(ActiveGroupName); @@ -646,6 +649,12 @@ namespace OpenSim.Framework if (args.ContainsKey("crossingflags") && args["crossingflags"] != null) CrossingFlags = (byte)args["crossingflags"].AsInteger(); + if(CrossingFlags != 0) + { + if (args.ContainsKey("crossExtraFlags") && args["crossExtraFlags"] != null) + CrossExtraFlags = (byte)args["crossExtraFlags"].AsInteger(); + } + if (args.ContainsKey("active_group_id") && args["active_group_id"] != null) ActiveGroupID = args["active_group_id"].AsUUID(); diff --git a/OpenSim/Framework/Client/IClientIPEndpoint.cs b/OpenSim/Framework/Client/IClientIPEndpoint.cs index 2b99bf0a99..2194616a02 100644 --- a/OpenSim/Framework/Client/IClientIPEndpoint.cs +++ b/OpenSim/Framework/Client/IClientIPEndpoint.cs @@ -34,6 +34,6 @@ namespace OpenSim.Framework.Client { public interface IClientIPEndpoint { - IPAddress EndPoint { get; } + IPEndPoint RemoteEndPoint { get; } } } diff --git a/OpenSim/Framework/ClientInfo.cs b/OpenSim/Framework/ClientInfo.cs index 98e4465cf8..a1ca9bc32b 100644 --- a/OpenSim/Framework/ClientInfo.cs +++ b/OpenSim/Framework/ClientInfo.cs @@ -36,14 +36,8 @@ namespace OpenSim.Framework public readonly DateTime StartedTime = DateTime.Now; public AgentCircuitData agentcircuit = null; - public Dictionary needAck; - - public List out_packets = new List(); - public Dictionary pendingAcks = new Dictionary(); public EndPoint proxyEP; - public uint sequence; - public byte[] usecircuit; public EndPoint userEP; public int resendThrottle; @@ -59,9 +53,5 @@ namespace OpenSim.Framework public int targetThrottle; public int maxThrottle; - - public Dictionary SyncRequests = new Dictionary(); - public Dictionary AsyncRequests = new Dictionary(); - public Dictionary GenericRequests = new Dictionary(); } } diff --git a/OpenSim/Framework/ClientManager.cs b/OpenSim/Framework/ClientManager.cs index baff2f4354..45c54e4989 100644 --- a/OpenSim/Framework/ClientManager.cs +++ b/OpenSim/Framework/ClientManager.cs @@ -27,10 +27,8 @@ using System; using System.Collections.Generic; -using System.Reflection; using System.Net; using OpenMetaverse; -using OpenMetaverse.Packets; namespace OpenSim.Framework { @@ -76,20 +74,16 @@ namespace OpenSim.Framework { lock (m_syncRoot) { - if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint)) - return false; + // allow self healing +// if (m_dict1.ContainsKey(value.AgentId) || m_dict2.ContainsKey(value.RemoteEndPoint)) +// return false; m_dict1[value.AgentId] = value; m_dict2[value.RemoteEndPoint] = value; - IClientAPI[] oldArray = m_array; - int oldLength = oldArray.Length; - - IClientAPI[] newArray = new IClientAPI[oldLength + 1]; - for (int i = 0; i < oldLength; i++) - newArray[i] = oldArray[i]; - newArray[oldLength] = value; - + // dict1 is the master + IClientAPI[] newArray = new IClientAPI[m_dict1.Count]; + m_dict1.Values.CopyTo(newArray, 0); m_array = newArray; } @@ -112,22 +106,12 @@ namespace OpenSim.Framework m_dict1.Remove(key); m_dict2.Remove(value.RemoteEndPoint); - IClientAPI[] oldArray = m_array; - int oldLength = oldArray.Length; - - IClientAPI[] newArray = new IClientAPI[oldLength - 1]; - int j = 0; - for (int i = 0; i < oldLength; i++) - { - if (oldArray[i] != value) - newArray[j++] = oldArray[i]; - } - + IClientAPI[] newArray = new IClientAPI[m_dict1.Count]; + m_dict1.Values.CopyTo(newArray, 0); m_array = newArray; return true; } } - return false; } @@ -196,26 +180,12 @@ namespace OpenSim.Framework } } - /// - /// Performs a given task in parallel for each of the elements in the - /// collection - /// - /// Action to perform on each element - public void ForEach(Action action) - { - IClientAPI[] localArray = m_array; - Parallel.For(0, localArray.Length, - delegate(int i) - { action(localArray[i]); } - ); - } - /// /// Performs a given task synchronously for each of the elements in /// the collection /// /// Action to perform on each element - public void ForEachSync(Action action) + public void ForEach(Action action) { IClientAPI[] localArray = m_array; for (int i = 0; i < localArray.Length; i++) diff --git a/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs index 55ec13e5d3..816523b770 100644 --- a/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs +++ b/OpenSim/Framework/DoubleDictionaryThreadAbortSafe.cs @@ -74,21 +74,19 @@ namespace OpenSim.Framework { rwLock.EnterWriteLock(); gotLock = true; + if (Dictionary1.ContainsKey(key1)) + { + if (!Dictionary2.ContainsKey(key2)) + throw new ArgumentException("key1 exists in the dictionary but not key2"); + } + else if (Dictionary2.ContainsKey(key2)) + { + if (!Dictionary1.ContainsKey(key1)) + throw new ArgumentException("key2 exists in the dictionary but not key1"); + } + Dictionary1[key1] = value; + Dictionary2[key2] = value; } - - if (Dictionary1.ContainsKey(key1)) - { - if (!Dictionary2.ContainsKey(key2)) - throw new ArgumentException("key1 exists in the dictionary but not key2"); - } - else if (Dictionary2.ContainsKey(key2)) - { - if (!Dictionary1.ContainsKey(key1)) - throw new ArgumentException("key2 exists in the dictionary but not key1"); - } - - Dictionary1[key1] = value; - Dictionary2[key2] = value; } finally { @@ -112,10 +110,9 @@ namespace OpenSim.Framework { rwLock.EnterWriteLock(); gotLock = true; + Dictionary1.Remove(key1); + success = Dictionary2.Remove(key2); } - - Dictionary1.Remove(key1); - success = Dictionary2.Remove(key2); } finally { @@ -151,8 +148,12 @@ namespace OpenSim.Framework { if (kvp.Value.Equals(value)) { - Dictionary1.Remove(key1); - Dictionary2.Remove(kvp.Key); + try { } + finally + { + Dictionary1.Remove(key1); + Dictionary2.Remove(kvp.Key); + } found = true; break; } @@ -193,8 +194,12 @@ namespace OpenSim.Framework { if (kvp.Value.Equals(value)) { - Dictionary2.Remove(key2); - Dictionary1.Remove(kvp.Key); + try { } + finally + { + Dictionary2.Remove(key2); + Dictionary1.Remove(kvp.Key); + } found = true; break; } @@ -224,10 +229,9 @@ namespace OpenSim.Framework { rwLock.EnterWriteLock(); gotLock = true; + Dictionary1.Clear(); + Dictionary2.Clear(); } - - Dictionary1.Clear(); - Dictionary2.Clear(); } finally { @@ -485,15 +489,15 @@ namespace OpenSim.Framework try {} finally { - rwLock.EnterUpgradeableReadLock(); + rwLock.EnterWriteLock(); gotWriteLock = true; + + for (int i = 0; i < list.Count; i++) + Dictionary1.Remove(list[i]); + + for (int i = 0; i < list2.Count; i++) + Dictionary2.Remove(list2[i]); } - - for (int i = 0; i < list.Count; i++) - Dictionary1.Remove(list[i]); - - for (int i = 0; i < list2.Count; i++) - Dictionary2.Remove(list2[i]); } finally { diff --git a/OpenSim/Framework/IAssetCache.cs b/OpenSim/Framework/IAssetCache.cs index 8477116403..2df9199a26 100644 --- a/OpenSim/Framework/IAssetCache.cs +++ b/OpenSim/Framework/IAssetCache.cs @@ -47,8 +47,9 @@ namespace OpenSim.Framework /// Get an asset by its id. /// /// - /// null if the asset does not exist. - AssetBase Get(string id); + /// Will be set to null if no asset was found + /// False if the asset has been negative-cached + bool Get(string id, out AssetBase asset); /// /// Check whether an asset with the specified id exists in the cache. diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 1267993d1f..5ca8c88ecb 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -107,7 +107,7 @@ namespace OpenSim.Framework public delegate void GenericCall4(Packet packet, IClientAPI remoteClient); public delegate void DeRezObject( - IClientAPI remoteClient, List localIDs, UUID groupID, DeRezAction action, UUID destinationID); + IClientAPI remoteClient, List localIDs, UUID groupID, DeRezAction action, UUID destinationID, bool AddToReturns = true); public delegate void GenericCall5(IClientAPI remoteClient, bool status); @@ -685,9 +685,10 @@ namespace OpenSim.Framework ExtraData = 1 << 20, Sound = 1 << 21, Joint = 1 << 22, - FullUpdate = 0x3fffffff, - CancelKill = 0x7fffffff, - Kill = 0x80000000 + FullUpdate = 0x0fffffff, + SendInTransit = 0x20000000, + CancelKill = 0x4fffffff, // 1 << 30 + Kill = 0x80000000 // 1 << 31 } /* included in .net 4.0 @@ -1112,7 +1113,7 @@ namespace OpenSim.Framework /// void SendKillObject(List localID); - void SendPartFullUpdate(ISceneEntity ent, uint? parentID); +// void SendPartFullUpdate(ISceneEntity ent, uint? parentID); void SendAnimations(UUID[] animID, int[] seqs, UUID sourceAgentId, UUID[] objectIDs); void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args); @@ -1187,7 +1188,8 @@ namespace OpenSim.Framework void SetAgentThrottleSilent(int throttle, int setting); int GetAgentThrottleSilent(int throttle); - void SendAvatarDataImmediate(ISceneEntity avatar); + void SendEntityFullUpdateImmediate(ISceneEntity entity); + void SendEntityTerseUpdateImmediate(ISceneEntity entity); /// /// Send a positional, velocity, etc. update to the viewer for a given entity. diff --git a/OpenSim/Framework/ILandChannel.cs b/OpenSim/Framework/ILandChannel.cs index 44a24b94a3..866783751c 100644 --- a/OpenSim/Framework/ILandChannel.cs +++ b/OpenSim/Framework/ILandChannel.cs @@ -76,6 +76,8 @@ namespace OpenSim.Region.Framework.Interfaces /// ILandObject GetLandObject(int localID); + ILandObject GetLandObject(UUID GlobalID); + /// /// Clear the land channel of all parcels. /// @@ -86,6 +88,7 @@ namespace OpenSim.Region.Framework.Interfaces bool IsForcefulBansAllowed(); void UpdateLandObject(int localID, LandData data); + void SendParcelsOverlay(IClientAPI client); void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient); void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel); void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel); diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index f3b850d528..a7832568a2 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs @@ -189,5 +189,7 @@ namespace OpenSim.Framework /// /// The music url. string GetMusicUrl(); + + void Clear(); } } diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs index be454385db..c72c742151 100644 --- a/OpenSim/Framework/IMoneyModule.cs +++ b/OpenSim/Framework/IMoneyModule.cs @@ -41,6 +41,7 @@ namespace OpenSim.Framework void ApplyCharge(UUID agentID, int amount, MoneyTransactionType type, string extraData = ""); void ApplyUploadCharge(UUID agentID, int amount, string text); void MoveMoney(UUID fromUser, UUID toUser, int amount, string text); + bool MoveMoney(UUID fromUser, UUID toUser, int amount, MoneyTransactionType type, string text); int UploadCharge { get; } int GroupCreationCharge { get; } diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs index 13d29776c5..13b58be3dd 100644 --- a/OpenSim/Framework/LandData.cs +++ b/OpenSim/Framework/LandData.cs @@ -97,7 +97,9 @@ namespace OpenSim.Framework private bool _mediaLoop = false; private bool _obscureMusic = false; private bool _obscureMedia = false; - private float _dwell = 0; + + private float m_dwell = 0; + public double LastDwellTimeMS; public bool SeeAVs { get; set; } public bool AnyAVSounds { get; set; } @@ -111,11 +113,12 @@ namespace OpenSim.Framework { get { - return _dwell; + return m_dwell; } set { - _dwell = value; + m_dwell = value; + LastDwellTimeMS = Util.GetTimeStampMS(); } } @@ -735,6 +738,7 @@ namespace OpenSim.Framework SeeAVs = true; AnyAVSounds = true; GroupAVSounds = true; + LastDwellTimeMS = Util.GetTimeStampMS(); } /// @@ -784,7 +788,7 @@ namespace OpenSim.Framework landData._obscureMedia = _obscureMedia; landData._simwideArea = _simwideArea; landData._simwidePrims = _simwidePrims; - landData._dwell = _dwell; + landData.m_dwell = m_dwell; landData.SeeAVs = SeeAVs; landData.AnyAVSounds = AnyAVSounds; landData.GroupAVSounds = GroupAVSounds; diff --git a/OpenSim/Framework/Monitoring/JobEngine.cs b/OpenSim/Framework/Monitoring/JobEngine.cs index 0a39e4b6be..115871e4a7 100644 --- a/OpenSim/Framework/Monitoring/JobEngine.cs +++ b/OpenSim/Framework/Monitoring/JobEngine.cs @@ -57,7 +57,8 @@ namespace OpenSim.Framework.Monitoring /// /// Will be null if no job is currently running. /// - public Job CurrentJob { get; private set; } + private Job m_currentJob; + public Job CurrentJob { get { return m_currentJob;} } /// /// Number of jobs waiting to be processed. @@ -82,16 +83,15 @@ namespace OpenSim.Framework.Monitoring private CancellationTokenSource m_cancelSource; - /// - /// Used to signal that we are ready to complete stop. - /// - private ManualResetEvent m_finishedProcessingAfterStop = new ManualResetEvent(false); + private int m_timeout = -1; - public JobEngine(string name, string loggingName) + private bool m_threadRunnig = false; + + public JobEngine(string name, string loggingName, int timeout = -1) { Name = name; LoggingName = loggingName; - + m_timeout = timeout; RequestProcessTimeoutOnStop = 5000; } @@ -104,18 +104,9 @@ namespace OpenSim.Framework.Monitoring IsRunning = true; - m_finishedProcessingAfterStop.Reset(); - m_cancelSource = new CancellationTokenSource(); - - WorkManager.StartThread( - ProcessRequests, - Name, - ThreadPriority.Normal, - false, - true, - null, - int.MaxValue); + WorkManager.RunInThreadPool(ProcessRequests, null, Name, false); + m_threadRunnig = true; } } @@ -131,17 +122,16 @@ namespace OpenSim.Framework.Monitoring m_log.DebugFormat("[JobEngine] Stopping {0}", Name); IsRunning = false; - - m_finishedProcessingAfterStop.Reset(); - if(m_jobQueue.Count <= 0) + if(m_threadRunnig) + { m_cancelSource.Cancel(); - - if(m_finishedProcessingAfterStop.WaitOne(RequestProcessTimeoutOnStop)) - m_finishedProcessingAfterStop.Close(); + m_threadRunnig = false; + } } finally { - m_cancelSource.Dispose(); + if(m_cancelSource != null) + m_cancelSource.Dispose(); } } } @@ -200,6 +190,18 @@ namespace OpenSim.Framework.Monitoring /// public bool QueueJob(Job job) { + lock(JobLock) + { + if(!IsRunning) + return false; + + if(!m_threadRunnig) + { + WorkManager.RunInThreadPool(ProcessRequests, null, Name, false); + m_threadRunnig = true; + } + } + if (m_jobQueue.Count < m_jobQueue.BoundedCapacity) { m_jobQueue.Add(job); @@ -219,31 +221,28 @@ namespace OpenSim.Framework.Monitoring m_warnOverMaxQueue = false; } - return false; } } - private void ProcessRequests() + private void ProcessRequests(Object o) { - while(IsRunning || m_jobQueue.Count > 0) + while(IsRunning) { try { - CurrentJob = m_jobQueue.Take(m_cancelSource.Token); + if(!m_jobQueue.TryTake(out m_currentJob, m_timeout, m_cancelSource.Token)) + { + lock(JobLock) + m_threadRunnig = false; + break; + } } catch(ObjectDisposedException e) { - // If we see this whilst not running then it may be due to a race where this thread checks - // IsRunning after the stopping thread sets it to false and disposes of the cancellation source. - if(IsRunning) - throw e; - else - { - m_log.DebugFormat("[JobEngine] {0} stopping ignoring {1} jobs in queue", - Name,m_jobQueue.Count); - break; - } + m_log.DebugFormat("[JobEngine] {0} stopping ignoring {1} jobs in queue", + Name,m_jobQueue.Count); + break; } catch(OperationCanceledException) { @@ -251,27 +250,24 @@ namespace OpenSim.Framework.Monitoring } if(LogLevel >= 1) - m_log.DebugFormat("[{0}]: Processing job {1}",LoggingName,CurrentJob.Name); + m_log.DebugFormat("[{0}]: Processing job {1}",LoggingName,m_currentJob.Name); try { - CurrentJob.Action(); + m_currentJob.Action(); } catch(Exception e) { m_log.Error( string.Format( - "[{0}]: Job {1} failed, continuing. Exception ",LoggingName,CurrentJob.Name),e); + "[{0}]: Job {1} failed, continuing. Exception ",LoggingName,m_currentJob.Name),e); } if(LogLevel >= 1) - m_log.DebugFormat("[{0}]: Processed job {1}",LoggingName,CurrentJob.Name); + m_log.DebugFormat("[{0}]: Processed job {1}",LoggingName,m_currentJob.Name); - CurrentJob = null; + m_currentJob = null; } - - Watchdog.RemoveThread(false); - m_finishedProcessingAfterStop.Set(); } public class Job diff --git a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs index 3391240ce5..a26a6e0366 100644 --- a/OpenSim/Framework/Monitoring/ServerStatsCollector.cs +++ b/OpenSim/Framework/Monitoring/ServerStatsCollector.cs @@ -88,7 +88,7 @@ namespace OpenSim.Framework.Monitoring IConfig cfg = source.Configs["Monitoring"]; if (cfg != null) - Enabled = cfg.GetBoolean("ServerStatsEnabled", true); + Enabled = cfg.GetBoolean("ServerStatsEnabled", false); if (Enabled) { @@ -98,12 +98,18 @@ namespace OpenSim.Framework.Monitoring public void Start() { + if(!Enabled) + return; + if (RegisteredStats.Count == 0) RegisterServerStats(); } public void Close() { + if(!Enabled) + return; + if (RegisteredStats.Count > 0) { foreach (Stat stat in RegisteredStats.Values) diff --git a/OpenSim/Framework/Monitoring/StatsManager.cs b/OpenSim/Framework/Monitoring/StatsManager.cs index 55c327656a..a6b341f21c 100644 --- a/OpenSim/Framework/Monitoring/StatsManager.cs +++ b/OpenSim/Framework/Monitoring/StatsManager.cs @@ -47,6 +47,8 @@ namespace OpenSim.Framework.Monitoring // Subcommand used to list other stats. public const string ListSubCommand = "list"; + public static string StatsPassword { get; set; } + // All subcommands public static HashSet SubCommands = new HashSet { AllSubCommand, ListSubCommand }; @@ -302,6 +304,17 @@ namespace OpenSim.Framework.Monitoring int response_code = 200; string contenttype = "text/json"; + if (StatsPassword != String.Empty && (!request.ContainsKey("pass") || request["pass"].ToString() != StatsPassword)) + { + responsedata["int_response_code"] = response_code; + responsedata["content_type"] = "text/plain"; + responsedata["keepalive"] = false; + responsedata["str_response_string"] = "Access denied"; + responsedata["access_control_allow_origin"] = "*"; + + return responsedata; + } + string pCategoryName = StatsManager.AllSubCommand; string pContainerName = StatsManager.AllSubCommand; string pStatName = StatsManager.AllSubCommand; diff --git a/OpenSim/Framework/Monitoring/Watchdog.cs b/OpenSim/Framework/Monitoring/Watchdog.cs index 9cc61ee62d..9cac451c63 100644 --- a/OpenSim/Framework/Monitoring/Watchdog.cs +++ b/OpenSim/Framework/Monitoring/Watchdog.cs @@ -180,6 +180,30 @@ namespace OpenSim.Framework.Monitoring m_watchdogTimer.Elapsed += WatchdogTimerElapsed; } + public static void Stop() + { + if(m_threads == null) + return; + + lock(m_threads) + { + m_enabled = false; + if(m_watchdogTimer != null) + { + m_watchdogTimer.Dispose(); + m_watchdogTimer = null; + } + + foreach(ThreadWatchdogInfo twi in m_threads.Values) + { + Thread t = twi.Thread; + if(t.IsAlive) + t.Abort(); + } + m_threads.Clear(); + } + } + /// /// Add a thread to the watchdog tracker. /// @@ -230,14 +254,12 @@ namespace OpenSim.Framework.Monitoring twi.Cleanup(); 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; } } @@ -317,6 +339,8 @@ namespace OpenSim.Framework.Monitoring /// private static void WatchdogTimerElapsed(object sender, System.Timers.ElapsedEventArgs e) { + if(!m_enabled) + return; int now = Environment.TickCount & Int32.MaxValue; int msElapsed = now - LastWatchdogThreadTick; @@ -334,21 +358,26 @@ namespace OpenSim.Framework.Monitoring List callbackInfos = null; List threadsToRemove = null; + const ThreadState thgone = ThreadState.Stopped; + lock (m_threads) { foreach(ThreadWatchdogInfo threadInfo in m_threads.Values) { - if(threadInfo.Thread.ThreadState == ThreadState.Stopped) + if(!m_enabled) + return; + if((threadInfo.Thread.ThreadState & thgone) != 0) { if(threadsToRemove == null) threadsToRemove = new List(); threadsToRemove.Add(threadInfo); - +/* if(callbackInfos == null) callbackInfos = new List(); callbackInfos.Add(threadInfo); +*/ } else if(!threadInfo.IsTimedOut && now - threadInfo.LastTick >= threadInfo.Timeout) { diff --git a/OpenSim/Framework/Monitoring/WorkManager.cs b/OpenSim/Framework/Monitoring/WorkManager.cs index 43130f9a0b..5d9b185f29 100644 --- a/OpenSim/Framework/Monitoring/WorkManager.cs +++ b/OpenSim/Framework/Monitoring/WorkManager.cs @@ -57,7 +57,7 @@ namespace OpenSim.Framework.Monitoring static WorkManager() { - JobEngine = new JobEngine("Non-blocking non-critical job engine", "JOB ENGINE"); + JobEngine = new JobEngine("Non-blocking non-critical job engine", "JOB ENGINE", 30000); StatsManager.RegisterStat( new Stat( @@ -82,6 +82,12 @@ namespace OpenSim.Framework.Monitoring HandleControlCommand); } + public static void Stop() + { + JobEngine.Stop(); + Watchdog.Stop(); + } + /// /// Start a new long-lived thread. /// @@ -131,7 +137,6 @@ namespace OpenSim.Framework.Monitoring thread.Start(); - return thread; } @@ -177,9 +182,9 @@ namespace OpenSim.Framework.Monitoring /// /// /// The name of the job. This is used in monitoring and debugging. - public static void RunInThreadPool(System.Threading.WaitCallback callback, object obj, string name) + public static void RunInThreadPool(System.Threading.WaitCallback callback, object obj, string name, bool timeout = true) { - Util.FireAndForget(callback, obj, name); + Util.FireAndForget(callback, obj, name, timeout); } /// @@ -226,10 +231,8 @@ namespace OpenSim.Framework.Monitoring JobEngine.QueueJob(name, () => callback(obj)); else if (canRunInThisThread) callback(obj); - else if (mustNotTimeout) - RunInThread(callback, obj, name, log); else - Util.FireAndForget(callback, obj, name); + Util.FireAndForget(callback, obj, name, !mustNotTimeout); } private static void HandleControlCommand(string module, string[] args) diff --git a/OpenSim/Framework/OutboundUrlFilter.cs b/OpenSim/Framework/OutboundUrlFilter.cs index ee4707fa8c..63ae361448 100644 --- a/OpenSim/Framework/OutboundUrlFilter.cs +++ b/OpenSim/Framework/OutboundUrlFilter.cs @@ -212,7 +212,17 @@ namespace OpenSim.Framework // Check that we are permitted to make calls to this endpoint. bool foundIpv4Address = false; - IPAddress[] addresses = Dns.GetHostAddresses(url.Host); + IPAddress[] addresses = null; + + try + { + addresses = Dns.GetHostAddresses(url.Host); + } + catch + { + // If there is a DNS error, we can't stop the script! + return true; + } foreach (IPAddress addr in addresses) { @@ -253,4 +263,4 @@ namespace OpenSim.Framework return allowed; } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/PermissionsUtil.cs b/OpenSim/Framework/PermissionsUtil.cs index 3dce04dde0..e50d4df8ea 100644 --- a/OpenSim/Framework/PermissionsUtil.cs +++ b/OpenSim/Framework/PermissionsUtil.cs @@ -60,9 +60,57 @@ namespace OpenSim.Framework str += "C"; if ((perms & (int)PermissionMask.Transfer) != 0) str += "T"; + if ((perms & (int)PermissionMask.Export) != 0) + str += "X"; if (str == "") str = "."; return str; } + + public static void ApplyFoldedPermissions(uint foldedSourcePerms, ref uint targetPerms) + { + uint folded = foldedSourcePerms & (uint)PermissionMask.FoldedMask; + if(folded == 0 || folded == (uint)PermissionMask.FoldedMask) // invalid we need to ignore, or nothing to do + return; + + folded <<= (int)PermissionMask.FoldingShift; + folded |= ~(uint)PermissionMask.UnfoldedMask; + + uint tmp = targetPerms; + tmp &= folded; + targetPerms = tmp; + } + + // do not touch MOD + public static void ApplyNoModFoldedPermissions(uint foldedSourcePerms, ref uint target) + { + uint folded = foldedSourcePerms & (uint)PermissionMask.FoldedMask; + if(folded == 0 || folded == (uint)PermissionMask.FoldedMask) // invalid we need to ignore, or nothing to do + return; + + folded <<= (int)PermissionMask.FoldingShift; + folded |= (~(uint)PermissionMask.UnfoldedMask | (uint)PermissionMask.Modify); + + uint tmp = target; + tmp &= folded; + target = tmp; + } + + public static uint FixAndFoldPermissions(uint perms) + { + uint tmp = perms; + + // C & T rule + if((tmp & (uint)(PermissionMask.Copy | PermissionMask.Transfer)) == 0) + tmp |= (uint)PermissionMask.Transfer; + + // unlock + tmp |= (uint)PermissionMask.Move; + + tmp &= ~(uint)PermissionMask.FoldedMask; + tmp |= ((tmp >> (int)PermissionMask.FoldingShift) & (uint)PermissionMask.FoldedMask); + + return tmp; + } } } diff --git a/OpenSim/Framework/PhysicsInertia.cs b/OpenSim/Framework/PhysicsInertia.cs new file mode 100644 index 0000000000..6e1579136c --- /dev/null +++ b/OpenSim/Framework/PhysicsInertia.cs @@ -0,0 +1,262 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; +using System.Text; +using System.IO; +using System.Xml; + +namespace OpenSim.Framework +{ + public class PhysicsInertiaData + { + public float TotalMass; // the total mass of a linkset + public Vector3 CenterOfMass; // the center of mass position relative to root part position + public Vector3 Inertia; // (Ixx, Iyy, Izz) moment of inertia relative to center of mass and principal axis in local coords + public Vector4 InertiaRotation; // if principal axis don't match local axis, the principal axis rotation + // or the upper triangle of the inertia tensor + // Ixy (= Iyx), Ixz (= Izx), Iyz (= Izy)) + + public PhysicsInertiaData() + { + } + + public PhysicsInertiaData(PhysicsInertiaData source) + { + TotalMass = source.TotalMass; + CenterOfMass = source.CenterOfMass; + Inertia = source.Inertia; + InertiaRotation = source.InertiaRotation; + } + + private XmlTextWriter writer; + + private void XWint(string name, int i) + { + writer.WriteElementString(name, i.ToString()); + } + + private void XWfloat(string name, float f) + { + writer.WriteElementString(name, f.ToString(Culture.FormatProvider)); + } + + private void XWVector(string name, Vector3 vec) + { + writer.WriteStartElement(name); + writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider)); + writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider)); + writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider)); + writer.WriteEndElement(); + } + + private void XWVector4(string name, Vector4 quat) + { + writer.WriteStartElement(name); + writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider)); + writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider)); + writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider)); + writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider)); + writer.WriteEndElement(); + } + + public void ToXml2(XmlTextWriter twriter) + { + writer = twriter; + writer.WriteStartElement("PhysicsInertia"); + + XWfloat("MASS", TotalMass); + XWVector("CM", CenterOfMass); + XWVector("INERTIA", Inertia); + XWVector4("IROT", InertiaRotation); + + writer.WriteEndElement(); + writer = null; + } + + XmlReader reader; + + private int XRint() + { + return reader.ReadElementContentAsInt(); + } + + private float XRfloat() + { + return reader.ReadElementContentAsFloat(); + } + + public Vector3 XRvector() + { + Vector3 vec; + reader.ReadStartElement(); + vec.X = reader.ReadElementContentAsFloat(); + vec.Y = reader.ReadElementContentAsFloat(); + vec.Z = reader.ReadElementContentAsFloat(); + reader.ReadEndElement(); + return vec; + } + + public Vector4 XRVector4() + { + Vector4 q; + reader.ReadStartElement(); + q.X = reader.ReadElementContentAsFloat(); + q.Y = reader.ReadElementContentAsFloat(); + q.Z = reader.ReadElementContentAsFloat(); + q.W = reader.ReadElementContentAsFloat(); + reader.ReadEndElement(); + return q; + } + + public static bool EReadProcessors( + Dictionary processors, + XmlReader xtr) + { + bool errors = false; + + string nodeName = string.Empty; + while (xtr.NodeType != XmlNodeType.EndElement) + { + nodeName = xtr.Name; + + Action p = null; + if (processors.TryGetValue(xtr.Name, out p)) + { + try + { + p(); + } + catch + { + errors = true; + if (xtr.NodeType == XmlNodeType.EndElement) + xtr.Read(); + } + } + else + { + xtr.ReadOuterXml(); // ignore + } + } + + return errors; + } + + public string ToXml2() + { + using (StringWriter sw = new StringWriter()) + { + using (XmlTextWriter xwriter = new XmlTextWriter(sw)) + { + ToXml2(xwriter); + } + + return sw.ToString(); + } + } + + public static PhysicsInertiaData FromXml2(string text) + { + if (text == String.Empty) + return null; + + UTF8Encoding enc = new UTF8Encoding(); + MemoryStream ms = new MemoryStream(enc.GetBytes(text)); + XmlTextReader xreader = new XmlTextReader(ms); + + PhysicsInertiaData v = new PhysicsInertiaData(); + bool error; + + v.FromXml2(xreader, out error); + + xreader.Close(); + + if (error) + return null; + + return v; + } + + public static PhysicsInertiaData FromXml2(XmlReader reader) + { + PhysicsInertiaData data = new PhysicsInertiaData(); + + bool errors = false; + + data.FromXml2(reader, out errors); + if (errors) + return null; + + return data; + } + + private void FromXml2(XmlReader _reader, out bool errors) + { + errors = false; + reader = _reader; + + Dictionary m_XmlProcessors = new Dictionary(); + + m_XmlProcessors.Add("MASS", ProcessXR_Mass); + m_XmlProcessors.Add("CM", ProcessXR_CM); + m_XmlProcessors.Add("INERTIA", ProcessXR_Inertia); + m_XmlProcessors.Add("IROT", ProcessXR_InertiaRotation); + + reader.ReadStartElement("PhysicsInertia", String.Empty); + + errors = EReadProcessors( + m_XmlProcessors, + reader); + + reader.ReadEndElement(); + reader = null; + } + + private void ProcessXR_Mass() + { + TotalMass = XRfloat(); + } + + private void ProcessXR_CM() + { + CenterOfMass = XRvector(); + } + + private void ProcessXR_Inertia() + { + Inertia = XRvector(); + } + + private void ProcessXR_InertiaRotation() + { + InertiaRotation = XRVector4(); + } + } +} diff --git a/OpenSim/Framework/PrimitiveBaseShape.cs b/OpenSim/Framework/PrimitiveBaseShape.cs index 29985d2586..96d78d3eed 100644 --- a/OpenSim/Framework/PrimitiveBaseShape.cs +++ b/OpenSim/Framework/PrimitiveBaseShape.cs @@ -328,6 +328,70 @@ namespace OpenSim.Framework return shape; } + public static PrimitiveBaseShape CreateMesh(int numberOfFaces, UUID meshAssetID) + { + PrimitiveBaseShape shape = new PrimitiveBaseShape(); + + shape._pathScaleX = 100; + shape._pathScaleY = 100; + + if(numberOfFaces <= 0) // oops ? + numberOfFaces = 1; + + switch(numberOfFaces) + { + case 1: // torus + shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Curve1; + break; + + case 2: // torus with hollow (a sl viewer whould see 4 faces on a hollow sphere) + shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Curve1; + shape.ProfileHollow = 1; + break; + + case 3: // cylinder + shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Straight; + break; + + case 4: // cylinder with hollow + shape.ProfileCurve = (byte)ProfileShape.Circle | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Straight; + shape.ProfileHollow = 1; + break; + + case 5: // prism + shape.ProfileCurve = (byte)ProfileShape.EquilateralTriangle | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Straight; + break; + + case 6: // box + shape.ProfileCurve = (byte)ProfileShape.Square | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Straight; + break; + + case 7: // box with hollow + shape.ProfileCurve = (byte)ProfileShape.Square | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Straight; + shape.ProfileHollow = 1; + break; + + default: // 8 faces box with cut + shape.ProfileCurve = (byte)ProfileShape.Square | (byte)HollowShape.Triangle; + shape.PathCurve = (byte)Extrusion.Straight; + shape.ProfileBegin = 1; + break; + } + + shape.SculptEntry = true; + shape.SculptType = (byte)OpenMetaverse.SculptType.Mesh; + shape.SculptTexture = meshAssetID; + + return shape; + } + public void SetScale(float side) { _scale = new Vector3(side, side, side); @@ -1516,35 +1580,48 @@ namespace OpenSim.Framework { MediaList ml = new MediaList(); ml.ReadXml(rawXml); + if(ml.Count == 0) + return null; return ml; } public void ReadXml(string rawXml) { - using (StringReader sr = new StringReader(rawXml)) + try { - using (XmlTextReader xtr = new XmlTextReader(sr)) + using (StringReader sr = new StringReader(rawXml)) { - xtr.MoveToContent(); - - string type = xtr.GetAttribute("type"); - //m_log.DebugFormat("[MOAP]: Loaded media texture entry with type {0}", type); - - if (type != MEDIA_TEXTURE_TYPE) - return; - - xtr.ReadStartElement("OSMedia"); - - OSDArray osdMeArray = (OSDArray)OSDParser.DeserializeLLSDXml(xtr.ReadInnerXml()); - foreach (OSD osdMe in osdMeArray) + using (XmlTextReader xtr = new XmlTextReader(sr)) { - MediaEntry me = (osdMe is OSDMap ? MediaEntry.FromOSD(osdMe) : new MediaEntry()); - Add(me); - } + xtr.MoveToContent(); - xtr.ReadEndElement(); + string type = xtr.GetAttribute("type"); + //m_log.DebugFormat("[MOAP]: Loaded media texture entry with type {0}", type); + + if (type != MEDIA_TEXTURE_TYPE) + return; + + xtr.ReadStartElement("OSMedia"); + OSD osdp = OSDParser.DeserializeLLSDXml(xtr.ReadInnerXml()); + if(osdp == null || !(osdp is OSDArray)) + return; + + OSDArray osdMeArray = osdp as OSDArray; + if(osdMeArray.Count == 0) + return; + + foreach (OSD osdMe in osdMeArray) + { + MediaEntry me = (osdMe is OSDMap ? MediaEntry.FromOSD(osdMe) : new MediaEntry()); + Add(me); + } + } } } + catch + { + m_log.Debug("PrimitiveBaseShape] error decoding MOAP xml" ); + } } public void ReadXml(XmlReader reader) diff --git a/OpenSim/Framework/PriorityQueue.cs b/OpenSim/Framework/PriorityQueue.cs index 5b9185e5c8..22ffcdc8b6 100644 --- a/OpenSim/Framework/PriorityQueue.cs +++ b/OpenSim/Framework/PriorityQueue.cs @@ -216,6 +216,27 @@ namespace OpenSim.Framework return false; } + public bool TryOrderedDequeue(out EntityUpdate value, out Int32 timeinqueue) + { + // If there is anything in imediate queues, return it first no + // matter what else. Breaks fairness. But very useful. + for (int iq = 0; iq < NumberOfQueues; iq++) + { + if (m_heaps[iq].Count > 0) + { + MinHeapItem item = m_heaps[iq].RemoveMin(); + m_lookupTable.Remove(item.Value.Entity.LocalId); + timeinqueue = Util.EnvironmentTickCountSubtract(item.EntryTime); + value = item.Value; + return true; + } + } + + timeinqueue = 0; + value = default(EntityUpdate); + return false; + } + /// /// Reapply the prioritization function to each of the updates currently /// stored in the priority queues. diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index 99e97e8b51..75ed999601 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -130,7 +130,7 @@ namespace OpenSim.Framework private float m_physPrimMin = 0; private int m_physPrimMax = 0; private bool m_clampPrimSize = false; - private int m_objectCapacity = 0; + private int m_objectCapacity = 15000; private int m_maxPrimsPerUser = -1; private int m_linksetCapacity = 0; private string m_regionType = String.Empty; @@ -420,6 +420,7 @@ namespace OpenSim.Framework set { m_remotingPort = value; } } + /// /// This accessor can throw all the exceptions that Dns.GetHostAddresses can throw. /// @@ -427,42 +428,7 @@ namespace OpenSim.Framework /// public IPEndPoint ExternalEndPoint { - get - { - // Old one defaults to IPv6 - //return new IPEndPoint(Dns.GetHostAddresses(m_externalHostName)[0], m_internalEndPoint.Port); - - IPAddress ia = null; - // If it is already an IP, don't resolve it - just return directly - if (IPAddress.TryParse(m_externalHostName, out ia)) - return new IPEndPoint(ia, m_internalEndPoint.Port); - - // Reset for next check - ia = null; - try - { - foreach (IPAddress Adr in Dns.GetHostAddresses(m_externalHostName)) - { - if (ia == null) - ia = Adr; - - if (Adr.AddressFamily == AddressFamily.InterNetwork) - { - ia = Adr; - break; - } - } - } - catch (SocketException e) - { - throw new Exception( - "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" + - e + "' attached to this exception", e); - } - - return new IPEndPoint(ia, m_internalEndPoint.Port); - } - + get { return Util.getEndPoint(m_externalHostName, m_internalEndPoint.Port); } set { m_externalHostName = value.ToString(); } } @@ -753,7 +719,7 @@ namespace OpenSim.Framework m_clampPrimSize = config.GetBoolean("ClampPrimSize", false); allKeys.Remove("ClampPrimSize"); - m_objectCapacity = config.GetInt("MaxPrims", 15000); + m_objectCapacity = config.GetInt("MaxPrims", m_objectCapacity); allKeys.Remove("MaxPrims"); m_maxPrimsPerUser = config.GetInt("MaxPrimsPerUser", -1); diff --git a/OpenSim/Framework/RestClient.cs b/OpenSim/Framework/RestClient.cs index 0166d9d37e..4939cf7bfd 100644 --- a/OpenSim/Framework/RestClient.cs +++ b/OpenSim/Framework/RestClient.cs @@ -428,22 +428,23 @@ namespace OpenSim.Framework if (WebUtil.DebugLevel >= 5) WebUtil.LogOutgoingDetail(string.Format("SEND {0}: ", reqnum), src); - using (Stream dst = _request.GetRequestStream()) - { - m_log.Debug("[REST]: GetRequestStream is ok"); - - byte[] buf = new byte[1024]; - int length = src.Read(buf, 0, 1024); - m_log.Debug("[REST]: First Read is ok"); - while (length > 0) - { - dst.Write(buf, 0, length); - length = src.Read(buf, 0, 1024); - } - } - + try { + using (Stream dst = _request.GetRequestStream()) + { +// m_log.Debug("[REST]: GetRequestStream is ok"); + + byte[] buf = new byte[1024]; + int length = src.Read(buf, 0, 1024); +// m_log.Debug("[REST]: First Read is ok"); + while (length > 0) + { + dst.Write(buf, 0, length); + length = src.Read(buf, 0, 1024); + } + } + _response = (HttpWebResponse)_request.GetResponse(); } catch (WebException e) diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index f761813560..81dd3574ad 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -108,13 +108,21 @@ namespace OpenSim.Framework.Servers protected override void ShutdownSpecific() { - m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting..."); + Watchdog.Enabled = false; + base.ShutdownSpecific(); + + MainServer.Stop(); + Thread.Sleep(5000); + Util.StopThreadPool(); + WorkManager.Stop(); + + Thread.Sleep(1000); RemovePIDFile(); - base.ShutdownSpecific(); + m_log.Info("[SHUTDOWN]: Shutdown processing on main thread complete. Exiting..."); - if (!SuppressExit) + if (!SuppressExit) Environment.Exit(0); } @@ -163,8 +171,7 @@ namespace OpenSim.Framework.Servers } catch(Exception e) { - m_log.FatalFormat("Fatal error: {0}", - (e.Message == null || e.Message == String.Empty) ? "Unknown reason":e.Message ); + m_log.Fatal("Fatal error: " + e.ToString()); Environment.Exit(1); } diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index fb92b9237a..f4ba02faba 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -399,11 +399,10 @@ namespace OpenSim.Framework.Servers.HttpServer Stream requestStream = req.InputStream; + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); - reader.Close(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody = reader.ReadToEnd(); Hashtable keysvals = new Hashtable(); Hashtable headervals = new Hashtable(); @@ -567,13 +566,10 @@ namespace OpenSim.Framework.Servers.HttpServer IGenericHTTPHandler HTTPRequestHandler = requestHandler as IGenericHTTPHandler; Stream requestStream = request.InputStream; + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); - - reader.Close(); - //requestStream.Close(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody = reader.ReadToEnd(); Hashtable keysvals = new Hashtable(); Hashtable headervals = new Hashtable(); @@ -690,7 +686,8 @@ namespace OpenSim.Framework.Servers.HttpServer } } - request.InputStream.Close(); + if(request.InputStream.CanRead) + request.InputStream.Dispose(); if (buffer != null) { @@ -998,7 +995,7 @@ namespace OpenSim.Framework.Servers.HttpServer { String requestBody; - Stream requestStream = request.InputStream; + Stream requestStream = Util.Copy(request.InputStream); Stream innerStream = null; try { @@ -1009,9 +1006,8 @@ namespace OpenSim.Framework.Servers.HttpServer } using (StreamReader reader = new StreamReader(requestStream, Encoding.UTF8)) - { requestBody = reader.ReadToEnd(); - } + } finally { @@ -1263,12 +1259,10 @@ namespace OpenSim.Framework.Servers.HttpServer //m_log.Warn("[BASE HTTP SERVER]: We've figured out it's a LLSD Request"); Stream requestStream = request.InputStream; + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); - reader.Close(); - requestStream.Close(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody= reader.ReadToEnd(); //m_log.DebugFormat("[OGP]: {0}:{1}", request.RawUrl, requestBody); response.KeepAlive = true; @@ -1592,15 +1586,10 @@ namespace OpenSim.Framework.Servers.HttpServer byte[] buffer; Stream requestStream = request.InputStream; - + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader reader = new StreamReader(requestStream, encoding); - - string requestBody = reader.ReadToEnd(); - // avoid warning for now - reader.ReadToEnd(); - reader.Close(); - requestStream.Close(); + using(StreamReader reader = new StreamReader(requestStream, encoding)) + requestBody = reader.ReadToEnd(); Hashtable keysvals = new Hashtable(); Hashtable headervals = new Hashtable(); @@ -1838,7 +1827,7 @@ namespace OpenSim.Framework.Servers.HttpServer Hashtable headerdata = (Hashtable)responsedata["headers"]; foreach (string header in headerdata.Keys) - response.AddHeader(header, (string)headerdata[header]); + response.AddHeader(header, headerdata[header].ToString()); } byte[] buffer; @@ -2028,7 +2017,8 @@ namespace OpenSim.Framework.Servers.HttpServer try { - PollServiceRequestManager.Stop(); + if(PollServiceRequestManager != null) + PollServiceRequestManager.Stop(); m_httpListener2.ExceptionThrown -= httpServerException; //m_httpListener2.DisconnectHandler = null; diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs index 8ace7a99d0..7150aad1d6 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceEventArgs.cs @@ -50,7 +50,7 @@ namespace OpenSim.Framework.Servers.HttpServer public enum EventType : int { - LongPoll = 0, + Poll = 0, LslHttp = 1, Inventory = 2, Texture = 3, @@ -82,7 +82,7 @@ namespace OpenSim.Framework.Servers.HttpServer NoEvents = pNoEvents; Id = pId; TimeOutms = pTimeOutms; - Type = EventType.LongPoll; + Type = EventType.Poll; } } } diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs index 0e4a9413d0..fefcb20aa0 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceHttpRequest.cs @@ -82,6 +82,9 @@ namespace OpenSim.Framework.Servers.HttpServer byte[] buffer = server.DoHTTPGruntWork(responsedata, response); + if(Request.Body.CanRead) + Request.Body.Dispose(); + response.SendChunked = false; response.ContentLength64 = buffer.Length; response.ContentEncoding = Encoding.UTF8; @@ -107,6 +110,9 @@ namespace OpenSim.Framework.Servers.HttpServer OSHttpResponse response = new OSHttpResponse(new HttpResponse(HttpContext, Request), HttpContext); + if(Request.Body.CanRead) + Request.Body.Dispose(); + response.SendChunked = false; response.ContentLength64 = 0; response.ContentEncoding = Encoding.UTF8; diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs index 936146d904..c6a3e65154 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceRequestManager.cs @@ -48,7 +48,6 @@ namespace OpenSim.Framework.Servers.HttpServer private Dictionary> m_bycontext; private BlockingQueue m_requests = new BlockingQueue(); - private static Queue m_slowRequests = new Queue(); private static Queue m_retryRequests = new Queue(); private uint m_WorkerThreadCount = 0; @@ -56,11 +55,9 @@ namespace OpenSim.Framework.Servers.HttpServer private Thread m_retrysThread; private bool m_running = false; - private int slowCount = 0; private SmartThreadPool m_threadPool; - public PollServiceRequestManager( BaseHttpServer pSrv, bool performResponsesAsync, uint pWorkerThreadCount, int pTimeout) { @@ -80,7 +77,6 @@ namespace OpenSim.Framework.Servers.HttpServer startInfo.ThreadPoolName = "PoolService"; m_threadPool = new SmartThreadPool(startInfo); - } public void Start() @@ -95,7 +91,7 @@ namespace OpenSim.Framework.Servers.HttpServer PoolWorkerJob, string.Format("PollServiceWorkerThread {0}:{1}", i, m_server.Port), ThreadPriority.Normal, - false, + true, false, null, int.MaxValue); @@ -105,7 +101,7 @@ namespace OpenSim.Framework.Servers.HttpServer this.CheckRetries, string.Format("PollServiceWatcherThread:{0}", m_server.Port), ThreadPriority.Normal, - false, + true, true, null, 1000 * 60 * 10); @@ -163,17 +159,7 @@ namespace OpenSim.Framework.Servers.HttpServer public void EnqueueInt(PollServiceHttpRequest req) { if (m_running) - { - if (req.PollServiceArgs.Type != PollServiceEventArgs.EventType.LongPoll) - { - m_requests.Enqueue(req); - } - else - { - lock (m_slowRequests) - m_slowRequests.Enqueue(req); - } - } + m_requests.Enqueue(req); } private void CheckRetries() @@ -188,17 +174,6 @@ namespace OpenSim.Framework.Servers.HttpServer while (m_retryRequests.Count > 0 && m_running) m_requests.Enqueue(m_retryRequests.Dequeue()); } - slowCount++; - if (slowCount >= 10) - { - slowCount = 0; - - lock (m_slowRequests) - { - while (m_slowRequests.Count > 0 && m_running) - m_requests.Enqueue(m_slowRequests.Dequeue()); - } - } } } @@ -206,11 +181,13 @@ namespace OpenSim.Framework.Servers.HttpServer { m_running = false; - Thread.Sleep(1000); // let the world move + Thread.Sleep(100); // let the world move foreach (Thread t in m_workerThreads) Watchdog.AbortThread(t.ManagedThreadId); + m_threadPool.Shutdown(); + // any entry in m_bycontext should have a active request on the other queues // so just delete contents to easy GC foreach (Queue qu in m_bycontext.Values) @@ -229,22 +206,15 @@ namespace OpenSim.Framework.Servers.HttpServer } PollServiceHttpRequest wreq; + m_retryRequests.Clear(); - lock (m_slowRequests) - { - while (m_slowRequests.Count > 0) - m_requests.Enqueue(m_slowRequests.Dequeue()); - - } - while (m_requests.Count() > 0) { try { wreq = m_requests.Dequeue(0); wreq.DoHTTPstop(m_server); - } catch { @@ -260,8 +230,7 @@ namespace OpenSim.Framework.Servers.HttpServer { while (m_running) { - PollServiceHttpRequest req = m_requests.Dequeue(5000); - + PollServiceHttpRequest req = m_requests.Dequeue(4500); Watchdog.UpdateThread(); if (req != null) { @@ -276,11 +245,13 @@ namespace OpenSim.Framework.Servers.HttpServer try { req.DoHTTPGruntWork(m_server, responsedata); - byContextDequeue(req); } - catch (ObjectDisposedException) // Browser aborted before we could read body, server closed the stream + catch (ObjectDisposedException) { - // Ignore it, no need to reply + } + finally + { + byContextDequeue(req); } return null; }, null); @@ -295,12 +266,15 @@ namespace OpenSim.Framework.Servers.HttpServer { req.DoHTTPGruntWork(m_server, req.PollServiceArgs.NoEvents(req.RequestID, req.PollServiceArgs.Id)); - byContextDequeue(req); } catch (ObjectDisposedException) { // Ignore it, no need to reply } + finally + { + byContextDequeue(req); + } return null; }, null); } diff --git a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs index 0305dee118..dfc27157a3 100644 --- a/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs +++ b/OpenSim/Framework/Servers/HttpServer/RestStreamHandler.cs @@ -50,11 +50,10 @@ namespace OpenSim.Framework.Servers.HttpServer protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { + string requestBody; Encoding encoding = Encoding.UTF8; - StreamReader streamReader = new StreamReader(request, encoding); - - string requestBody = streamReader.ReadToEnd(); - streamReader.Close(); + using(StreamReader streamReader = new StreamReader(request,encoding)) + requestBody = streamReader.ReadToEnd(); string param = GetParam(path); string responseString = m_restMethod(requestBody, path, param, httpRequest, httpResponse); diff --git a/OpenSim/Framework/Servers/MainServer.cs b/OpenSim/Framework/Servers/MainServer.cs index ea7b2b56c4..9b1d9068c7 100644 --- a/OpenSim/Framework/Servers/MainServer.cs +++ b/OpenSim/Framework/Servers/MainServer.cs @@ -353,5 +353,17 @@ namespace OpenSim.Framework.Servers return m_Servers[port]; } } + + public static void Stop() + { + lock (m_Servers) + { + foreach (BaseHttpServer httpServer in m_Servers.Values) + { + httpServer.Stop(); + } + } + } + } } \ No newline at end of file diff --git a/OpenSim/Framework/Servers/ServerBase.cs b/OpenSim/Framework/Servers/ServerBase.cs index 8965e71a34..3c2dce81c8 100644 --- a/OpenSim/Framework/Servers/ServerBase.cs +++ b/OpenSim/Framework/Servers/ServerBase.cs @@ -57,6 +57,7 @@ namespace OpenSim.Framework.Servers protected OpenSimAppender m_consoleAppender; protected FileAppender m_logFileAppender; + protected FileAppender m_statsLogFileAppender; protected DateTime m_startuptime; protected string m_startupDirectory = Environment.CurrentDirectory; @@ -156,6 +157,10 @@ namespace OpenSim.Framework.Servers { m_logFileAppender = (FileAppender)appender; } + else if (appender.Name == "StatsLogFileAppender") + { + m_statsLogFileAppender = (FileAppender)appender; + } } if (null == m_consoleAppender) @@ -185,6 +190,18 @@ namespace OpenSim.Framework.Servers m_log.InfoFormat("[SERVER BASE]: Logging started to file {0}", m_logFileAppender.File); } + + if (m_statsLogFileAppender != null && startupConfig != null) + { + string cfgStatsFileName = startupConfig.GetString("StatsLogFile", null); + if (cfgStatsFileName != null) + { + m_statsLogFileAppender.File = cfgStatsFileName; + m_statsLogFileAppender.ActivateOptions(); + } + + m_log.InfoFormat("[SERVER BASE]: Stats Logging started to file {0}", m_statsLogFileAppender.File); + } } /// @@ -257,18 +274,6 @@ namespace OpenSim.Framework.Servers "Show thread status. Synonym for \"show threads\"", (string module, string[] args) => Notice(GetThreadsReport())); - m_console.Commands.AddCommand ( - "Debug", false, "debug comms set", - "debug comms set serialosdreq true|false", - "Set comms parameters. For debug purposes.", - HandleDebugCommsSet); - - m_console.Commands.AddCommand ( - "Debug", false, "debug comms status", - "debug comms status", - "Show current debug comms parameters.", - HandleDebugCommsStatus); - m_console.Commands.AddCommand ( "Debug", false, "debug threadpool set", "debug threadpool set worker|iocp min|max ", @@ -326,47 +331,13 @@ namespace OpenSim.Framework.Servers public void RegisterCommonComponents(IConfigSource configSource) { - IConfig networkConfig = configSource.Configs["Network"]; - - if (networkConfig != null) - { - WebUtil.SerializeOSDRequestsPerEndpoint = networkConfig.GetBoolean("SerializeOSDRequests", false); - } +// IConfig networkConfig = configSource.Configs["Network"]; m_serverStatsCollector = new ServerStatsCollector(); m_serverStatsCollector.Initialise(configSource); m_serverStatsCollector.Start(); } - private void HandleDebugCommsStatus(string module, string[] args) - { - Notice("serialosdreq is {0}", WebUtil.SerializeOSDRequestsPerEndpoint); - } - - private void HandleDebugCommsSet(string module, string[] args) - { - if (args.Length != 5) - { - Notice("Usage: debug comms set serialosdreq true|false"); - return; - } - - if (args[3] != "serialosdreq") - { - Notice("Usage: debug comms set serialosdreq true|false"); - return; - } - - bool setSerializeOsdRequests; - - if (!ConsoleUtil.TryParseConsoleBool(m_console, args[4], out setSerializeOsdRequests)) - return; - - WebUtil.SerializeOSDRequestsPerEndpoint = setSerializeOsdRequests; - - Notice("serialosdreq is now {0}", setSerializeOsdRequests); - } - private void HandleShowThreadpoolCallsActive(string module, string[] args) { List> calls = Util.GetFireAndForgetCallsInProgress().ToList(); @@ -911,16 +882,12 @@ namespace OpenSim.Framework.Servers sb.Append("\n"); } - sb.Append("\n"); + sb.Append(GetThreadPoolReport()); - // For some reason mono 2.6.7 returns an empty threads set! Not going to confuse people by reporting - // zero active threads. + sb.Append("\n"); int totalThreads = Process.GetCurrentProcess().Threads.Count; if (totalThreads > 0) - sb.AppendFormat("Total threads active: {0}\n\n", totalThreads); - - sb.Append("Main threadpool (excluding script engine pools)\n"); - sb.Append(GetThreadPoolReport()); + sb.AppendFormat("Total process threads active: {0}\n\n", totalThreads); return sb.ToString(); } @@ -931,15 +898,46 @@ namespace OpenSim.Framework.Servers /// public static string GetThreadPoolReport() { + + StringBuilder sb = new StringBuilder(); + + // framework pool is alwasy active + int maxWorkers; + int minWorkers; + int curWorkers; + int maxComp; + int minComp; + int curComp; + + try + { + ThreadPool.GetMaxThreads(out maxWorkers, out maxComp); + ThreadPool.GetMinThreads(out minWorkers, out minComp); + ThreadPool.GetAvailableThreads(out curWorkers, out curComp); + curWorkers = maxWorkers - curWorkers; + curComp = maxComp - curComp; + + sb.Append("\nFramework main threadpool \n"); + sb.AppendFormat("workers: {0} ({1} / {2})\n", curWorkers, maxWorkers, minWorkers); + sb.AppendFormat("Completion: {0} ({1} / {2})\n", curComp, maxComp, minComp); + } + catch { } + + if ( + Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem + || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) + { + sb.AppendFormat("\nThread pool used: Framework main threadpool\n"); + return sb.ToString(); + } + string threadPoolUsed = null; int maxThreads = 0; int minThreads = 0; int allocatedThreads = 0; int inUseThreads = 0; int waitingCallbacks = 0; - int completionPortThreads = 0; - StringBuilder sb = new StringBuilder(); if (Util.FireAndForgetMethod == FireAndForgetMethod.SmartThreadPool) { STPInfo stpi = Util.GetSmartThreadPoolInfo(); @@ -955,22 +953,10 @@ namespace OpenSim.Framework.Servers waitingCallbacks = stpi.WaitingCallbacks; } } - else if ( - Util.FireAndForgetMethod == FireAndForgetMethod.QueueUserWorkItem - || Util.FireAndForgetMethod == FireAndForgetMethod.UnsafeQueueUserWorkItem) - { - threadPoolUsed = "BuiltInThreadPool"; - ThreadPool.GetMaxThreads(out maxThreads, out completionPortThreads); - ThreadPool.GetMinThreads(out minThreads, out completionPortThreads); - int availableThreads; - ThreadPool.GetAvailableThreads(out availableThreads, out completionPortThreads); - inUseThreads = maxThreads - availableThreads; - allocatedThreads = -1; - waitingCallbacks = -1; - } - + if (threadPoolUsed != null) { + sb.Append("\nThreadpool (excluding script engine pools)\n"); sb.AppendFormat("Thread pool used : {0}\n", threadPoolUsed); sb.AppendFormat("Max threads : {0}\n", maxThreads); sb.AppendFormat("Min threads : {0}\n", minThreads); diff --git a/OpenSim/Framework/Util.cs b/OpenSim/Framework/Util.cs index 6d679f2c12..a42dcc6f6c 100644 --- a/OpenSim/Framework/Util.cs +++ b/OpenSim/Framework/Util.cs @@ -63,22 +63,37 @@ namespace OpenSim.Framework None = 0, // folded perms - foldedTransfer = 1, - foldedModify = 1 << 1, - foldedCopy = 1 << 2, + FoldedTransfer = 1, + FoldedModify = 1 << 1, + FoldedCopy = 1 << 2, + FoldedExport = 1 << 3, - foldedMask = 0x07, + // DO NOT USE THIS FOR NEW WORK. IT IS DEPRECATED AND + // EXISTS ONLY TO REACT TO EXISTING OBJECTS HAVING IT. + // NEW CODE SHOULD NEVER SET THIS BIT! + // Use InventoryItemFlags.ObjectSlamPerm in the Flags field of + // this legacy slam bit. It comes from prior incomplete + // understanding of the code and the prohibition on + // reading viewer code that used to be in place. + Slam = (1 << 4), - // - Transfer = 1 << 13, - Modify = 1 << 14, - Copy = 1 << 15, - Export = 1 << 16, - Move = 1 << 19, - Damage = 1 << 20, + FoldedMask = 0x0f, + + FoldingShift = 13 , // number of bit shifts from normal perm to folded or back (same as Transfer shift below) + // when doing as a block + + Transfer = 1 << 13, // 0x02000 + Modify = 1 << 14, // 0x04000 + Copy = 1 << 15, // 0x08000 + Export = 1 << 16, // 0x10000 + Move = 1 << 19, // 0x80000 + Damage = 1 << 20, // 0x100000 does not seem to be in use // All does not contain Export, which is special and must be // explicitly given - All = (1 << 13) | (1 << 14) | (1 << 15) | (1 << 19) + All = 0x8e000, + AllAndExport = 0x9e000, + AllEffective = 0x9e000, + UnfoldedMask = 0x1e000 } /// @@ -141,12 +156,14 @@ namespace OpenSim.Framework public static readonly int MAX_THREADPOOL_LEVEL = 3; public static double TimeStampClockPeriodMS; + public static double TimeStampClockPeriod; static Util() { LogThreadPool = 0; LogOverloads = true; - TimeStampClockPeriodMS = 1000.0D / (double)Stopwatch.Frequency; + TimeStampClockPeriod = 1.0D/ (double)Stopwatch.Frequency; + TimeStampClockPeriodMS = 1e3 * TimeStampClockPeriod; m_log.InfoFormat("[UTIL] TimeStamp clock with period of {0}ms", Math.Round(TimeStampClockPeriodMS,6,MidpointRounding.AwayFromZero)); } @@ -414,6 +431,7 @@ namespace OpenSim.Framework return regionCoord << 8; } + public static bool checkServiceURI(string uristr, out string serviceURI) { serviceURI = string.Empty; @@ -975,6 +993,8 @@ namespace OpenSim.Framework return output.ToString(); } + private static ExpiringCache dnscache = new ExpiringCache(); + /// /// Converts a URL to a IPAddress /// @@ -992,38 +1012,128 @@ namespace OpenSim.Framework /// An IP address, or null public static IPAddress GetHostFromDNS(string dnsAddress) { - // Is it already a valid IP? No need to look it up. - IPAddress ipa; - if (IPAddress.TryParse(dnsAddress, out ipa)) - return ipa; + if(String.IsNullOrWhiteSpace(dnsAddress)) + return null; - IPAddress[] hosts = null; + IPAddress ia = null; + if(dnscache.TryGetValue(dnsAddress, out ia) && ia != null) + { + dnscache.AddOrUpdate(dnsAddress, ia, 300); + return ia; + } - // Not an IP, lookup required + ia = null; + // If it is already an IP, don't let GetHostEntry see it + if (IPAddress.TryParse(dnsAddress, out ia) && ia != null) + { + if (ia.Equals(IPAddress.Any) || ia.Equals(IPAddress.IPv6Any)) + return null; + dnscache.AddOrUpdate(dnsAddress, ia, 300); + return ia; + } + + IPHostEntry IPH; try { - hosts = Dns.GetHostEntry(dnsAddress).AddressList; + IPH = Dns.GetHostEntry(dnsAddress); } - catch (Exception e) + catch // (SocketException e) { - m_log.WarnFormat("[UTIL]: An error occurred while resolving host name {0}, {1}", dnsAddress, e); - - // Still going to throw the exception on for now, since this was what was happening in the first place - throw e; + return null; } - foreach (IPAddress host in hosts) + if(IPH == null || IPH.AddressList.Length == 0) + return null; + + ia = null; + foreach (IPAddress Adr in IPH.AddressList) { - if (host.AddressFamily == AddressFamily.InterNetwork) + if (ia == null) + ia = Adr; + + if (Adr.AddressFamily == AddressFamily.InterNetwork) { - return host; + ia = Adr; + break; + } + } + if(ia != null) + dnscache.AddOrUpdate(dnsAddress, ia, 300); + return ia; + } + + public static IPEndPoint getEndPoint(IPAddress ia, int port) + { + if(ia == null) + return null; + + IPEndPoint newEP = null; + try + { + newEP = new IPEndPoint(ia, port); + } + catch + { + newEP = null; + } + return newEP; + } + + public static IPEndPoint getEndPoint(string hostname, int port) + { + if(String.IsNullOrWhiteSpace(hostname)) + return null; + + IPAddress ia = null; + if(dnscache.TryGetValue(hostname, out ia) && ia != null) + { + dnscache.AddOrUpdate(hostname, ia, 300); + return getEndPoint(ia, port); + } + + ia = null; + + // If it is already an IP, don't let GetHostEntry see it + if (IPAddress.TryParse(hostname, out ia) && ia != null) + { + if (ia.Equals(IPAddress.Any) || ia.Equals(IPAddress.IPv6Any)) + return null; + + dnscache.AddOrUpdate(hostname, ia, 300); + return getEndPoint(ia, port); + } + + + IPHostEntry IPH; + try + { + IPH = Dns.GetHostEntry(hostname); + } + catch // (SocketException e) + { + return null; + } + + if(IPH == null || IPH.AddressList.Length == 0) + return null; + + ia = null; + foreach (IPAddress Adr in IPH.AddressList) + { + if (ia == null) + ia = Adr; + + if (Adr.AddressFamily == AddressFamily.InterNetwork) + { + ia = Adr; + break; } } - if (hosts.Length > 0) - return hosts[0]; + if(ia != null) + dnscache.AddOrUpdate(hostname, ia, 300); - return null; + return getEndPoint(ia,port); } public static Uri GetURI(string protocol, string hostname, int port, string path) @@ -1180,7 +1290,7 @@ namespace OpenSim.Framework { foreach (IAppender appender in LogManager.GetRepository().GetAppenders()) { - if (appender is FileAppender) + if (appender is FileAppender && appender.Name == "LogFileAppender") { return ((FileAppender)appender).File; } @@ -1189,6 +1299,19 @@ namespace OpenSim.Framework return "./OpenSim.log"; } + public static string statsLogFile() + { + foreach (IAppender appender in LogManager.GetRepository().GetAppenders()) + { + if (appender is FileAppender && appender.Name == "StatsLogFileAppender") + { + return ((FileAppender)appender).File; + } + } + + return "./OpenSimStats.log"; + } + public static string logDir() { return Path.GetDirectoryName(logFile()); @@ -2100,9 +2223,9 @@ namespace OpenSim.Framework // might have gotten an oversized array even after the string trim byte[] data = UTF8.GetBytes(str); - if (data.Length > 256) + if (data.Length > 255) //play safe { - int cut = 255; + int cut = 254; if((data[cut] & 0x80 ) != 0 ) { while(cut > 0 && (data[cut] & 0xc0) != 0xc0) @@ -2204,7 +2327,7 @@ namespace OpenSim.Framework if (data.Length > MaxLength) { - int cut = MaxLength -1 ; + int cut = MaxLength - 1 ; if((data[cut] & 0x80 ) != 0 ) { while(cut > 0 && (data[cut] & 0xc0) != 0xc0) @@ -2371,8 +2494,9 @@ namespace OpenSim.Framework public bool Running { get; set; } public bool Aborted { get; set; } private int started; + public bool DoTimeout; - public ThreadInfo(long threadFuncNum, string context) + public ThreadInfo(long threadFuncNum, string context, bool dotimeout = true) { ThreadFuncNum = threadFuncNum; this.context = context; @@ -2380,6 +2504,7 @@ namespace OpenSim.Framework Thread = null; Running = false; Aborted = false; + DoTimeout = dotimeout; } public void Started() @@ -2450,7 +2575,7 @@ namespace OpenSim.Framework foreach (KeyValuePair entry in activeThreads) { ThreadInfo t = entry.Value; - if (t.Running && !t.Aborted && (t.Elapsed() >= THREAD_TIMEOUT)) + if (t.DoTimeout && t.Running && !t.Aborted && (t.Elapsed() >= THREAD_TIMEOUT)) { m_log.WarnFormat("Timeout in threadfunc {0} ({1}) {2}", t.ThreadFuncNum, t.Thread.Name, t.GetStackTrace()); t.Abort(); @@ -2491,10 +2616,10 @@ namespace OpenSim.Framework FireAndForget(callback, obj, null); } - public static void FireAndForget(System.Threading.WaitCallback callback, object obj, string context) + public static void FireAndForget(System.Threading.WaitCallback callback, object obj, string context, bool dotimeout = true) { Interlocked.Increment(ref numTotalThreadFuncsCalled); - +/* if (context != null) { if (!m_fireAndForgetCallsMade.ContainsKey(context)) @@ -2507,13 +2632,13 @@ namespace OpenSim.Framework else m_fireAndForgetCallsInProgress[context]++; } - +*/ WaitCallback realCallback; bool loggingEnabled = LogThreadPool > 0; long threadFuncNum = Interlocked.Increment(ref nextThreadFuncNum); - ThreadInfo threadInfo = new ThreadInfo(threadFuncNum, context); + ThreadInfo threadInfo = new ThreadInfo(threadFuncNum, context, dotimeout); if (FireAndForgetMethod == FireAndForgetMethod.RegressionTest) { @@ -2524,8 +2649,8 @@ namespace OpenSim.Framework Culture.SetCurrentCulture(); callback(o); - if (context != null) - m_fireAndForgetCallsInProgress[context]--; +// if (context != null) +// m_fireAndForgetCallsInProgress[context]--; }; } else @@ -2551,7 +2676,6 @@ namespace OpenSim.Framework } catch (ThreadAbortException e) { - m_log.Error(string.Format("Aborted threadfunc {0} ", threadFuncNum), e); } catch (Exception e) { @@ -2566,8 +2690,8 @@ namespace OpenSim.Framework if ((loggingEnabled || (threadFuncOverloadMode == 1)) && threadInfo.LogThread) m_log.DebugFormat("Exit threadfunc {0} ({1})", threadFuncNum, FormatDuration(threadInfo.Elapsed())); - if (context != null) - m_fireAndForgetCallsInProgress[context]--; +// if (context != null) +// m_fireAndForgetCallsInProgress[context]--; } }; } @@ -2824,6 +2948,16 @@ namespace OpenSim.Framework return stpi; } + public static void StopThreadPool() + { + if (m_ThreadPool == null) + return; + SmartThreadPool pool = m_ThreadPool; + m_ThreadPool = null; + + try { pool.Shutdown(); } catch {} + } + #endregion FireAndForget Threading Pattern /// @@ -2837,6 +2971,7 @@ namespace OpenSim.Framework { return Environment.TickCount & EnvironmentTickCountMask; } + const Int32 EnvironmentTickCountMask = 0x3fffffff; /// @@ -2883,6 +3018,11 @@ namespace OpenSim.Framework // returns a timestamp in ms as double // using the time resolution avaiable to StopWatch + public static double GetTimeStamp() + { + return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriod; + } + public static double GetTimeStampMS() { return (double)Stopwatch.GetTimestamp() * TimeStampClockPeriodMS; diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs index ccaf69edfd..427e149f69 100644 --- a/OpenSim/Framework/WearableCacheItem.cs +++ b/OpenSim/Framework/WearableCacheItem.cs @@ -113,7 +113,8 @@ namespace OpenSim.Framework { if (dataCache.Check(item.TextureID.ToString())) { - AssetBase assetItem = dataCache.Get(item.TextureID.ToString()); + AssetBase assetItem; + dataCache.Get(item.TextureID.ToString(), out assetItem); if (assetItem != null) { itemmap.Add("assetdata", OSD.FromBinary(assetItem.Data)); diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 12f58feb79..48078ada97 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -71,11 +71,6 @@ namespace OpenSim.Framework /// public static int RequestNumber { get; set; } - /// - /// Control where OSD requests should be serialized per endpoint. - /// - public static bool SerializeOSDRequestsPerEndpoint { get; set; } - /// /// this is the header field used to communicate the local request id /// used for performance and debugging @@ -98,31 +93,6 @@ namespace OpenSim.Framework /// public const int MaxRequestDiagLength = 200; - /// - /// Dictionary of end points - /// - private static Dictionary m_endpointSerializer = new Dictionary(); - - private static object EndPointLock(string url) - { - System.Uri uri = new System.Uri(url); - string endpoint = string.Format("{0}:{1}",uri.Host,uri.Port); - - lock (m_endpointSerializer) - { - object eplock = null; - - if (! m_endpointSerializer.TryGetValue(endpoint,out eplock)) - { - eplock = new object(); - m_endpointSerializer.Add(endpoint,eplock); - // m_log.WarnFormat("[WEB UTIL] add a new host to end point serializer {0}",endpoint); - } - - return eplock; - } - } - #region JSONRequest /// @@ -154,21 +124,6 @@ namespace OpenSim.Framework return ServiceOSDRequest(url, null, "GET", timeout, false, false); } - public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed, bool rpc) - { - if (SerializeOSDRequestsPerEndpoint) - { - lock (EndPointLock(url)) - { - return ServiceOSDRequestWorker(url, data, method, timeout, compressed, rpc); - } - } - else - { - return ServiceOSDRequestWorker(url, data, method, timeout, compressed, rpc); - } - } - public static void LogOutgoingDetail(Stream outputStream) { LogOutgoingDetail("", outputStream); @@ -222,7 +177,7 @@ namespace OpenSim.Framework LogOutgoingDetail(string.Format("RESPONSE {0}: ", reqnum), input); } - private static OSDMap ServiceOSDRequestWorker(string url, OSDMap data, string method, int timeout, bool compressed, bool rpc) + public static OSDMap ServiceOSDRequest(string url, OSDMap data, string method, int timeout, bool compressed, bool rpc) { int reqnum = RequestNumber++; @@ -421,14 +376,6 @@ namespace OpenSim.Framework } public static OSDMap ServiceFormRequest(string url, NameValueCollection data, int timeout) - { - lock (EndPointLock(url)) - { - return ServiceFormRequestWorker(url,data,timeout); - } - } - - private static OSDMap ServiceFormRequestWorker(string url, NameValueCollection data, int timeout) { int reqnum = RequestNumber++; string method = (data != null && data["RequestMethod"] != null) ? data["RequestMethod"] : "unknown"; @@ -1315,18 +1262,24 @@ namespace OpenSim.Framework { if (hwr.StatusCode == HttpStatusCode.NotFound) return deserial; + if (hwr.StatusCode == HttpStatusCode.Unauthorized) { - m_log.Error(string.Format( - "[SynchronousRestObjectRequester]: Web request {0} requires authentication ", - requestUrl)); - return deserial; + m_log.ErrorFormat("[SynchronousRestObjectRequester]: Web request {0} requires authentication", + requestUrl); + } + else + { + m_log.WarnFormat("[SynchronousRestObjectRequester]: Web request {0} returned error: {1}", + requestUrl, hwr.StatusCode); } } else - m_log.Error(string.Format( - "[SynchronousRestObjectRequester]: WebException for {0} {1} {2} ", - verb, requestUrl, typeof(TResponse).ToString()), e); + m_log.ErrorFormat( + "[SynchronousRestObjectRequester]: WebException for {0} {1} {2} {3}", + verb, requestUrl, typeof(TResponse).ToString(), e.Message); + + return deserial; } } catch (System.InvalidOperationException) diff --git a/OpenSim/Region/Application/Application.cs b/OpenSim/Region/Application/Application.cs index 5cb6a88e94..66ce8e5e3d 100644 --- a/OpenSim/Region/Application/Application.cs +++ b/OpenSim/Region/Application/Application.cs @@ -74,7 +74,15 @@ namespace OpenSim AppDomain.CurrentDomain.UnhandledException += new UnhandledExceptionEventHandler(CurrentDomain_UnhandledException); - ServicePointManager.DefaultConnectionLimit = 12; + if(Util.IsWindows()) + ServicePointManager.DefaultConnectionLimit = 32; + else + { + ServicePointManager.DefaultConnectionLimit = 12; + } + + try { ServicePointManager.DnsRefreshTimeout = 300000; } catch { } + ServicePointManager.Expect100Continue = false; ServicePointManager.UseNagleAlgorithm = false; // Add the arguments supplied when running the application to the configuration diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 8022b1e587..fcc87177a6 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -33,6 +33,7 @@ using System.Diagnostics; using System.IO; using System.Linq; using System.Reflection; +using System.Runtime; using System.Text; using System.Text.RegularExpressions; using System.Timers; @@ -124,8 +125,11 @@ namespace OpenSim Util.InitThreadPool(stpMinThreads, stpMaxThreads); m_log.Info("[OPENSIM MAIN]: Using async_call_method " + Util.FireAndForgetMethod); + + m_log.InfoFormat("[OPENSIM MAIN] Running GC in {0} mode", GCSettings.IsServerGC ? "server":"workstation"); } +#if (_MONO) private static Mono.Unix.UnixSignal[] signals; @@ -139,7 +143,8 @@ namespace OpenSim //Mono.Unix.Native.Signum signal = signals [index].Signum; MainConsole.Instance.RunCommand("shutdown"); } - }); + }); +#endif /// /// Performs initialisation of the scene, such as loading configuration from disk. @@ -150,6 +155,7 @@ namespace OpenSim m_log.Info("========================= STARTING OPENSIM ========================="); m_log.Info("===================================================================="); +#if (_MONO) if(!Util.IsWindows()) { try @@ -159,6 +165,7 @@ namespace OpenSim { new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGTERM) }; + signal_thread.IsBackground = true; signal_thread.Start(); } catch (Exception e) @@ -168,6 +175,7 @@ namespace OpenSim m_log.Debug("Exception was: ", e); } } +#endif //m_log.InfoFormat("[OPENSIM MAIN]: GC Is Server GC: {0}", GCSettings.IsServerGC.ToString()); // http://msdn.microsoft.com/en-us/library/bb384202.aspx //GCSettings.LatencyMode = GCLatencyMode.Batch; @@ -211,6 +219,7 @@ namespace OpenSim if (managedStatsURI != String.Empty) { string urlBase = String.Format("/{0}/", managedStatsURI); + StatsManager.StatsPassword = managedStatsPassword; MainServer.Instance.AddHTTPHandler(urlBase, StatsManager.HandleStatsRequest); m_log.InfoFormat("[OPENSIM] Enabling remote managed stats fetch. URL = {0}", urlBase); } @@ -477,6 +486,12 @@ namespace OpenSim RunCommandScript(m_shutdownCommandsFile); } + if (m_timedScript != "disabled") + { + m_scriptTimer.Dispose(); + m_timedScript = "disabled"; + } + base.ShutdownSpecific(); } @@ -496,7 +511,6 @@ namespace OpenSim private void WatchdogTimeoutHandler(Watchdog.ThreadWatchdogInfo twi) { int now = Environment.TickCount & Int32.MaxValue; - m_log.ErrorFormat( "[WATCHDOG]: Timeout detected for thread \"{0}\". ThreadState={1}. Last tick was {2}ms ago. {3}", twi.Thread.Name, diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index b33e2c2784..0862fcf302 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -88,6 +88,7 @@ namespace OpenSim public string userStatsURI = String.Empty; public string managedStatsURI = String.Empty; + public string managedStatsPassword = String.Empty; protected bool m_autoCreateClientStack = true; @@ -236,9 +237,10 @@ namespace OpenSim string permissionModules = Util.GetConfigVarFromSections(Config, "permissionmodules", new string[] { "Startup", "Permissions" }, "DefaultPermissionsModule"); - m_permsModules = new List(permissionModules.Split(',')); + m_permsModules = new List(permissionModules.Split(',').Select(m => m.Trim())); managedStatsURI = startupConfig.GetString("ManagedStatsRemoteFetchURI", String.Empty); + managedStatsPassword = startupConfig.GetString("ManagedStatsRemoteFetchPassword", String.Empty); } // Load the simulation data service @@ -459,15 +461,14 @@ namespace OpenSim while (regionInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null) SetUpEstateOwner(scene); + scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); + // Prims have to be loaded after module configuration since some modules may be invoked during the load scene.LoadPrimsFromStorage(regionInfo.originRegionID); // TODO : Try setting resource for region xstats here on scene MainServer.Instance.AddStreamHandler(new RegionStatsHandler(regionInfo)); - scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); - scene.EventManager.TriggerParcelPrimCountUpdate(); - if (scene.SnmpService != null) { scene.SnmpService.BootInfo("Grid Registration in progress", scene); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 58b7b00169..6f5775ad3d 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -946,17 +946,26 @@ namespace OpenSim.Region.ClientStack.Linden continue; } - PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); + OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; + + PrimitiveBaseShape pbs = null; + if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ... + { + int meshindx = inner_instance_list["mesh"].AsInteger(); + if (meshAssets.Count > meshindx) + pbs = PrimitiveBaseShape.CreateMesh(face_list.Count, meshAssets[meshindx]); + } + if(pbs == null) // fallback + pbs = PrimitiveBaseShape.CreateBox(); Primitive.TextureEntry textureEntry = new Primitive.TextureEntry(Primitive.TextureEntry.WHITE_TEXTURE); - - OSDArray face_list = (OSDArray)inner_instance_list["face_list"]; for (uint face = 0; face < face_list.Count; face++) { OSDMap faceMap = (OSDMap)face_list[(int)face]; - Primitive.TextureEntryFace f = pbs.Textures.CreateFace(face); + + Primitive.TextureEntryFace f = textureEntry.CreateFace(face); //clone the default if (faceMap.ContainsKey("fullbright")) f.Fullbright = faceMap["fullbright"].AsBoolean(); if (faceMap.ContainsKey("diffuse_color")) @@ -986,51 +995,11 @@ namespace OpenSim.Region.ClientStack.Linden if (textures.Count > textureNum) f.TextureID = textures[textureNum]; - else - f.TextureID = Primitive.TextureEntry.WHITE_TEXTURE; - + textureEntry.FaceTextures[face] = f; } - pbs.TextureEntry = textureEntry.GetBytes(); - if (inner_instance_list.ContainsKey("mesh")) // seems to happen always but ... - { - int meshindx = inner_instance_list["mesh"].AsInteger(); - if (meshAssets.Count > meshindx) - { - pbs.SculptEntry = true; - pbs.SculptType = (byte)SculptType.Mesh; - pbs.SculptTexture = meshAssets[meshindx]; // actual asset UUID after meshs suport introduction - // data will be requested from asset on rez (i hope) - } - } - - // faces number to pbs shape - switch(face_list.Count) - { - case 1: - case 2: - pbs.ProfileCurve = (byte)ProfileCurve.Circle; - pbs.PathCurve = (byte)PathCurve.Circle; - break; - - case 3: - case 4: - pbs.ProfileCurve = (byte)ProfileCurve.Circle; - pbs.PathCurve = (byte)PathCurve.Line; - break; - case 5: - pbs.ProfileCurve = (byte)ProfileCurve.EqualTriangle; - pbs.PathCurve = (byte)PathCurve.Line; - break; - - default: - pbs.ProfileCurve = (byte)ProfileCurve.Square; - pbs.PathCurve = (byte)PathCurve.Line; - break; - } - Vector3 position = inner_instance_list["position"].AsVector3(); Quaternion rotation = inner_instance_list["rotation"].AsQuaternion(); @@ -1608,7 +1577,10 @@ namespace OpenSim.Region.ClientStack.Linden break; m_Scene.TryGetScenePresence(m_AgentID, out sp); - if(sp == null || sp.IsChildAgent || sp.IsDeleted || sp.IsInTransit) + if(sp == null || sp.IsChildAgent || sp.IsDeleted) + break; + + if(sp.IsInTransit && !sp.IsInLocalTransit) break; client = sp.ControllingClient; @@ -1730,7 +1702,10 @@ namespace OpenSim.Region.ClientStack.Linden break; m_Scene.TryGetScenePresence(m_AgentID, out sp); - if(sp == null || sp.IsChildAgent || sp.IsDeleted || sp.IsInTransit) + if(sp == null || sp.IsChildAgent || sp.IsDeleted) + break; + + if(sp.IsInTransit && !sp.IsInLocalTransit) break; client = sp.ControllingClient; @@ -1838,7 +1813,7 @@ namespace OpenSim.Region.ClientStack.Linden if(sp == null || sp.IsDeleted) return ""; - if(sp.IsInTransit) + if(sp.IsInTransit && !sp.IsInLocalTransit) { httpResponse.StatusCode = (int)System.Net.HttpStatusCode.ServiceUnavailable; httpResponse.AddHeader("Retry-After","30"); @@ -1848,7 +1823,6 @@ namespace OpenSim.Region.ClientStack.Linden NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); string[] ids = query.GetValues("ids"); - Dictionary names = m_UserManager.GetUsersNames(ids); OSDMap osdReply = new OSDMap(); @@ -1864,12 +1838,18 @@ namespace OpenSim.Region.ClientStack.Linden string[] parts = kvp.Value.Split(new char[] {' '}); OSDMap osdname = new OSDMap(); + + // dont tell about unknown users, we can't send them back on Bad either + if(parts[0] == "Unknown") + continue; +/* if(parts[0] == "Unknown") { osdname["display_name_next_update"] = OSD.FromDate(DateTime.UtcNow.AddHours(1)); osdname["display_name_expires"] = OSD.FromDate(DateTime.UtcNow.AddHours(2)); } else +*/ { osdname["display_name_next_update"] = OSD.FromDate(DateTime.UtcNow.AddDays(8)); osdname["display_name_expires"] = OSD.FromDate(DateTime.UtcNow.AddMonths(1)); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs index 1feece1f70..7c9a1c4bf8 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueGetModule.cs @@ -500,13 +500,13 @@ namespace OpenSim.Region.ClientStack.Linden responsedata["http_protocol_version"] = "HTTP/1.0"; return responsedata; } - +/* this is not a event message public void DisableSimulator(ulong handle, UUID avatarID) { OSD item = EventQueueHelper.DisableSimulator(handle); Enqueue(item, avatarID); } - +*/ public virtual void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) { if (DebugLevel > 0) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs index e1e88aedb8..461f776eb2 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/EventQueue/EventQueueHelper.cs @@ -90,7 +90,7 @@ namespace OpenSim.Region.ClientStack.Linden return BuildEvent("EnableSimulator", llsdBody); } - +/* public static OSD DisableSimulator(ulong handle) { //OSDMap llsdSimInfo = new OSDMap(1); @@ -105,7 +105,7 @@ namespace OpenSim.Region.ClientStack.Linden return BuildEvent("DisableSimulator", llsdBody); } - +*/ public static OSD CrossRegion(ulong handle, Vector3 pos, Vector3 lookAt, IPEndPoint newRegionExternalEndPoint, string capsURL, UUID agentID, UUID sessionID, diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs index 69ff713c77..ba917e3952 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetMeshModule.cs @@ -89,8 +89,8 @@ namespace OpenSim.Region.ClientStack.Linden private Dictionary m_capsDict = new Dictionary(); private static Thread[] m_workerThreads = null; private static int m_NumberScenes = 0; - private static OpenMetaverse.BlockingQueue m_queue = - new OpenMetaverse.BlockingQueue(); + private static OpenSim.Framework.BlockingQueue m_queue = + new OpenSim.Framework.BlockingQueue(); private Dictionary m_pollservices = new Dictionary(); @@ -171,7 +171,7 @@ namespace OpenSim.Region.ClientStack.Linden m_workerThreads[i] = WorkManager.StartThread(DoMeshRequests, String.Format("GetMeshWorker{0}", i), ThreadPriority.Normal, - false, + true, false, null, int.MaxValue); @@ -204,9 +204,12 @@ namespace OpenSim.Region.ClientStack.Linden { while(true) { - aPollRequest poolreq = m_queue.Dequeue(); + aPollRequest poolreq = m_queue.Dequeue(4500); Watchdog.UpdateThread(); - poolreq.thepoll.Process(poolreq); + if(m_NumberScenes <= 0) + return; + if(poolreq.reqID != UUID.Zero) + poolreq.thepoll.Process(poolreq); } } @@ -218,7 +221,7 @@ namespace OpenSim.Region.ClientStack.Linden PollServiceMeshEventArgs args; if (m_pollservices.TryGetValue(user, out args)) { - args.UpdateThrottle(imagethrottle, p); + args.UpdateThrottle(imagethrottle); } } @@ -235,14 +238,13 @@ namespace OpenSim.Region.ClientStack.Linden base(null, uri, null, null, null, pId, int.MaxValue) { m_scene = scene; - m_throttler = new MeshCapsDataThrottler(100000, 1400000, 10000, scene, pId); + m_throttler = new MeshCapsDataThrottler(100000); // x is request id, y is userid HasEvents = (x, y) => { lock (responses) { bool ret = m_throttler.hasEvents(x, responses); - m_throttler.ProcessTime(); return ret; } @@ -257,8 +259,8 @@ namespace OpenSim.Region.ClientStack.Linden } finally { - m_throttler.ProcessTime(); responses.Remove(x); + m_throttler.PassTime(); } } }; @@ -271,6 +273,7 @@ namespace OpenSim.Region.ClientStack.Linden reqinfo.request = y; m_queue.Enqueue(reqinfo); + m_throttler.PassTime(); }; // this should never happen except possible on shutdown @@ -332,12 +335,15 @@ namespace OpenSim.Region.ClientStack.Linden }; } - m_throttler.ProcessTime(); + m_throttler.PassTime(); } - internal void UpdateThrottle(int pimagethrottle, ScenePresence p) + internal void UpdateThrottle(int pthrottle) { - m_throttler.UpdateThrottle(pimagethrottle, p); + int tmp = 2 * pthrottle; + if(tmp < 10000) + tmp = 10000; + m_throttler.ThrottleBytes = tmp; } } @@ -391,25 +397,15 @@ namespace OpenSim.Region.ClientStack.Linden internal sealed class MeshCapsDataThrottler { + private double lastTimeElapsed = 0; + private double BytesSent = 0; - private volatile int currenttime = 0; - private volatile int lastTimeElapsed = 0; - private volatile int BytesSent = 0; - private int CapSetThrottle = 0; - private float CapThrottleDistributon = 0.30f; - private readonly Scene m_scene; - private ThrottleOutPacketType Throttle; - private readonly UUID User; - - public MeshCapsDataThrottler(int pBytes, int max, int min, Scene pScene, UUID puser) + public MeshCapsDataThrottler(int pBytes) { + if(pBytes < 10000) + pBytes = 10000; ThrottleBytes = pBytes; - if(ThrottleBytes < 10000) - ThrottleBytes = 10000; - lastTimeElapsed = Util.EnvironmentTickCount(); - Throttle = ThrottleOutPacketType.Asset; - m_scene = pScene; - User = puser; + lastTimeElapsed = Util.GetTimeStampMS(); } public bool hasEvents(UUID key, Dictionary responses) @@ -439,46 +435,22 @@ namespace OpenSim.Region.ClientStack.Linden return haskey; } - public void ProcessTime() + public void PassTime() { - PassTime(); - } - - private void PassTime() - { - currenttime = Util.EnvironmentTickCount(); - int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); - if (timeElapsed >= 100) + double currenttime = Util.GetTimeStampMS(); + double timeElapsed = currenttime - lastTimeElapsed; + if(timeElapsed < 50.0) + return; + int add = (int)(ThrottleBytes * timeElapsed * 0.001); + if (add >= 1000) { lastTimeElapsed = currenttime; - BytesSent -= (ThrottleBytes * timeElapsed / 1000); + BytesSent -= add; if (BytesSent < 0) BytesSent = 0; } } - private void AlterThrottle(int setting, ScenePresence p) - { - p.ControllingClient.SetAgentThrottleSilent((int)Throttle,setting); - } - - public int ThrottleBytes - { - get { return CapSetThrottle; } - set - { - if (value > 10000) - CapSetThrottle = value; - else - CapSetThrottle = 10000; - } - } - - internal void UpdateThrottle(int pimagethrottle, ScenePresence p) - { - // Client set throttle ! - CapSetThrottle = 2 * pimagethrottle; - ProcessTime(); - } + public int ThrottleBytes; } } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs index 0c20e0417e..b01c7dc3c1 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/GetTextureModule.cs @@ -77,8 +77,8 @@ namespace OpenSim.Region.ClientStack.Linden private Dictionary m_capsDict = new Dictionary(); private static Thread[] m_workerThreads = null; private static int m_NumberScenes = 0; - private static OpenMetaverse.BlockingQueue m_queue = - new OpenMetaverse.BlockingQueue(); + private static OpenSim.Framework.BlockingQueue m_queue = + new OpenSim.Framework.BlockingQueue(); private Dictionary m_pollservices = new Dictionary(); @@ -139,7 +139,7 @@ namespace OpenSim.Region.ClientStack.Linden m_workerThreads[i] = WorkManager.StartThread(DoTextureRequests, String.Format("GetTextureWorker{0}", i), ThreadPriority.Normal, - false, + true, false, null, int.MaxValue); @@ -220,7 +220,7 @@ namespace OpenSim.Region.ClientStack.Linden new Dictionary(); private Scene m_scene; - private CapsDataThrottler m_throttler = new CapsDataThrottler(100000, 1400000,10000); + private CapsDataThrottler m_throttler = new CapsDataThrottler(100000); public PollServiceTextureEventArgs(UUID pId, Scene scene) : base(null, "", null, null, null, pId, int.MaxValue) { @@ -231,7 +231,6 @@ namespace OpenSim.Region.ClientStack.Linden lock (responses) { bool ret = m_throttler.hasEvents(x, responses); - m_throttler.ProcessTime(); return ret; } @@ -247,6 +246,7 @@ namespace OpenSim.Region.ClientStack.Linden finally { responses.Remove(x); + m_throttler.PassTime(); } } }; @@ -263,7 +263,7 @@ namespace OpenSim.Region.ClientStack.Linden { if (responses.Count > 0) { - if (m_queue.Count >= 4) + if (m_queue.Count() >= 4) { // Never allow more than 4 fetches to wait reqinfo.send503 = true; @@ -271,6 +271,7 @@ namespace OpenSim.Region.ClientStack.Linden } } m_queue.Enqueue(reqinfo); + m_throttler.PassTime(); }; // this should never happen except possible on shutdown @@ -351,14 +352,15 @@ namespace OpenSim.Region.ClientStack.Linden }; } - m_throttler.ProcessTime(); + m_throttler.PassTime(); } internal void UpdateThrottle(int pimagethrottle) { - m_throttler.ThrottleBytes = 2 * pimagethrottle; - if(m_throttler.ThrottleBytes < 10000) - m_throttler.ThrottleBytes = 10000; + int tmp = 2 * pimagethrottle; + if(tmp < 10000) + tmp = 10000; + m_throttler.ThrottleBytes = tmp; } } @@ -415,24 +417,25 @@ namespace OpenSim.Region.ClientStack.Linden { while (true) { - aPollRequest poolreq = m_queue.Dequeue(); + aPollRequest poolreq = m_queue.Dequeue(4500); Watchdog.UpdateThread(); - poolreq.thepoll.Process(poolreq); + if(m_NumberScenes <= 0) + return; + if(poolreq.reqID != UUID.Zero) + poolreq.thepoll.Process(poolreq); } } internal sealed class CapsDataThrottler { - - private volatile int currenttime = 0; - private volatile int lastTimeElapsed = 0; + private double lastTimeElapsed = 0; private volatile int BytesSent = 0; - public CapsDataThrottler(int pBytes, int max, int min) + public CapsDataThrottler(int pBytes) { + if(pBytes < 10000) + pBytes = 10000; ThrottleBytes = pBytes; - if(ThrottleBytes < 10000) - ThrottleBytes = 10000; - lastTimeElapsed = Util.EnvironmentTickCount(); + lastTimeElapsed = Util.GetTimeStampMS(); } public bool hasEvents(UUID key, Dictionary responses) { @@ -465,20 +468,17 @@ namespace OpenSim.Region.ClientStack.Linden return haskey; } - public void ProcessTime() + public void PassTime() { - PassTime(); - } - - private void PassTime() - { - currenttime = Util.EnvironmentTickCount(); - int timeElapsed = Util.EnvironmentTickCountSubtract(currenttime, lastTimeElapsed); - //processTimeBasedActions(responses); - if (timeElapsed >= 100) + double currenttime = Util.GetTimeStampMS(); + double timeElapsed = currenttime - lastTimeElapsed; + if(timeElapsed < 50.0) + return; + int add = (int)(ThrottleBytes * timeElapsed * 0.001); + if (add >= 1000) { lastTimeElapsed = currenttime; - BytesSent -= (ThrottleBytes * timeElapsed / 1000); + BytesSent -= add; if (BytesSent < 0) BytesSent = 0; } } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs index 189fa36376..b044e564fb 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/ObjectAdd.cs @@ -121,6 +121,9 @@ namespace OpenSim.Region.ClientStack.Linden OSD r = OSDParser.DeserializeLLSDXml((string)request["requestbody"]); + if (r.Type != OSDType.Map) // not a proper req + return responsedata; + //UUID session_id = UUID.Zero; bool bypass_raycast = false; uint everyone_mask = 0; @@ -157,9 +160,6 @@ namespace OpenSim.Region.ClientStack.Linden int state = 0; int lastattach = 0; - if (r.Type != OSDType.Map) // not a proper req - return responsedata; - OSDMap rm = (OSDMap)r; if (rm.ContainsKey("ObjectData")) //v2 @@ -307,8 +307,6 @@ namespace OpenSim.Region.ClientStack.Linden } } - - Vector3 pos = m_scene.GetNewRezLocation(ray_start, ray_end, ray_target_id, rotation, (bypass_raycast) ? (byte)1 : (byte)0, (ray_end_is_intersection) ? (byte)1 : (byte)0, true, scale, false); PrimitiveBaseShape pbs = PrimitiveBaseShape.CreateBox(); @@ -359,6 +357,8 @@ namespace OpenSim.Region.ClientStack.Linden rootpart.NextOwnerMask = next_owner_mask; rootpart.Material = (byte)material; + obj.InvalidateDeepEffectivePerms(); + m_scene.PhysicsScene.AddPhysicsActorTaint(rootpart.PhysActor); responsedata["int_response_code"] = 200; //501; //410; //404; diff --git a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs index 6874662c07..116c51f5b3 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/ObjectCaps/UploadObjectAssetModule.cs @@ -335,6 +335,7 @@ namespace OpenSim.Region.ClientStack.Linden grp.AbsolutePosition = obj.Position; prim.RotationOffset = obj.Rotation; + // Required for linking grp.RootPart.ClearUpdateSchedule(); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs index b3e3ac3795..e8387e3de2 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/RegionConsoleModule.cs @@ -185,8 +185,9 @@ namespace OpenSim.Region.ClientStack.Linden protected override byte[] ProcessRequest(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader reader = new StreamReader(request); - string message = reader.ReadToEnd(); + string message; + using(StreamReader reader = new StreamReader(request)) + message = reader.ReadToEnd(); OSD osd = OSDParser.DeserializeLLSDXml(message); diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs index dfe097ef97..b406b3743a 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs @@ -63,9 +63,7 @@ namespace OpenSim.Region.ClientStack.Linden private static readonly string m_uploadBakedTexturePath = "0010/";// This is in the LandManagementModule. private Scene m_scene; - private bool m_persistBakedTextures; - private IBakedTextureModule m_BakedTextureModule; private string m_URL; public void Initialise(IConfigSource source) @@ -76,15 +74,12 @@ namespace OpenSim.Region.ClientStack.Linden m_URL = config.GetString("Cap_UploadBakedTexture", string.Empty); - IConfig appearanceConfig = source.Configs["Appearance"]; - if (appearanceConfig != null) - m_persistBakedTextures = appearanceConfig.GetBoolean("PersistBakedTextures", m_persistBakedTextures); +// IConfig appearanceConfig = source.Configs["Appearance"]; } public void AddRegion(Scene s) { m_scene = s; - } public void RemoveRegion(Scene s) @@ -92,7 +87,6 @@ namespace OpenSim.Region.ClientStack.Linden s.EventManager.OnRegisterCaps -= RegisterCaps; s.EventManager.OnNewPresence -= RegisterNewPresence; s.EventManager.OnRemovePresence -= DeRegisterPresence; - m_BakedTextureModule = null; m_scene = null; } @@ -101,7 +95,6 @@ namespace OpenSim.Region.ClientStack.Linden m_scene.EventManager.OnRegisterCaps += RegisterCaps; m_scene.EventManager.OnNewPresence += RegisterNewPresence; m_scene.EventManager.OnRemovePresence += DeRegisterPresence; - } private void DeRegisterPresence(UUID agentId) @@ -110,156 +103,12 @@ namespace OpenSim.Region.ClientStack.Linden private void RegisterNewPresence(ScenePresence presence) { -// presence.ControllingClient.OnSetAppearance += CaptureAppearanceSettings; } -/* not in use. work done in AvatarFactoryModule ValidateBakedTextureCache() and UpdateBakedTextureCache() - private void CaptureAppearanceSettings(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) - { - // if cacheItems.Length > 0 viewer is giving us current textures information. - // baked ones should had been uploaded and in assets cache as local itens - - - if (cacheItems.Length == 0) - return; // no textures information, nothing to do - - ScenePresence p = null; - if (!m_scene.TryGetScenePresence(remoteClient.AgentId, out p)) - return; // what are we doing if there is no presence to cache for? - - if (p.IsDeleted) - return; // does this really work? - - int maxCacheitemsLoop = cacheItems.Length; - if (maxCacheitemsLoop > 20) - { - maxCacheitemsLoop = AvatarWearable.MAX_WEARABLES; - m_log.WarnFormat("[CACHEDBAKES]: Too Many Cache items Provided {0}, the max is {1}. Truncating!", cacheItems.Length, AvatarWearable.MAX_WEARABLES); - } - - m_BakedTextureModule = m_scene.RequestModuleInterface(); - - - // some nice debug - m_log.Debug("[Cacheitems]: " + cacheItems.Length); - for (int iter = 0; iter < maxCacheitemsLoop; iter++) - { - m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + - cacheItems[iter].TextureID); - } - - // p.Appearance.WearableCacheItems is in memory primary cashID to textures mapper - - WearableCacheItem[] existingitems = p.Appearance.WearableCacheItems; - - if (existingitems == null) - { - if (m_BakedTextureModule != null) - { - WearableCacheItem[] savedcache = null; - try - { - if (p.Appearance.WearableCacheItemsDirty) - { - savedcache = m_BakedTextureModule.Get(p.UUID); - p.Appearance.WearableCacheItems = savedcache; - p.Appearance.WearableCacheItemsDirty = false; - } - } - - catch (Exception) - { - // The service logs a sufficient error message. - } - - - if (savedcache != null) - existingitems = savedcache; - } - } - - // Existing items null means it's a fully new appearance - if (existingitems == null) - { - for (int i = 0; i < maxCacheitemsLoop; i++) - { - if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) - { - Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex]; - if (face == null) - { - textureEntry.CreateFace(cacheItems[i].TextureIndex); - textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID = - AppearanceManager.DEFAULT_AVATAR_TEXTURE; - continue; - } - cacheItems[i].TextureID = face.TextureID; - if (m_scene.AssetService != null) - cacheItems[i].TextureAsset = - m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); - } - else - { - m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length); - } - } - } - else - { - for (int i = 0; i < maxCacheitemsLoop; i++) - { - if (textureEntry.FaceTextures.Length > cacheItems[i].TextureIndex) - { - Primitive.TextureEntryFace face = textureEntry.FaceTextures[cacheItems[i].TextureIndex]; - if (face == null) - { - textureEntry.CreateFace(cacheItems[i].TextureIndex); - textureEntry.FaceTextures[cacheItems[i].TextureIndex].TextureID = - AppearanceManager.DEFAULT_AVATAR_TEXTURE; - continue; - } - cacheItems[i].TextureID = - face.TextureID; - } - else - { - m_log.WarnFormat("[CACHEDBAKES]: Invalid Texture Index Provided, Texture doesn't exist or hasn't been uploaded yet {0}, the max is {1}. Skipping!", cacheItems[i].TextureIndex, textureEntry.FaceTextures.Length); - } - } - - for (int i = 0; i < maxCacheitemsLoop; i++) - { - if (cacheItems[i].TextureAsset == null) - { - cacheItems[i].TextureAsset = - m_scene.AssetService.GetCached(cacheItems[i].TextureID.ToString()); - } - } - } - p.Appearance.WearableCacheItems = cacheItems; - - if (m_BakedTextureModule != null) - { - m_BakedTextureModule.Store(remoteClient.AgentId, cacheItems); - p.Appearance.WearableCacheItemsDirty = true; - - } - else - p.Appearance.WearableCacheItemsDirty = false; - - for (int iter = 0; iter < maxCacheitemsLoop; iter++) - { - m_log.Debug("[CacheitemsLeaving] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + - cacheItems[iter].TextureID); - } - } - */ public void PostInitialise() { } - - public void Close() { } public string Name { get { return "UploadBakedTextureModule"; } } @@ -275,7 +124,7 @@ namespace OpenSim.Region.ClientStack.Linden if (m_URL == "localhost") { UploadBakedTextureHandler avatarhandler = new UploadBakedTextureHandler( - caps, m_scene.AssetService, m_persistBakedTextures); + caps, m_scene.AssetService); caps.RegisterHandler( "UploadBakedTexture", diff --git a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs index e0ec842c9e..8d4e561e6e 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/WebFetchInvDescModule.cs @@ -207,7 +207,7 @@ namespace OpenSim.Region.ClientStack.Linden m_workerThreads[i] = WorkManager.StartThread(DoInventoryRequests, String.Format("InventoryWorkerThread{0}", i), ThreadPriority.Normal, - false, + true, true, null, int.MaxValue); @@ -443,10 +443,9 @@ namespace OpenSim.Region.ClientStack.Linden { while (true) { + aPollRequest poolreq = m_queue.Dequeue(4500); Watchdog.UpdateThread(); - aPollRequest poolreq = m_queue.Dequeue(5000); - if (poolreq != null && poolreq.thepoll != null) { try @@ -456,7 +455,7 @@ namespace OpenSim.Region.ClientStack.Linden catch (Exception e) { m_log.ErrorFormat( - "[INVENTORY]: Failed to process queued inventory request {0} for {1}. Exception {3}", + "[INVENTORY]: Failed to process queued inventory request {0} for {1}. Exception {2}", poolreq.reqID, poolreq.presence != null ? poolreq.presence.Name : "unknown", e); } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index df3466815b..6dd38856bc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -62,7 +62,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Handles new client connections /// Constructor takes a single Packet and authenticates everything /// - public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector + public class LLClientView : IClientAPI, IClientCore, IClientIM, IClientChat, IClientInventory, IStatsCollector, IClientIPEndpoint { /// /// Debug packet level. See OpenSim.RegisterConsoleCommands() for more details. @@ -325,6 +325,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public LLImageManager ImageManager { get; private set; } + public JobEngine m_asyncPacketProcess; private readonly LLUDPServer m_udpServer; private readonly LLUDPClient m_udpClient; private readonly UUID m_sessionId; @@ -378,7 +379,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected Scene m_scene; protected string m_firstName; protected string m_lastName; - protected Thread m_clientThread; protected Vector3 m_startpos; protected UUID m_activeGroupID; protected string m_activeGroupName = String.Empty; @@ -529,7 +529,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_prioritizer = new Prioritizer(m_scene); RegisterLocalPacketHandlers(); - + string name = string.Format("AsyncInUDP-{0}",m_agentId.ToString()); + m_asyncPacketProcess = new JobEngine(name, name, 10000); IsActive = true; } @@ -592,6 +593,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (OnConnectionClosed != null) OnConnectionClosed(this); + m_asyncPacketProcess.Stop(); // Flush all of the packets out of the UDP server for this client if (m_udpServer != null) @@ -703,29 +705,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// true if the handler was added. This is currently always the case. public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync) - { - return AddLocalPacketHandler(packetType, handler, doAsync, false); - } - - /// - /// Add a handler for the given packet type. - /// - /// - /// - /// - /// If true, when the packet is received handle it on a different thread. Whether this is given direct to - /// a threadpool thread or placed in a queue depends on the inEngine parameter. - /// - /// - /// If async is false then this parameter is ignored. - /// If async is true and inEngine is false, then the packet is sent directly to a - /// threadpool thread. - /// If async is true and inEngine is true, then the packet is sent to the IncomingPacketAsyncHandlingEngine. - /// This may result in slower handling but reduces the risk of overloading the simulator when there are many - /// simultaneous async requests. - /// - /// true if the handler was added. This is currently always the case. - public bool AddLocalPacketHandler(PacketType packetType, PacketMethod handler, bool doAsync, bool inEngine) { bool result = false; lock (m_packetHandlers) @@ -733,7 +712,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!m_packetHandlers.ContainsKey(packetType)) { m_packetHandlers.Add( - packetType, new PacketProcessor() { method = handler, Async = doAsync, InEngine = inEngine }); + packetType, new PacketProcessor() { method = handler, Async = doAsync}); result = true; } } @@ -768,30 +747,16 @@ namespace OpenSim.Region.ClientStack.LindenUDP PacketProcessor pprocessor; if (m_packetHandlers.TryGetValue(packet.Type, out pprocessor)) { - ClientInfo cinfo = UDPClient.GetClientInfo(); //there is a local handler for this packet type if (pprocessor.Async) { - if (!cinfo.AsyncRequests.ContainsKey(packet.Type.ToString())) - cinfo.AsyncRequests[packet.Type.ToString()] = 0; - cinfo.AsyncRequests[packet.Type.ToString()]++; - object obj = new AsyncPacketProcess(this, pprocessor.method, packet); - - if (pprocessor.InEngine) - m_udpServer.IpahEngine.QueueJob(packet.Type.ToString(), () => ProcessSpecificPacketAsync(obj)); - else - Util.FireAndForget(ProcessSpecificPacketAsync, obj, packet.Type.ToString()); - + m_asyncPacketProcess.QueueJob(packet.Type.ToString(), () => ProcessSpecificPacketAsync(obj)); result = true; } else { - if (!cinfo.SyncRequests.ContainsKey(packet.Type.ToString())) - cinfo.SyncRequests[packet.Type.ToString()] = 0; - cinfo.SyncRequests[packet.Type.ToString()]++; - result = pprocessor.method(this, packet); } } @@ -806,11 +771,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP } if (found) { - ClientInfo cinfo = UDPClient.GetClientInfo(); - if (!cinfo.GenericRequests.ContainsKey(packet.Type.ToString())) - cinfo.GenericRequests[packet.Type.ToString()] = 0; - cinfo.GenericRequests[packet.Type.ToString()]++; - result = method(this, packet); } } @@ -841,6 +801,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { + m_asyncPacketProcess.Start(); m_scene.AddNewAgent(this, PresenceType.User); // RefreshGroupMembership(); @@ -3111,10 +3072,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP public void SendParcelInfo(RegionInfo info, LandData land, UUID parcelID, uint x, uint y) { - float dwell = 0.0f; - IDwellModule dwellModule = m_scene.RequestModuleInterface(); - if (dwellModule != null) - dwell = dwellModule.GetDwell(land.GlobalID); ParcelInfoReplyPacket reply = (ParcelInfoReplyPacket)PacketPool.Instance.GetPacket(PacketType.ParcelInfoReply); reply.AgentData.AgentID = m_agentId; reply.Data.ParcelID = parcelID; @@ -3141,7 +3098,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP reply.Data.GlobalZ = pos.Z; reply.Data.SimName = Utils.StringToBytes(info.RegionName); reply.Data.SnapshotID = land.SnapshotID; - reply.Data.Dwell = dwell; + reply.Data.Dwell = land.Dwell; reply.Data.SalePrice = land.SalePrice; reply.Data.AuctionID = (int)land.AuctionID; @@ -3950,24 +3907,68 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// /// Send an ObjectUpdate packet with information about an avatar /// - public void SendAvatarDataImmediate(ISceneEntity avatar) + public void SendEntityFullUpdateImmediate(ISceneEntity ent) { // m_log.DebugFormat( // "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", // avatar.Name, avatar.UUID, Name, AgentId); - ScenePresence presence = avatar as ScenePresence; - if (presence == null) + if (ent == null) return; ObjectUpdatePacket objupdate = (ObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ObjectUpdate); objupdate.Header.Zerocoded = true; - objupdate.RegionData.RegionHandle = presence.RegionHandle; -// objupdate.RegionData.TimeDilation = ushort.MaxValue; objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); objupdate.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; - objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); + + if(ent is ScenePresence) + { + ScenePresence presence = ent as ScenePresence; + objupdate.RegionData.RegionHandle = presence.RegionHandle; + objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); + } + else if(ent is SceneObjectPart) + { + SceneObjectPart part = ent as SceneObjectPart; + objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + objupdate.ObjectData[0] = CreatePrimUpdateBlock(part, (ScenePresence)SceneAgent); + } + + OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); + + // We need to record the avatar local id since the root prim of an attachment points to this. +// m_attachmentsSent.Add(avatar.LocalId); + } + + public void SendEntityTerseUpdateImmediate(ISceneEntity ent) + { +// m_log.DebugFormat( +// "[LLCLIENTVIEW]: Sending immediate object update for avatar {0} {1} to {2} {3}", +// avatar.Name, avatar.UUID, Name, AgentId); + + if (ent == null) + return; + + ImprovedTerseObjectUpdatePacket objupdate = + (ImprovedTerseObjectUpdatePacket)PacketPool.Instance.GetPacket(PacketType.ImprovedTerseObjectUpdate); + objupdate.Header.Zerocoded = true; + + objupdate.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); + objupdate.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + + if(ent is ScenePresence) + { + ScenePresence presence = ent as ScenePresence; + objupdate.RegionData.RegionHandle = presence.RegionHandle; + objupdate.ObjectData[0] = CreateImprovedTerseBlock(ent, false); + } + else if(ent is SceneObjectPart) + { + SceneObjectPart part = ent as SceneObjectPart; + objupdate.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + objupdate.ObjectData[0] = CreateImprovedTerseBlock(ent, false); + } OutPacket(objupdate, ThrottleOutPacketType.Task | ThrottleOutPacketType.HighPriority); @@ -4021,7 +4022,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP #region Primitive Packet/Data Sending Methods - /// /// Generate one of the object update packets based on PrimUpdateFlags /// and broadcast the packet to clients @@ -4044,10 +4044,20 @@ namespace OpenSim.Region.ClientStack.LindenUDP */ if (entity is SceneObjectPart) { - SceneObjectPart e = (SceneObjectPart)entity; - SceneObjectGroup g = e.ParentGroup; + SceneObjectPart p = (SceneObjectPart)entity; + SceneObjectGroup g = p.ParentGroup; if (g.HasPrivateAttachmentPoint && g.OwnerID != AgentId) return; // Don't send updates for other people's HUDs + + if((updateFlags ^ PrimUpdateFlags.SendInTransit) == 0) + { + List partIDs = (new List {p.LocalId}); + lock (m_entityProps.SyncRoot) + m_entityProps.Remove(partIDs); + lock (m_entityUpdates.SyncRoot) + m_entityUpdates.Remove(partIDs); + return; + } } //double priority = m_prioritizer.GetUpdatePriority(this, entity); @@ -4126,20 +4136,34 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Vector3 mycamera = Vector3.Zero; Vector3 mypos = Vector3.Zero; ScenePresence mysp = (ScenePresence)SceneAgent; - if(mysp != null && !mysp.IsDeleted) + + bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; + // we should have a presence + if(mysp == null) + return; + + if(doCulling) { cullingrange = mysp.DrawDistance + m_scene.ReprioritizationDistance + 16f; // mycamera = mysp.CameraPosition; mypos = mysp.AbsolutePosition; } - else - doCulling = false; while (maxUpdatesBytes > 0) { lock (m_entityUpdates.SyncRoot) - if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) - break; + { + if(orderedDequeue) + { + if (!m_entityUpdates.TryOrderedDequeue(out update, out timeinqueue)) + break; + } + else + { + if (!m_entityUpdates.TryDequeue(out update, out timeinqueue)) + break; + } + } PrimUpdateFlags updateFlags = (PrimUpdateFlags)update.Flags; @@ -4154,9 +4178,15 @@ namespace OpenSim.Region.ClientStack.LindenUDP { SceneObjectPart part = (SceneObjectPart)update.Entity; SceneObjectGroup grp = part.ParentGroup; - if (grp.inTransit) + if (grp.inTransit && !update.Flags.HasFlag(PrimUpdateFlags.SendInTransit)) continue; +/* debug + if (update.Flags.HasFlag(PrimUpdateFlags.SendInTransit)) + { + + } +*/ if (grp.IsDeleted) { // Don't send updates for objects that have been marked deleted. @@ -4213,14 +4243,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP { part.Shape.LightEntry = false; } - - if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh)) - { - // Ensure that mesh has at least 8 valid faces - part.Shape.ProfileBegin = 12500; - part.Shape.ProfileEnd = 0; - part.Shape.ProfileHollow = 27500; - } } if(doCulling && !grp.IsAttachment) @@ -4248,14 +4270,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP continue; } } - - if (part.Shape != null && (part.Shape.SculptType == (byte)SculptType.Mesh)) - { - // Ensure that mesh has at least 8 valid faces - part.Shape.ProfileBegin = 12500; - part.Shape.ProfileEnd = 0; - part.Shape.ProfileHollow = 27500; - } } else if (update.Entity is ScenePresence) { @@ -4330,7 +4344,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (update.Entity is ScenePresence) ablock = CreateAvatarUpdateBlock((ScenePresence)update.Entity); else - ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId); + ablock = CreatePrimUpdateBlock((SceneObjectPart)update.Entity, mysp); objectUpdateBlocks.Add(ablock); objectUpdates.Value.Add(update); maxUpdatesBytes -= ablock.Length; @@ -4462,6 +4476,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } // hack.. dont use +/* public void SendPartFullUpdate(ISceneEntity ent, uint? parentID) { if (ent is SceneObjectPart) @@ -4472,7 +4487,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP packet.RegionData.TimeDilation = Utils.FloatToUInt16(m_scene.TimeDilation, 0.0f, 1.0f); packet.ObjectData = new ObjectUpdatePacket.ObjectDataBlock[1]; - ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, this.m_agentId); + ObjectUpdatePacket.ObjectDataBlock blk = CreatePrimUpdateBlock(part, mysp); if (parentID.HasValue) { blk.ParentID = parentID.Value; @@ -4488,7 +4503,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // updatesThisCall, Name, SceneAgent.IsChildAgent ? "child" : "root", Scene.Name); // } - +*/ public void ReprioritizeUpdates() { lock (m_entityUpdates.SyncRoot) @@ -4846,6 +4861,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP // OpenSim.Framework.Lazy> propertyUpdates = // new OpenSim.Framework.Lazy>(); + bool orderedDequeue = m_scene.UpdatePrioritizationScheme == UpdatePrioritizationSchemes.SimpleAngularDistance; EntityUpdate iupdate; Int32 timeinqueue; // this is just debugging code & can be dropped later @@ -4853,8 +4869,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP while (maxUpdateBytes > 0) { lock (m_entityProps.SyncRoot) - if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) - break; + { + if(orderedDequeue) + { + if (!m_entityProps.TryOrderedDequeue(out iupdate, out timeinqueue)) + break; + } + else + { + if (!m_entityProps.TryDequeue(out iupdate, out timeinqueue)) + break; + } + } ObjectPropertyUpdate update = (ObjectPropertyUpdate)iupdate; if (update.SendFamilyProps) @@ -5522,6 +5548,26 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion #region Helper Methods + private void ClampVectorForUint(ref Vector3 v, float max) + { + float a,b; + + a = Math.Abs(v.X); + b = Math.Abs(v.Y); + if(b > a) + a = b; + b= Math.Abs(v.Z); + if(b > a) + a = b; + + if (a > max) + { + a = max / a; + v.X *= a; + v.Y *= a; + v.Z *= a; + } + } protected ImprovedTerseObjectUpdatePacket.ObjectDataBlock CreateImprovedTerseBlock(ISceneEntity entity, bool sendTexture) { @@ -5612,11 +5658,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP pos += 12; // Velocity + ClampVectorForUint(ref velocity, 128f); Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.X, -128.0f, 128.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Y, -128.0f, 128.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(velocity.Z, -128.0f, 128.0f), data, pos); pos += 2; // Acceleration + ClampVectorForUint(ref acceleration, 64f); Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.X, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Y, -64.0f, 64.0f), data, pos); pos += 2; Utils.UInt16ToBytes(Utils.FloatToUInt16(acceleration.Z, -64.0f, 64.0f), data, pos); pos += 2; @@ -5628,6 +5676,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP Utils.UInt16ToBytes(Utils.FloatToUInt16(rotation.W, -1.0f, 1.0f), data, pos); pos += 2; // Angular Velocity + ClampVectorForUint(ref angularVelocity, 64f); Utils.UInt16ToBytes(Utils.FloatToUInt16(angularVelocity.X, -64.0f, 64.0f), data, pos); pos += 2; 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; @@ -5726,29 +5775,29 @@ namespace OpenSim.Region.ClientStack.LindenUDP return update; } - protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) +// protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart data, UUID recipientID) + protected ObjectUpdatePacket.ObjectDataBlock CreatePrimUpdateBlock(SceneObjectPart part, ScenePresence sp) { byte[] objectData = new byte[60]; - data.RelativePosition.ToBytes(objectData, 0); - data.Velocity.ToBytes(objectData, 12); - data.Acceleration.ToBytes(objectData, 24); + part.RelativePosition.ToBytes(objectData, 0); + part.Velocity.ToBytes(objectData, 12); + part.Acceleration.ToBytes(objectData, 24); - Quaternion rotation = data.RotationOffset; + Quaternion rotation = part.RotationOffset; rotation.Normalize(); rotation.ToBytes(objectData, 36); - data.AngularVelocity.ToBytes(objectData, 48); + part.AngularVelocity.ToBytes(objectData, 48); ObjectUpdatePacket.ObjectDataBlock update = new ObjectUpdatePacket.ObjectDataBlock(); - update.ClickAction = (byte)data.ClickAction; + update.ClickAction = (byte)part.ClickAction; update.CRC = 0; - update.ExtraParams = data.Shape.ExtraParams ?? Utils.EmptyBytes; - update.FullID = data.UUID; - update.ID = data.LocalId; + update.ExtraParams = part.Shape.ExtraParams ?? Utils.EmptyBytes; + update.FullID = part.UUID; + update.ID = part.LocalId; //update.JointAxisOrAnchor = Vector3.Zero; // These are deprecated //update.JointPivot = Vector3.Zero; //update.JointType = 0; - update.Material = data.Material; - update.MediaURL = Utils.EmptyBytes; // FIXME: Support this in OpenSim + update.Material = part.Material; /* if (data.ParentGroup.IsAttachment) { @@ -5776,68 +5825,74 @@ namespace OpenSim.Region.ClientStack.LindenUDP } */ - if (data.ParentGroup.IsAttachment) + if (part.ParentGroup.IsAttachment) { - if (data.IsRoot) + if (part.IsRoot) { - update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + data.ParentGroup.FromItemID); + update.NameValue = Util.StringToBytes256("AttachItemID STRING RW SV " + part.ParentGroup.FromItemID); } else update.NameValue = Utils.EmptyBytes; - int st = (int)data.ParentGroup.AttachmentPoint; + int st = (int)part.ParentGroup.AttachmentPoint; update.State = (byte)(((st & 0xf0) >> 4) + ((st & 0x0f) << 4)); ; } else { update.NameValue = Utils.EmptyBytes; - update.State = data.Shape.State; // not sure about this + update.State = part.Shape.State; // not sure about this } update.ObjectData = objectData; - update.ParentID = data.ParentID; - update.PathBegin = data.Shape.PathBegin; - update.PathCurve = data.Shape.PathCurve; - update.PathEnd = data.Shape.PathEnd; - update.PathRadiusOffset = data.Shape.PathRadiusOffset; - update.PathRevolutions = data.Shape.PathRevolutions; - update.PathScaleX = data.Shape.PathScaleX; - update.PathScaleY = data.Shape.PathScaleY; - update.PathShearX = data.Shape.PathShearX; - update.PathShearY = data.Shape.PathShearY; - update.PathSkew = data.Shape.PathSkew; - update.PathTaperX = data.Shape.PathTaperX; - update.PathTaperY = data.Shape.PathTaperY; - update.PathTwist = data.Shape.PathTwist; - update.PathTwistBegin = data.Shape.PathTwistBegin; - update.PCode = data.Shape.PCode; - update.ProfileBegin = data.Shape.ProfileBegin; - update.ProfileCurve = data.Shape.ProfileCurve; - update.ProfileEnd = data.Shape.ProfileEnd; - update.ProfileHollow = data.Shape.ProfileHollow; - update.PSBlock = data.ParticleSystem ?? Utils.EmptyBytes; - update.TextColor = data.GetTextColor().GetBytes(false); - update.TextureAnim = data.TextureAnimation ?? Utils.EmptyBytes; - update.TextureEntry = data.Shape.TextureEntry ?? Utils.EmptyBytes; - update.Scale = data.Shape.Scale; - update.Text = Util.StringToBytes256(data.Text); - update.MediaURL = Util.StringToBytes256(data.MediaUrl); + update.ParentID = part.ParentID; + update.PathBegin = part.Shape.PathBegin; + update.PathCurve = part.Shape.PathCurve; + update.PathEnd = part.Shape.PathEnd; + update.PathRadiusOffset = part.Shape.PathRadiusOffset; + update.PathRevolutions = part.Shape.PathRevolutions; + update.PathScaleX = part.Shape.PathScaleX; + update.PathScaleY = part.Shape.PathScaleY; + update.PathShearX = part.Shape.PathShearX; + update.PathShearY = part.Shape.PathShearY; + update.PathSkew = part.Shape.PathSkew; + update.PathTaperX = part.Shape.PathTaperX; + update.PathTaperY = part.Shape.PathTaperY; + update.PathTwist = part.Shape.PathTwist; + update.PathTwistBegin = part.Shape.PathTwistBegin; + update.PCode = part.Shape.PCode; + update.ProfileBegin = part.Shape.ProfileBegin; + update.ProfileCurve = part.Shape.ProfileCurve; + + if(part.Shape.SculptType == (byte)SculptType.Mesh) // filter out hack + update.ProfileCurve = (byte)(part.Shape.ProfileCurve & 0x0f); + else + update.ProfileCurve = part.Shape.ProfileCurve; + + update.ProfileEnd = part.Shape.ProfileEnd; + update.ProfileHollow = part.Shape.ProfileHollow; + update.PSBlock = part.ParticleSystem ?? Utils.EmptyBytes; + update.TextColor = part.GetTextColor().GetBytes(false); + update.TextureAnim = part.TextureAnimation ?? Utils.EmptyBytes; + update.TextureEntry = part.Shape.TextureEntry ?? Utils.EmptyBytes; + update.Scale = part.Shape.Scale; + update.Text = Util.StringToBytes(part.Text, 255); + update.MediaURL = Util.StringToBytes(part.MediaUrl, 255); #region PrimFlags - PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(recipientID, data.UUID); + PrimFlags flags = (PrimFlags)m_scene.Permissions.GenerateClientFlags(part, sp); // Don't send the CreateSelected flag to everyone flags &= ~PrimFlags.CreateSelected; - if (recipientID == data.OwnerID) + if (sp.UUID == part.OwnerID) { - if (data.CreateSelected) + if (part.CreateSelected) { // Only send this flag once, then unset it flags |= PrimFlags.CreateSelected; - data.CreateSelected = false; + part.CreateSelected = false; } } @@ -5849,21 +5904,21 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion PrimFlags - if (data.Sound != UUID.Zero) + if (part.Sound != UUID.Zero) { - update.Sound = data.Sound; - update.OwnerID = data.OwnerID; - update.Gain = (float)data.SoundGain; - update.Radius = (float)data.SoundRadius; - update.Flags = data.SoundFlags; + update.Sound = part.Sound; + update.OwnerID = part.OwnerID; + update.Gain = (float)part.SoundGain; + update.Radius = (float)part.SoundRadius; + update.Flags = part.SoundFlags; } - switch ((PCode)data.Shape.PCode) + switch ((PCode)part.Shape.PCode) { case PCode.Grass: case PCode.Tree: case PCode.NewTree: - update.Data = new byte[] { data.Shape.State }; + update.Data = new byte[] { part.Shape.State }; break; default: update.Data = Utils.EmptyBytes; @@ -5941,10 +5996,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.ParcelBuy, HandleParcelBuyRequest, false); AddLocalPacketHandler(PacketType.UUIDGroupNameRequest, HandleUUIDGroupNameRequest); AddLocalPacketHandler(PacketType.ObjectGroup, HandleObjectGroupRequest); - AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage, true, true); - AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest, true, true); + AddLocalPacketHandler(PacketType.GenericMessage, HandleGenericMessage); + AddLocalPacketHandler(PacketType.AvatarPropertiesRequest, HandleAvatarPropertiesRequest); AddLocalPacketHandler(PacketType.ChatFromViewer, HandleChatFromViewer); - AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate, true, true); + AddLocalPacketHandler(PacketType.AvatarPropertiesUpdate, HandlerAvatarPropertiesUpdate); AddLocalPacketHandler(PacketType.ScriptDialogReply, HandlerScriptDialogReply); AddLocalPacketHandler(PacketType.ImprovedInstantMessage, HandlerImprovedInstantMessage); AddLocalPacketHandler(PacketType.AcceptFriendship, HandlerAcceptFriendship); @@ -6131,8 +6186,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP AddLocalPacketHandler(PacketType.PickDelete, HandlePickDelete); AddLocalPacketHandler(PacketType.PickGodDelete, HandlePickGodDelete); AddLocalPacketHandler(PacketType.PickInfoUpdate, HandlePickInfoUpdate); - AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate, true, true); - AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate, true, true); + AddLocalPacketHandler(PacketType.AvatarNotesUpdate, HandleAvatarNotesUpdate); + AddLocalPacketHandler(PacketType.AvatarInterestsUpdate, HandleAvatarInterestsUpdate); AddLocalPacketHandler(PacketType.GrantUserRights, HandleGrantUserRights); AddLocalPacketHandler(PacketType.PlacesQuery, HandlePlacesQuery); AddLocalPacketHandler(PacketType.UpdateMuteListEntry, HandleUpdateMuteListEntry); @@ -6223,20 +6278,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// private bool CheckAgentCameraUpdateSignificance(AgentUpdatePacket.AgentDataBlock x) { - float vdelta = Vector3.Distance(x.CameraAtAxis, m_thisAgentUpdateArgs.CameraAtAxis); - if((vdelta > VDELTA)) - return true; + if(Math.Abs(x.CameraCenter.X - m_thisAgentUpdateArgs.CameraCenter.X) > VDELTA || + Math.Abs(x.CameraCenter.Y - m_thisAgentUpdateArgs.CameraCenter.Y) > VDELTA || + Math.Abs(x.CameraCenter.Z - m_thisAgentUpdateArgs.CameraCenter.Z) > VDELTA || - vdelta = Vector3.Distance(x.CameraCenter, m_thisAgentUpdateArgs.CameraCenter); - if((vdelta > VDELTA)) - return true; + Math.Abs(x.CameraAtAxis.X - m_thisAgentUpdateArgs.CameraAtAxis.X) > VDELTA || + Math.Abs(x.CameraAtAxis.Y - m_thisAgentUpdateArgs.CameraAtAxis.Y) > VDELTA || +// Math.Abs(x.CameraAtAxis.Z - m_thisAgentUpdateArgs.CameraAtAxis.Z) > VDELTA || - vdelta = Vector3.Distance(x.CameraLeftAxis, m_thisAgentUpdateArgs.CameraLeftAxis); - if((vdelta > VDELTA)) - return true; + Math.Abs(x.CameraLeftAxis.X - m_thisAgentUpdateArgs.CameraLeftAxis.X) > VDELTA || + Math.Abs(x.CameraLeftAxis.Y - m_thisAgentUpdateArgs.CameraLeftAxis.Y) > VDELTA || +// Math.Abs(x.CameraLeftAxis.Z - m_thisAgentUpdateArgs.CameraLeftAxis.Z) > VDELTA || - vdelta = Vector3.Distance(x.CameraUpAxis, m_thisAgentUpdateArgs.CameraUpAxis); - if((vdelta > VDELTA)) + Math.Abs(x.CameraUpAxis.X - m_thisAgentUpdateArgs.CameraUpAxis.X) > VDELTA || + Math.Abs(x.CameraUpAxis.Y - m_thisAgentUpdateArgs.CameraUpAxis.Y) > VDELTA +// Math.Abs(x.CameraLeftAxis.Z - m_thisAgentUpdateArgs.CameraLeftAxis.Z) > VDELTA || + ) return true; return false; @@ -6342,6 +6399,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP ParcelGodMarkAsContentPacket ParcelGodMarkAsContent = (ParcelGodMarkAsContentPacket)Packet; + if(SessionId != ParcelGodMarkAsContent.AgentData.SessionID || AgentId != ParcelGodMarkAsContent.AgentData.AgentID) + return false; + ParcelGodMark ParcelGodMarkAsContentHandler = OnParcelGodMark; if (ParcelGodMarkAsContentHandler != null) { @@ -6357,6 +6417,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP { FreezeUserPacket FreezeUser = (FreezeUserPacket)Packet; + if(SessionId != FreezeUser.AgentData.SessionID || AgentId != FreezeUser.AgentData.AgentID) + return false; + FreezeUserUpdate FreezeUserHandler = OnParcelFreezeUser; if (FreezeUserHandler != null) { @@ -6374,6 +6437,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP EjectUserPacket EjectUser = (EjectUserPacket)Packet; + if(SessionId != EjectUser.AgentData.SessionID || AgentId != EjectUser.AgentData.AgentID) + return false; + EjectUserUpdate EjectUserHandler = OnParcelEjectUser; if (EjectUserHandler != null) { @@ -6391,6 +6457,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP ParcelBuyPassPacket ParcelBuyPass = (ParcelBuyPassPacket)Packet; + if(SessionId != ParcelBuyPass.AgentData.SessionID || AgentId != ParcelBuyPass.AgentData.AgentID) + return false; + ParcelBuyPass ParcelBuyPassHandler = OnParcelBuyPass; if (ParcelBuyPassHandler != null) { @@ -6423,8 +6492,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool HandleUUIDGroupNameRequest(IClientAPI sender, Packet Pack) { - UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; + ScenePresence sp = (ScenePresence)SceneAgent; + if(sp == null || sp.IsDeleted || (sp.IsInTransit && !sp.IsInLocalTransit)) + return true; + UUIDGroupNameRequestPacket upack = (UUIDGroupNameRequestPacket)Pack; for (int i = 0; i < upack.UUIDNameBlock.Length; i++) { @@ -7443,7 +7515,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP SendUserInfoReply(false, true, ""); } return true; - } private bool HandleUpdateUserInfo(IClientAPI sender, Packet Pack) @@ -7753,10 +7824,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP ObjectDuplicate handlerObjectDuplicate = null; - for (int i = 0; i < dupe.ObjectData.Length; i++) + handlerObjectDuplicate = OnObjectDuplicate; + if (handlerObjectDuplicate != null) { - handlerObjectDuplicate = OnObjectDuplicate; - if (handlerObjectDuplicate != null) + for (int i = 0; i < dupe.ObjectData.Length; i++) { UUID rezGroupID = dupe.AgentData.GroupID; if(!IsGroupMember(rezGroupID)) @@ -7978,19 +8049,41 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } + Dictionary objImageSeqs = null; + double lastobjImageSeqsMS = 0.0; + private bool HandleObjectImage(IClientAPI sender, Packet Pack) { ObjectImagePacket imagePack = (ObjectImagePacket)Pack; - UpdatePrimTexture handlerUpdatePrimTexture = null; + UpdatePrimTexture handlerUpdatePrimTexture = OnUpdatePrimTexture; + if (handlerUpdatePrimTexture == null) + return true; + + double now = Util.GetTimeStampMS(); + if(objImageSeqs == null || ( now - lastobjImageSeqsMS > 30000.0)) + { + objImageSeqs = null; // yeah i know superstition... + objImageSeqs = new Dictionary(16); + } + + lastobjImageSeqsMS = now; + uint seq = Pack.Header.Sequence; + uint id; + uint lastseq; + + ObjectImagePacket.ObjectDataBlock o; for (int i = 0; i < imagePack.ObjectData.Length; i++) { - handlerUpdatePrimTexture = OnUpdatePrimTexture; - if (handlerUpdatePrimTexture != null) - { - handlerUpdatePrimTexture(imagePack.ObjectData[i].ObjectLocalID, - imagePack.ObjectData[i].TextureEntry, this); - } + o = imagePack.ObjectData[i]; + id = o.ObjectLocalID; + if(objImageSeqs.TryGetValue(id, out lastseq)) + { + if(seq <= lastseq) + continue; + } + objImageSeqs[id] = seq; + handlerUpdatePrimTexture(id, o.TextureEntry, this); } return true; } @@ -9598,6 +9691,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP private bool HandleUUIDNameRequest(IClientAPI sender, Packet Pack) { + ScenePresence sp = (ScenePresence)SceneAgent; + if(sp == null || sp.IsDeleted || (sp.IsInTransit && !sp.IsInLocalTransit)) + return true; + UUIDNameRequestPacket incoming = (UUIDNameRequestPacket)Pack; foreach (UUIDNameRequestPacket.UUIDNameBlockBlock UUIDBlock in incoming.UUIDNameBlock) @@ -12515,11 +12612,11 @@ namespace OpenSim.Region.ClientStack.LindenUDP } int maxWearablesLoop = cachedtex.WearableData.Length; - if (maxWearablesLoop > cacheItems.Length) - maxWearablesLoop = cacheItems.Length; if (cacheItems != null) { + if (maxWearablesLoop > cacheItems.Length) + maxWearablesLoop = cacheItems.Length; for (int i = 0; i < maxWearablesLoop; i++) { int idx = cachedtex.WearableData[i].TextureIndex; @@ -13354,7 +13451,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP SendAssetNotFound(req); return; } - } if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) @@ -13431,11 +13527,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// public bool Async { get; set; } - /// - /// If async is true, should this packet be handled in the async engine or given directly to a threadpool - /// thread? - /// - public bool InEngine { get; set; } } public class AsyncPacketProcess diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs index ec51e28488..b575ed9448 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLUDPServer.cs @@ -312,9 +312,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// stack. Use zero to leave this value as the default protected int m_recvBufferSize; - /// Flag to process packets asynchronously or synchronously - protected bool m_asyncPacketHandling; - /// Tracks whether or not a packet was sent each round so we know /// whether or not to sleep protected bool m_packetSent; @@ -417,7 +414,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// Queue some low priority but potentially high volume async requests so that they don't overwhelm available /// threadpool threads. /// - public JobEngine IpahEngine { get; protected set; } +// public JobEngine IpahEngine { get; protected set; } /// /// Run queue empty processing within a single persistent thread. @@ -473,7 +470,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP IConfig config = configSource.Configs["ClientStack.LindenUDP"]; if (config != null) { - m_asyncPacketHandling = config.GetBoolean("async_packet_handling", true); m_recvBufferSize = config.GetInt("client_socket_rcvbuf_size", 0); sceneThrottleBps = config.GetInt("scene_throttle_max_bps", 0); @@ -531,7 +527,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { StartInbound(); StartOutbound(); - IpahEngine.Start(); +// IpahEngine.Start(); OqrEngine.Start(); m_elapsedMSSinceLastStatReport = Environment.TickCount; @@ -540,10 +536,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP public 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 inbound packet processing for the LLUDP server"); - base.StartInbound(m_recvBufferSize, m_asyncPacketHandling); + base.StartInbound(m_recvBufferSize); // This thread will process the packets received that are placed on the packetInbox WorkManager.StartThread( @@ -577,7 +572,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_log.Info("[LLUDPSERVER]: Shutting down the LLUDP server for " + Scene.Name); base.StopOutbound(); base.StopInbound(); - IpahEngine.Stop(); +// IpahEngine.Stop(); OqrEngine.Stop(); } @@ -696,12 +691,12 @@ namespace OpenSim.Region.ClientStack.LindenUDP Scene = (Scene)scene; m_location = new Location(Scene.RegionInfo.RegionHandle); - +/* IpahEngine = new JobEngine( string.Format("Incoming Packet Async Handling Engine ({0})", Scene.Name), "INCOMING PACKET ASYNC HANDLING ENGINE"); - +*/ OqrEngine = new JobEngine( string.Format("Outgoing Queue Refill Engine ({0})", Scene.Name), @@ -786,7 +781,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP MeasuresOfInterest.AverageChangeOverTime, stat => stat.Value = GetTotalQueuedOutgoingPackets(), StatVerbosity.Info)); - +/* StatsManager.RegisterStat( new Stat( "IncomingPacketAsyncRequestsWaiting", @@ -799,7 +794,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP MeasuresOfInterest.None, stat => stat.Value = IpahEngine.JobsWaiting, StatVerbosity.Debug)); - +*/ StatsManager.RegisterStat( new Stat( "OQRERequestsWaiting", @@ -1227,7 +1222,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP outgoingPacket.SequenceNumber, isReliable, isResend, udpClient.AgentID, Scene.Name); // Put the UDP payload on the wire - AsyncBeginSend(buffer); +// AsyncBeginSend(buffer); + SyncSend(buffer); // Keep track of when this packet was sent out (right now) outgoingPacket.TickCount = Environment.TickCount & Int32.MaxValue; @@ -1912,7 +1908,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP Buffer.BlockCopy(packetData, 0, buffer.Data, 0, length); - AsyncBeginSend(buffer); +// AsyncBeginSend(buffer); + SyncSend(buffer); } protected bool IsClientAuthorized(UseCircuitCodePacket useCircuitCode, out AuthenticateResponse sessionInfo) diff --git a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs index 35a07111df..8dd96d65d6 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/OpenSimUDPBase.cs @@ -57,9 +57,6 @@ namespace OpenMetaverse /// UDP socket, used in either client or server mode private Socket m_udpSocket; - /// Flag to process packets asynchronously or synchronously - private bool m_asyncPacketHandling; - /// /// Are we to use object pool(s) to reduce memory churn when receiving data? /// @@ -205,10 +202,8 @@ 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 virtual void StartInbound(int recvBufferSize, bool asyncPacketHandling) + public virtual void StartInbound(int recvBufferSize) { - m_asyncPacketHandling = asyncPacketHandling; - if (!IsRunningInbound) { m_log.DebugFormat("[UDPBASE]: Starting inbound UDP loop"); @@ -407,12 +402,7 @@ namespace OpenMetaverse if (IsRunningInbound) { UdpReceives++; - - // Asynchronous mode will start another receive before the - // callback for this packet is even fired. Very parallel :-) - if (m_asyncPacketHandling) - AsyncBeginReceive(); - + try { // get the buffer that was created in AsyncBeginReceive @@ -469,10 +459,7 @@ namespace OpenMetaverse // if (UsePools) // Pool.ReturnObject(buffer); - // Synchronous mode waits until the packet callback completes - // before starting the receive to fetch another packet - if (!m_asyncPacketHandling) - AsyncBeginReceive(); + AsyncBeginReceive(); } } } @@ -500,7 +487,7 @@ namespace OpenMetaverse } catch (SocketException) { } catch (ObjectDisposedException) { } -// } + // } } void AsyncEndSend(IAsyncResult result) @@ -515,5 +502,25 @@ namespace OpenMetaverse catch (SocketException) { } catch (ObjectDisposedException) { } } + + public void SyncSend(UDPPacketBuffer buf) + { + try + { + m_udpSocket.SendTo( + buf.Data, + 0, + buf.DataLength, + SocketFlags.None, + buf.RemoteEndPoint + ); + UdpSends++; + } + catch (SocketException e) + { + m_log.Warn("[UDPBASE]: sync send SocketException {0} " + e.Message); + } + catch (ObjectDisposedException) { } + } } } diff --git a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs index 0e1a9e3d10..eb262d27f7 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/Tests/BasicCircuitTests.cs @@ -91,6 +91,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests /// /// Test adding a client to the stack /// +/* [Test] public void TestAddClient() { @@ -165,7 +166,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP.Tests ScenePresence spAfterAckTimeout = m_scene.GetScenePresence(sp.UUID); Assert.That(spAfterAckTimeout, Is.Null); } - +*/ // /// // /// Test removing a client from the stack // /// diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index d2aa17793c..52b9d0ee84 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs @@ -258,24 +258,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction { m_uploadState = UploadState.Complete; - ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, m_asset.FullID); - + bool sucess = true; if (m_createItem) { - CompleteCreateItem(m_createItemCallback); + sucess = CompleteCreateItem(m_createItemCallback); } else if (m_updateItem) { - CompleteItemUpdate(m_updateItemData); + sucess = CompleteItemUpdate(m_updateItemData); } else if (m_updateTaskItem) { - CompleteTaskItemUpdate(m_updateTaskItemData); + sucess = CompleteTaskItemUpdate(m_updateTaskItemData); } else if (m_asset.Local) { m_Scene.AssetService.Store(m_asset); } + ourClient.SendAssetUploadCompleteMessage(m_asset.Type, sucess, m_asset.FullID); } m_log.DebugFormat( @@ -411,46 +411,70 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction /// Store the asset for the given item when it has been uploaded. /// /// - private void CompleteItemUpdate(InventoryItemBase item) + private bool CompleteItemUpdate(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); - ValidateAssets(); - m_Scene.AssetService.Store(m_asset); - if (m_asset.FullID != UUID.Zero) + uint perms = ValidateAssets(); + if(perms == 0) { - item.AssetID = m_asset.FullID; - m_Scene.InventoryService.UpdateItem(item); + string error = string.Format("Not enough permissions on asset(s) referenced by item '{0}', update failed", item.Name); + ourClient.SendAlertMessage(error); + m_transactions.RemoveXferUploader(m_transactionID); + ourClient.SendBulkUpdateInventory(item); // invalid the change item on viewer cache + } + else + { + m_Scene.AssetService.Store(m_asset); + if (m_asset.FullID != UUID.Zero) + { + item.AssetID = m_asset.FullID; + m_Scene.InventoryService.UpdateItem(item); + } + ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0); + m_transactions.RemoveXferUploader(m_transactionID); + m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(item, 0); } - ourClient.SendInventoryItemCreateUpdate(item, m_transactionID, 0); - - m_transactions.RemoveXferUploader(m_transactionID); - - m_Scene.EventManager.TriggerOnNewInventoryItemUploadComplete(item, 0); + return perms != 0; } /// /// Store the asset for the given task item when it has been uploaded. /// /// - private void CompleteTaskItemUpdate(TaskInventoryItem taskItem) + private bool 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); - ValidateAssets(); - m_Scene.AssetService.Store(m_asset); + if(ValidateAssets() == 0) + { + m_transactions.RemoveXferUploader(m_transactionID); + string error = string.Format("Not enough permissions on asset(s) referenced by task item '{0}', update failed", taskItem.Name); + ourClient.SendAlertMessage(error); + // force old asset to viewers ?? + return false; + } + m_Scene.AssetService.Store(m_asset); m_transactions.RemoveXferUploader(m_transactionID); + return true; } - private void CompleteCreateItem(uint callbackID) + private bool CompleteCreateItem(uint callbackID) { - ValidateAssets(); + if(ValidateAssets() == 0) + { + m_transactions.RemoveXferUploader(m_transactionID); + string error = string.Format("Not enough permissions on asset(s) referenced by item '{0}', creation failed", m_name); + ourClient.SendAlertMessage(error); + return false; + } + m_Scene.AssetService.Store(m_asset); InventoryItemBase item = new InventoryItemBase(); @@ -480,35 +504,40 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction ourClient.SendAlertMessage("Unable to create inventory item"); m_transactions.RemoveXferUploader(m_transactionID); + return true; } - - private void ValidateAssets() + private uint ValidateAssets() { + uint retPerms = 0x7fffffff; +// if(m_Scene.Permissions.BypassPermissions()) +// return retPerms; + if (m_asset.Type == (sbyte)CustomAssetType.AnimationSet) { + AnimationSet animSet = new AnimationSet(m_asset.Data); - bool allOk = animSet.Validate(x => { - int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x); - int required = (int)(PermissionMask.Transfer | PermissionMask.Copy); + retPerms &= animSet.Validate(x => { + const uint required = (uint)(PermissionMask.Transfer | PermissionMask.Copy); + uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, x); + // currrent yes/no rule if ((perms & required) != required) - return false; - return true; + return 0; + return perms; }); - if (!allOk) - m_asset.Data = animSet.ToBytes(); + return retPerms; } if (m_asset.Type == (sbyte)AssetType.Clothing || m_asset.Type == (sbyte)AssetType.Bodypart) { + const uint texturesfullPermMask = (uint)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy); string content = System.Text.Encoding.ASCII.GetString(m_asset.Data); string[] lines = content.Split(new char[] {'\n'}); - List validated = new List(); - + // on current requiriment of full rigths assume old assets where accepted Dictionary allowed = ExtractTexturesFromOldData(); int textures = 0; @@ -518,10 +547,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction try { if (line.StartsWith("textures ")) - { textures = Convert.ToInt32(line.Substring(9)); - validated.Add(line); - } + else if (textures > 0) { string[] parts = line.Split(new char[] {' '}); @@ -532,42 +559,35 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (defaultIDs.Contains(tx) || tx == UUID.Zero || (allowed.ContainsKey(id) && allowed[id] == tx)) { - validated.Add(parts[0] + " " + tx.ToString()); + continue; } else { - int perms = m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx); - int full = (int)(PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Copy); + uint perms = (uint)m_Scene.InventoryService.GetAssetPermissions(ourClient.AgentId, tx); - if ((perms & full) != full) + if ((perms & texturesfullPermMask) != texturesfullPermMask) { m_log.ErrorFormat("[ASSET UPLOADER]: REJECTED update with texture {0} from {1} because they do not own the texture", tx, ourClient.AgentId); - validated.Add(parts[0] + " " + UUID.Zero.ToString()); + return 0; } else { - validated.Add(line); + retPerms &= perms; } } textures--; } - else - { - validated.Add(line); - } } catch { // If it's malformed, skip it } } - - string final = String.Join("\n", validated.ToArray()); - - m_asset.Data = System.Text.Encoding.ASCII.GetBytes(final); } + return retPerms; } +/* not in use /// /// Get the asset data uploaded in this transfer. /// @@ -582,7 +602,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction return null; } - +*/ public void SetOldData(byte[] d) { m_oldData = d; diff --git a/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs b/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs index 8502006cd7..b4c68e2a65 100644 --- a/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs +++ b/OpenSim/Region/CoreModules/Agent/IPBan/SceneBanner.cs @@ -53,9 +53,9 @@ namespace OpenSim.Region.CoreModules.Agent.IPBan if (bans.Count > 0) { IClientIPEndpoint ipEndpoint; - if (client.TryGet(out ipEndpoint)) + if (client.TryGet(out ipEndpoint) && ipEndpoint.RemoteEndPoint != null) { - IPAddress end = ipEndpoint.EndPoint; + IPAddress end = ipEndpoint.RemoteEndPoint.Address; try { diff --git a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs index 2242e421c4..6e4a710bf9 100644 --- a/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs +++ b/OpenSim/Region/CoreModules/Agent/TextureSender/J2KDecoderModule.cs @@ -369,7 +369,8 @@ namespace OpenSim.Region.CoreModules.Agent.TextureSender else if (Cache != null) { string assetName = "j2kCache_" + AssetId.ToString(); - AssetBase layerDecodeAsset = Cache.Get(assetName); + AssetBase layerDecodeAsset; + Cache.Get(assetName, out layerDecodeAsset); if (layerDecodeAsset != null) { diff --git a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs index 23c1f035b8..403236c170 100644 --- a/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CenomeAssetCache.cs @@ -260,10 +260,9 @@ namespace OpenSim.Region.CoreModules.Asset /// Cache doesn't guarantee in any situation that asset is stored to it. /// /// - public AssetBase Get(string id) + public bool Get(string id, out AssetBase assetBase) { m_getCount++; - AssetBase assetBase; if (m_cache.TryGetValue(id, out assetBase)) m_hitCount++; @@ -284,7 +283,7 @@ namespace OpenSim.Region.CoreModules.Asset // if (null == assetBase) // m_log.DebugFormat("[CENOME ASSET CACHE]: Asset {0} not in cache", id); - return assetBase; + return true; } #endregion diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs index 51fc3d1d7b..10c0e85175 100644 --- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs @@ -115,7 +115,10 @@ namespace OpenSim.Region.CoreModules.Asset public bool Check(string id) { // XXX This is probably not an efficient implementation. - return Get(id) != null; + AssetBase asset; + if (!Get(id, out asset)) + return false; + return asset != null; } public void Cache(AssetBase asset) @@ -129,9 +132,10 @@ namespace OpenSim.Region.CoreModules.Asset // We don't do negative caching } - public AssetBase Get(string id) + public bool Get(string id, out AssetBase asset) { - return (AssetBase)m_Cache.Get(id); + asset = (AssetBase)m_Cache.Get(id); + return true; } public void Expire(string id) diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 187f090ec5..f2fc070c58 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -474,6 +474,8 @@ namespace OpenSim.Region.CoreModules.Asset { using (FileStream stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) { + if (stream.Length == 0) // Empty file will trigger exception below + return null; BinaryFormatter bformatter = new BinaryFormatter(); asset = (AssetBase)bformatter.Deserialize(stream); @@ -531,15 +533,26 @@ namespace OpenSim.Region.CoreModules.Asset return found; } + // For IAssetService public AssetBase Get(string id) { + AssetBase asset; + Get(id, out asset); + return asset; + } + + public bool Get(string id, out AssetBase asset) + { + asset = null; + m_Requests++; object dummy; if (m_negativeCache.TryGetValue(id, out dummy)) - return null; + { + return false; + } - AssetBase asset = null; asset = GetFromWeakReference(id); if (asset != null && m_updateFileTimeOnCacheHit) { @@ -578,13 +591,7 @@ namespace OpenSim.Region.CoreModules.Asset GenerateCacheHitReport().ForEach(l => m_log.InfoFormat("[FLOTSAM ASSET CACHE]: {0}", l)); } - if(asset == null) - { - - - } - - return asset; + return true; } public bool Check(string id) @@ -599,7 +606,9 @@ namespace OpenSim.Region.CoreModules.Asset public AssetBase GetCached(string id) { - return Get(id); + AssetBase asset; + Get(id, out asset); + return asset; } public void Expire(string id) @@ -637,7 +646,7 @@ namespace OpenSim.Region.CoreModules.Asset if (m_LogLevel >= 2) m_log.Debug("[FLOTSAM ASSET CACHE]: Clearing caches."); - if (m_FileCacheEnabled) + if (m_FileCacheEnabled && Directory.Exists(m_CacheDirectory)) { foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { @@ -672,10 +681,10 @@ namespace OpenSim.Region.CoreModules.Asset // 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); - - foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) + if(Directory.Exists(m_CacheDirectory)) { - CleanExpiredFiles(dir, purgeLine); + foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) + CleanExpiredFiles(dir, purgeLine); } lock(timerLock) @@ -697,6 +706,9 @@ namespace OpenSim.Region.CoreModules.Asset { try { + if(!Directory.Exists(dir)) + return; + foreach (string file in Directory.GetFiles(dir)) { if (File.GetLastAccessTime(file) < purgeLine) @@ -797,6 +809,9 @@ namespace OpenSim.Region.CoreModules.Asset return; } + catch (UnauthorizedAccessException e) + { + } finally { if (stream != null) @@ -857,6 +872,9 @@ namespace OpenSim.Region.CoreModules.Asset /// private int GetFileCacheCount(string dir) { + if(!Directory.Exists(dir)) + return 0; + int count = Directory.GetFiles(dir).Length; foreach (string subdir in Directory.GetDirectories(dir)) @@ -975,6 +993,9 @@ namespace OpenSim.Region.CoreModules.Asset /// private void ClearFileCache() { + if(!Directory.Exists(m_CacheDirectory)) + return; + foreach (string dir in Directory.GetDirectories(m_CacheDirectory)) { try @@ -1147,7 +1168,7 @@ namespace OpenSim.Region.CoreModules.Asset con.Output("FloatSam Ensuring assets are cached for all scenes."); - WorkManager.RunInThread(delegate + WorkManager.RunInThreadPool(delegate { bool wasRunning= false; lock(timerLock) @@ -1227,19 +1248,23 @@ namespace OpenSim.Region.CoreModules.Asset public AssetMetadata GetMetadata(string id) { - AssetBase asset = Get(id); + AssetBase asset; + Get(id, out asset); return asset.Metadata; } public byte[] GetData(string id) { - AssetBase asset = Get(id); + AssetBase asset; + Get(id, out asset); return asset.Data; } public bool Get(string id, object sender, AssetRetrieved handler) { - AssetBase asset = Get(id); + AssetBase asset; + if (!Get(id, out asset)) + return false; handler(id, sender, asset); return true; } @@ -1270,7 +1295,9 @@ namespace OpenSim.Region.CoreModules.Asset public bool UpdateContent(string id, byte[] data) { - AssetBase asset = Get(id); + AssetBase asset; + if (!Get(id, out asset)) + return false; asset.Data = data; Cache(asset); return true; diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs index 208963d1f4..abe9b23770 100644 --- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs @@ -131,14 +131,15 @@ namespace OpenSim.Region.CoreModules.Asset // We don't do negative caching } - public AssetBase Get(string id) + public bool Get(string id, out AssetBase asset) { - Object asset = null; - m_Cache.TryGet(id, out asset); + Object a = null; + m_Cache.TryGet(id, out a); - Debug(asset); + Debug(a); - return (AssetBase)asset; + asset = (AssetBase)a; + return true; } public void Expire(string id) diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 8b8ac20c4d..5bca482af3 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -42,6 +42,7 @@ using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Region.Framework.Scenes.Serialization; using OpenSim.Services.Interfaces; +using PermissionMask = OpenSim.Framework.PermissionMask; namespace OpenSim.Region.CoreModules.Avatar.Attachments { @@ -481,14 +482,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", // group.Name, group.LocalId, sp.Name, attachmentPt, silent); - if (sp.GetAttachments().Contains(group)) - { -// m_log.WarnFormat( -// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", -// group.Name, group.LocalId, sp.Name, AttachmentPt); - - return false; - } if (group.GetSittingAvatarsCount() != 0) { @@ -500,6 +493,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments return false; } + List attachments = sp.GetAttachments(attachmentPt); + if (attachments.Contains(group)) + { +// if (DebugLevel > 0) +// m_log.WarnFormat( +// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", +// group.Name, group.LocalId, sp.Name, attachmentPt); + + return false; + } + Vector3 attachPos = group.AbsolutePosition; // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should @@ -533,7 +537,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments { attachmentPt = (uint)group.RootPart.Shape.LastAttachPoint; attachPos = group.RootPart.AttachedPos; - group.HasGroupChanged = true; } // if we still didn't find a suitable attachment point....... @@ -544,18 +547,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments attachPos = Vector3.Zero; } - List attachments = sp.GetAttachments(attachmentPt); - - if (attachments.Contains(group)) - { - if (DebugLevel > 0) - m_log.WarnFormat( - "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", - group.Name, group.LocalId, sp.Name, attachmentPt); - - return false; - } - // If we already have 5, remove the oldest until only 4 are left. Skip over temp ones while (attachments.Count >= 5) { @@ -579,7 +570,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments lock (sp.AttachmentsSyncLock) { group.AttachmentPoint = attachmentPt; - group.AbsolutePosition = attachPos; + group.RootPart.AttachedPos = attachPos; if (addToInventory && sp.PresenceType != PresenceType.Npc) UpdateUserInventoryWithAttachment(sp, group, attachmentPt, append); @@ -906,6 +897,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (item != null) { + // attach is rez, need to update permissions + item.Flags &= ~(uint)(InventoryItemFlags.ObjectSlamPerm | InventoryItemFlags.ObjectOverwriteBase | + InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | + InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner); + + uint permsBase = (uint)(PermissionMask.Copy | PermissionMask.Transfer | + PermissionMask.Modify | PermissionMask.Move | + PermissionMask.Export | PermissionMask.FoldedMask); + + permsBase &= grp.CurrentAndFoldedNextPermissions(); + permsBase |= (uint)PermissionMask.Move; + item.BasePermissions = permsBase; + item.CurrentPermissions = permsBase; + item.NextPermissions = permsBase & grp.RootPart.NextOwnerMask | (uint)PermissionMask.Move; + item.EveryOnePermissions = permsBase & grp.RootPart.EveryoneMask; + item.GroupPermissions = permsBase & grp.RootPart.GroupMask; + item.CurrentPermissions &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify | + (uint)PermissionMask.Move | + (uint)PermissionMask.Export | + (uint)PermissionMask.FoldedMask); // Preserve folded permissions ?? + AssetBase asset = m_scene.CreateAsset( grp.GetPartName(grp.LocalId), grp.GetPartDescription(grp.LocalId), @@ -956,7 +971,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments m_scene.DeleteFromStorage(so.UUID); m_scene.EventManager.TriggerParcelPrimCountTainted(); - so.AttachedAvatar = sp.UUID; foreach (SceneObjectPart part in so.Parts) { @@ -969,11 +983,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments } } - so.AbsolutePosition = attachOffset; - so.RootPart.AttachedPos = attachOffset; - so.IsAttachment = true; so.RootPart.SetParentLocalId(sp.LocalId); + so.AttachedAvatar = sp.UUID; so.AttachmentPoint = attachmentpoint; + so.RootPart.AttachedPos = attachOffset; + so.AbsolutePosition = attachOffset; + so.IsAttachment = true; sp.AddAttachment(so); @@ -1322,7 +1337,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (part == null) return; - if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) + SceneObjectGroup group = part.ParentGroup; + + if (!m_scene.Permissions.CanTakeObject(group, sp)) { remoteClient.SendAgentAlertMessage( "You don't have sufficient permissions to attach this object", false); @@ -1334,7 +1351,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments AttachmentPt &= 0x7f; // Calls attach with a Zero position - SceneObjectGroup group = part.ParentGroup; if (AttachObject(sp, group , AttachmentPt, false, true, append)) { if (DebugLevel > 0) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index fb408a402d..9553f5b4b8 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -299,7 +299,8 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (bakedTextureFace == null) continue; - AssetBase asset = cache.Get(bakedTextureFace.TextureID.ToString()); + AssetBase asset; + cache.Get(bakedTextureFace.TextureID.ToString(), out asset); if (asset != null && asset.Local) { @@ -368,7 +369,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return true; // uploaded baked textures will be in assets local cache - IAssetService cache = m_scene.AssetService; + IAssetCache cache = m_scene.RequestModuleInterface(); IBakedTextureModule m_BakedTextureModule = m_scene.RequestModuleInterface(); int validDirtyBakes = 0; @@ -384,7 +385,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory List missing = new List(); - bool haveSkirt = (wearableCache[19].TextureAsset != null); + bool haveSkirt = (wearableCache[19].TextureID != UUID.Zero); bool haveNewSkirt = false; // Process received baked textures @@ -435,7 +436,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory */ wearableCache[idx].TextureAsset = null; if (cache != null) - wearableCache[idx].TextureAsset = cache.GetCached(face.TextureID.ToString()); + { + AssetBase asb = null; + cache.Get(face.TextureID.ToString(), out asb); + wearableCache[idx].TextureAsset = asb; + } if (wearableCache[idx].TextureAsset != null) { @@ -480,25 +485,26 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // if we got a full set of baked textures save all in BakedTextureModule if (m_BakedTextureModule != null) { - m_log.Debug("[UpdateBakedCache] start async uploading to bakedModule cache"); + m_log.DebugFormat("[UpdateBakedCache] Uploading to Bakes Server: cache hits: {0} changed entries: {1} rebakes {2}", + hits.ToString(), validDirtyBakes.ToString(), missing.Count); m_BakedTextureModule.Store(sp.UUID, wearableCache); } } + else + m_log.DebugFormat("[UpdateBakedCache] cache hits: {0} changed entries: {1} rebakes {2}", + hits.ToString(), validDirtyBakes.ToString(), missing.Count); - - // debug - m_log.Debug("[UpdateBakedCache] cache hits: " + hits.ToString() + " changed entries: " + validDirtyBakes.ToString() + " rebakes " + missing.Count); -/* for (int iter = 0; iter < AvatarAppearance.BAKE_INDICES.Length; iter++) { int j = AvatarAppearance.BAKE_INDICES[iter]; - m_log.Debug("[UpdateBCache] {" + iter + "/" + - sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" + - sp.Appearance.WearableCacheItems[j].CacheId + ", t-" + - sp.Appearance.WearableCacheItems[j].TextureID); + sp.Appearance.WearableCacheItems[j].TextureAsset = null; +// m_log.Debug("[UpdateBCache] {" + iter + "/" + +// sp.Appearance.WearableCacheItems[j].TextureIndex + "}: c-" + +// sp.Appearance.WearableCacheItems[j].CacheId + ", t-" + +// sp.Appearance.WearableCacheItems[j].TextureID); } -*/ + return (hits == cacheItems.Length); } @@ -512,7 +518,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory lock (m_setAppearanceLock) { - IAssetService cache = m_scene.AssetService; + IAssetCache cache = m_scene.RequestModuleInterface(); IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); WearableCacheItem[] bakedModuleCache = null; @@ -552,6 +558,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory } } */ + bool wearableCacheValid = false; if (wearableCache == null) { @@ -576,10 +583,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory hits++; wearableCache[idx].TextureAsset.Temporary = true; wearableCache[idx].TextureAsset.Local = true; - cache.Store(wearableCache[idx].TextureAsset); + cache.Cache(wearableCache[idx].TextureAsset); + wearableCache[idx].TextureAsset = null; continue; } - if (cache.GetCached((wearableCache[idx].TextureID).ToString()) != null) + + if (cache.Check((wearableCache[idx].TextureID).ToString())) { hits++; continue; @@ -644,7 +653,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory wearableCache[j].TextureAsset = bakedModuleCache[i].TextureAsset; bakedModuleCache[i].TextureAsset.Temporary = true; bakedModuleCache[i].TextureAsset.Local = true; - cache.Store(bakedModuleCache[i].TextureAsset); + cache.Cache(bakedModuleCache[i].TextureAsset); } } gotbacked = true; @@ -676,6 +685,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory face.TextureID = wearableCache[idx].TextureID; hits++; + wearableCache[idx].TextureAsset = null; } } } @@ -705,7 +715,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return 0; int texturesRebaked = 0; -// IAssetCache cache = m_scene.RequestModuleInterface(); + IAssetCache cache = m_scene.RequestModuleInterface(); for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) { @@ -721,18 +731,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (missingTexturesOnly) { - if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + if (cache != null && cache.Check(face.TextureID.ToString())) { continue; } else { - // On inter-simulator teleports, this occurs if baked textures are not being stored by the - // grid asset service (which means that they are not available to the new region and so have - // to be re-requested from the client). - // - // The only available core OpenSimulator behaviour right now - // is not to store these textures, temporarily or otherwise. m_log.DebugFormat( "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", face.TextureID, idx, sp.Name); diff --git a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs index 27e84b0f13..cfa9581d82 100644 --- a/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/BakedTextures/XBakesModule.cs @@ -216,6 +216,8 @@ namespace OpenSim.Region.CoreModules.Avatar.BakedTextures rc.Request(reqStream, m_Auth); m_log.DebugFormat("[XBakes]: stored {0} textures for user {1}", numberWears, agentId); } + if(reqStream != null) + reqStream.Dispose(); }, null, "XBakesModule.Store" ); } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 35b48d9924..772485cfeb 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -247,11 +247,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { FriendInfo[] friends = GetFriendsFromCache(principalID); FriendInfo finfo = GetFriend(friends, friendID); - if (finfo != null) + if (finfo != null && finfo.TheirFlags != -1) { return finfo.TheirFlags; } - return 0; } @@ -512,18 +511,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (((fi.MyFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) friendList.Add(fi); } + if(friendList.Count > 0) + { + Util.FireAndForget( + delegate + { +// m_log.DebugFormat( +// "[FRIENDS MODULE]: Notifying {0} friends of {1} of online status {2}", +// friendList.Count, agentID, online); - Util.FireAndForget( - delegate - { -// 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); - }, null, "FriendsModule.StatusChange" - ); + // Notify about this user status + StatusNotify(friendList, agentID, online); + }, null, "FriendsModule.StatusChange" + ); + } } } @@ -552,6 +553,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // 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()); + if(friendSessions == null) + return; foreach (PresenceInfo friendSession in friendSessions) { @@ -752,7 +755,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (friend == null) return; - if((friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0) + if(friend.TheirFlags == -1 || (friend.TheirFlags & (int)FriendRights.CanSeeOnMap) == 0) return; Scene hunterScene = (Scene)remoteClient.Scene; diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs index 81aa8829a4..091b1975e4 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs @@ -65,9 +65,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected override byte[] ProcessRequest( string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index 82154bcc9e..fae1e05349 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -214,7 +214,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends FriendInfo[] friends = GetFriendsFromCache(client.AgentId); foreach (FriendInfo f in friends) { - client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); + int rights = f.TheirFlags; + if(rights != -1 ) + client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, rights); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs index f699c0c889..6e6974a5c8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Gods/GodsModule.cs @@ -59,21 +59,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods /// Special UUID for actions that apply to all agents private static readonly UUID ALL_AGENTS = new UUID("44e87126-e794-4ded-05b3-7c42da3d5cdb"); + private static readonly UUID UUID_GRID_GOD = new UUID("6571e388-6218-4574-87db-f9379718315e"); protected Scene m_scene; protected IDialogModule m_dialogModule; - protected IDialogModule DialogModule - { - get - { - if (m_dialogModule == null) - m_dialogModule = m_scene.RequestModuleInterface(); - - return m_dialogModule; - } - } - public void Initialise(IConfigSource source) { } @@ -97,6 +87,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods public void RegionLoaded(Scene scene) { + m_dialogModule = m_scene.RequestModuleInterface(); } public void Close() {} @@ -152,7 +143,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods if (god == null || god.ControllingClient.SessionId != godSessionID) return String.Empty; - KickUser(godID, agentID, kickFlags, Util.StringToBytes1024(reason)); + KickUser(godID, agentID, kickFlags, reason); } else { @@ -173,8 +164,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods sp.GrantGodlikePowers(token, godLike); - if (godLike && !sp.IsViewerUIGod && DialogModule != null) - DialogModule.SendAlertToUser(agentID, "Request for god powers denied"); + if (godLike && !sp.IsViewerUIGod && m_dialogModule != null) + m_dialogModule.SendAlertToUser(agentID, "Request for god powers denied"); + } + + public void KickUser(UUID godID, UUID agentID, uint kickflags, byte[] reason) + { + KickUser(godID, agentID, kickflags, Utils.BytesToString(reason)); } /// @@ -184,7 +180,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods /// the person that is being kicked /// Tells what to do to the user /// The message to send to the user after it's been turned into a field - public void KickUser(UUID godID, UUID agentID, uint kickflags, byte[] reason) + public void KickUser(UUID godID, UUID agentID, uint kickflags, string reason) { // assuming automatic god rights on this for fast griefing reaction // this is also needed for kick via message @@ -200,10 +196,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods if(agentID == ALL_AGENTS) { m_scene.ForEachRootScenePresence(delegate(ScenePresence p) + { + if (p.UUID != godID) { - if (p.UUID != godID && godlevel > p.GodController.GodLevel) + if(godlevel > p.GodController.GodLevel) doKickmodes(godID, p, kickflags, reason); - }); + else if(m_dialogModule != null) + m_dialogModule.SendAlertToUser(p.UUID, "Kick from " + godID.ToString() + " ignored, kick reason: " + reason); + } + }); return; } @@ -217,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID); transferModule.SendInstantMessage(new GridInstantMessage( m_scene, godID, "God", agentID, (byte)250, false, - Utils.BytesToString(reason), UUID.Zero, true, + reason, UUID.Zero, true, new Vector3(), new byte[] {(byte)kickflags}, true), delegate(bool success) {} ); } @@ -225,7 +226,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods } if (godlevel <= sp.GodController.GodLevel) // no god wars + { + if(m_dialogModule != null) + m_dialogModule.SendAlertToUser(sp.UUID, "Kick from " + godID.ToString() + " ignored, kick reason: " + reason); return; + } if(sp.UUID == godID) return; @@ -233,29 +238,34 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods doKickmodes(godID, sp, kickflags, reason); } - private void doKickmodes(UUID godID, ScenePresence sp, uint kickflags, byte[] reason) + private void doKickmodes(UUID godID, ScenePresence sp, uint kickflags, string reason) { switch (kickflags) { case 0: - KickPresence(sp, Utils.BytesToString(reason)); + KickPresence(sp, reason); break; case 1: sp.AllowMovement = false; - m_dialogModule.SendAlertToUser(sp.UUID, Utils.BytesToString(reason)); - m_dialogModule.SendAlertToUser(godID, "User Frozen"); + if(m_dialogModule != null) + { + m_dialogModule.SendAlertToUser(sp.UUID, reason); + m_dialogModule.SendAlertToUser(godID, "User Frozen"); + } break; case 2: sp.AllowMovement = true; - m_dialogModule.SendAlertToUser(sp.UUID, Utils.BytesToString(reason)); - m_dialogModule.SendAlertToUser(godID, "User Unfrozen"); + if(m_dialogModule != null) + { + m_dialogModule.SendAlertToUser(sp.UUID, reason); + m_dialogModule.SendAlertToUser(godID, "User Unfrozen"); + } break; default: break; } } - private void KickPresence(ScenePresence sp, string reason) { if(sp.IsDeleted || sp.IsChildAgent) @@ -264,6 +274,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods sp.Scene.CloseAgent(sp.UUID, true); } + public void GridKickUser(UUID agentID, string reason) + { + int godlevel = 240; // grid god default + + ScenePresence sp = m_scene.GetScenePresence(agentID); + if (sp == null || sp.IsChildAgent) + { + IMessageTransferModule transferModule = + m_scene.RequestModuleInterface(); + if (transferModule != null) + { + m_log.DebugFormat("[GODS]: Sending nonlocal kill for agent {0}", agentID); + transferModule.SendInstantMessage(new GridInstantMessage( + m_scene, UUID_GRID_GOD, "GRID", agentID, (byte)250, false, + reason, UUID.Zero, true, + new Vector3(), new byte[] {0}, true), + delegate(bool success) {} ); + } + return; + } + + if(sp.IsDeleted) + return; + + if (godlevel <= sp.GodController.GodLevel) // no god wars + { + if(m_dialogModule != null) + m_dialogModule.SendAlertToUser(sp.UUID, "GRID kick detected and ignored, kick reason: " + reason); + return; + } + + sp.ControllingClient.Kick(reason); + sp.Scene.CloseAgent(sp.UUID, true); + } + private void OnIncomingInstantMessage(GridInstantMessage msg) { if (msg.dialog == (uint)250) // Nonlocal kick @@ -273,7 +318,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Gods UUID godID = new UUID(msg.fromAgentID); uint kickMode = (uint)msg.binaryBucket[0]; - KickUser(godID, agentID, kickMode, Util.StringToBytes1024(reason)); + if(godID == UUID_GRID_GOD) + GridKickUser(agentID, reason); + else + KickUser(godID, agentID, kickMode, reason); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs index d1f6054106..315ce1b072 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/OfflineMessageModule.cs @@ -52,6 +52,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private bool enabled = true; + private bool m_UseNewAvnCode = false; private List m_SceneList = new List(); private string m_RestURL = String.Empty; IMessageTransferModule m_TransferModule = null; @@ -82,6 +83,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage } m_ForwardOfflineGroupMessages = cnf.GetBoolean("ForwardOfflineGroupMessages", m_ForwardOfflineGroupMessages); + m_UseNewAvnCode = cnf.GetBoolean("UseNewAvnCode", m_UseNewAvnCode); } public void AddRegion(Scene scene) @@ -244,68 +246,73 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage return; } - Scene scene = FindScene(new UUID(im.fromAgentID)); - if (scene == null) - scene = m_SceneList[0]; - -// Avination new code -// SendReply reply = SynchronousRestObjectRequester.MakeRequest( -// "POST", m_RestURL+"/SaveMessage/?scope=" + -// scene.RegionInfo.ScopeID.ToString(), im); - -// current opensim and osgrid compatible - bool success = SynchronousRestObjectRequester.MakeRequest( - "POST", m_RestURL+"/SaveMessage/", im, 10000); -// current opensim and osgrid compatible end - - if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) + if(m_UseNewAvnCode) { - IClientAPI client = FindClient(new UUID(im.fromAgentID)); - if (client == null) - return; -/* Avination new code - if (reply.Message == String.Empty) - reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved"); + Scene scene = FindScene(new UUID(im.fromAgentID)); + if (scene == null) + scene = m_SceneList[0]; - bool sendReply = true; + UUID scopeID = scene.RegionInfo.ScopeID; + SendReply reply = SynchronousRestObjectRequester.MakeRequest( + "POST", m_RestURL+"/SaveMessage/?scope=" + scopeID.ToString(), im, 20000); - switch (reply.Disposition) + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) { - case 0: // Normal - break; - case 1: // Only once per user - if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID))) + IClientAPI client = FindClient(new UUID(im.fromAgentID)); + if (client == null) + return; + + if (string.IsNullOrEmpty(reply.Message)) + reply.Message = "User is not logged in. " + (reply.Success ? "Message saved." : "Message not saved"); + + bool sendReply = true; + + switch (reply.Disposition) { - sendReply = false; + case 0: // Normal + break; + case 1: // Only once per user + if (m_repliesSent.ContainsKey(client) && m_repliesSent[client].Contains(new UUID(im.toAgentID))) + sendReply = false; + else + { + if (!m_repliesSent.ContainsKey(client)) + m_repliesSent[client] = new List(); + m_repliesSent[client].Add(new UUID(im.toAgentID)); + } + break; } - else + + if (sendReply) { - if (!m_repliesSent.ContainsKey(client)) - m_repliesSent[client] = new List(); - m_repliesSent[client].Add(new UUID(im.toAgentID)); + client.SendInstantMessage(new GridInstantMessage( + null, new UUID(im.toAgentID), + "System", new UUID(im.fromAgentID), + (byte)InstantMessageDialog.MessageFromAgent, + reply.Message, + false, new Vector3())); } - break; } + } + else + { + bool success = SynchronousRestObjectRequester.MakeRequest( + "POST", m_RestURL+"/SaveMessage/", im, 20000); - if (sendReply) + if (im.dialog == (byte)InstantMessageDialog.MessageFromAgent) { + IClientAPI client = FindClient(new UUID(im.fromAgentID)); + if (client == null) + return; + client.SendInstantMessage(new GridInstantMessage( - null, new UUID(im.toAgentID), - "System", new UUID(im.fromAgentID), - (byte)InstantMessageDialog.MessageFromAgent, - reply.Message, - false, new Vector3())); - } -*/ -// current opensim and osgrid compatible - client.SendInstantMessage(new GridInstantMessage( null, new UUID(im.toAgentID), "System", new UUID(im.fromAgentID), (byte)InstantMessageDialog.MessageFromAgent, "User is not logged in. "+ (success ? "Message saved." : "Message not saved"), false, new Vector3())); -// current opensim and osgrid compatible end + } } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index f002ad7a40..ad46107768 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -218,10 +218,39 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Count inventory items (different to asset count) CountItems++; - + // Don't chase down link asset items as they actually point to their target item IDs rather than an asset if (SaveAssets && itemAssetType != AssetType.Link && itemAssetType != AssetType.LinkFolder) + { + int curErrorCntr = m_assetGatherer.ErrorCount; + int possible = m_assetGatherer.possibleNotAssetCount; m_assetGatherer.AddForInspection(inventoryItem.AssetID); + m_assetGatherer.GatherAll(); + curErrorCntr = m_assetGatherer.ErrorCount - curErrorCntr; + possible = m_assetGatherer.possibleNotAssetCount - possible; + + if(curErrorCntr > 0 || possible > 0) + { + string spath; + int indx = path.IndexOf("__"); + if(indx > 0) + spath = path.Substring(0,indx); + else + spath = path; + + if(curErrorCntr > 0) + { + m_log.ErrorFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references to missing or damaged assets", + inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, curErrorCntr); + if(possible > 0) + m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item also contains {0} references that may be to missing or damaged assets or not a problem", possible); + } + else if(possible > 0) + { + m_log.WarnFormat("[INVENTORY ARCHIVER Warning]: item {0} '{1}', type {2}, in '{3}', contains {4} references that may be to missing or damaged assets or not a problem", inventoryItem.ID, inventoryItem.Name, itemAssetType.ToString(), spath, possible); + } + } + } } /// @@ -381,6 +410,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); Exception e = new InventoryArchiverException(errorMessage); m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e, 0, 0); + if(m_saveStream != null && m_saveStream.CanWrite) + m_saveStream.Close(); throw e; } @@ -420,17 +451,20 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { m_assetGatherer.GatherAll(); - m_log.DebugFormat( - "[INVENTORY ARCHIVER]: Saving {0} assets for items", m_assetGatherer.GatheredUuids.Count); + int errors = m_assetGatherer.FailedUUIDs.Count; - AssetsRequest ar - = new AssetsRequest( + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: The items to save reference {0} possible assets", m_assetGatherer.GatheredUuids.Count + errors); + if(errors > 0) + m_log.DebugFormat("[INVENTORY ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors); + + AssetsRequest ar = new AssetsRequest( new AssetsArchiver(m_archiveWriter), - m_assetGatherer.GatheredUuids, m_scene.AssetService, + m_assetGatherer.GatheredUuids, m_assetGatherer.FailedUUIDs.Count, + m_scene.AssetService, m_scene.UserAccountService, m_scene.RegionInfo.ScopeID, options, ReceivedAllAssets); - - WorkManager.RunInThread(o => ar.Execute(), null, string.Format("AssetsRequest ({0})", m_scene.Name)); + ar.Execute(); } else { diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index be59eb5957..06aec7bca5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // { try { - new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream).Execute(options, UserAccountService); + InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, saveStream); + iarReq.Execute(options, UserAccountService); } catch (EntryPointNotFoundException e) { @@ -261,7 +262,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // { try { - new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath).Execute(options, UserAccountService); + InventoryArchiveWriteRequest iarReq = new InventoryArchiveWriteRequest(id, this, m_aScene, userInfo, invPath, savePath); + iarReq.Execute(options, UserAccountService); } catch (EntryPointNotFoundException e) { diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs index bc8aeca002..e02ca497ed 100644 --- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs @@ -149,7 +149,7 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles if (profileConfig == null) { - m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration"); + //m_log.Debug("[PROFILES]: UserProfiles disabled, no configuration"); Enabled = false; return; } @@ -1839,12 +1839,12 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles webRequest.ContentType = "application/json-rpc"; webRequest.Method = "POST"; - using(Stream dataStream = webRequest.GetRequestStream()) - dataStream.Write(content,0,content.Length); - WebResponse webResponse = null; try { + using(Stream dataStream = webRequest.GetRequestStream()) + dataStream.Write(content,0,content.Length); + webResponse = webRequest.GetResponse(); } catch (WebException e) @@ -1920,12 +1920,12 @@ namespace OpenSim.Region.CoreModules.Avatar.UserProfiles webRequest.ContentType = "application/json-rpc"; webRequest.Method = "POST"; - using(Stream dataStream = webRequest.GetRequestStream()) - dataStream.Write(content,0,content.Length); - WebResponse webResponse = null; try { + using(Stream dataStream = webRequest.GetRequestStream()) + dataStream.Write(content,0,content.Length); + webResponse = webRequest.GetResponse(); } catch (WebException e) diff --git a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs index 292099d864..c0afe7c49d 100644 --- a/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs +++ b/OpenSim/Region/CoreModules/Framework/Caps/CapabilitiesModule.cs @@ -142,9 +142,9 @@ namespace OpenSim.Region.CoreModules.Framework if (capsObjectPath == oldCaps.CapsObjectPath) { - m_log.WarnFormat( - "[CAPS]: Reusing caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ", - agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath); +// m_log.WarnFormat( +// "[CAPS]: Reusing caps for agent {0} in region {1}. Old caps path {2}, new caps path {3}. ", +// agentId, m_scene.RegionInfo.RegionName, oldCaps.CapsObjectPath, capsObjectPath); return; } else diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index 6dc982be3c..c93c54d5cf 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -157,7 +157,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_idCache = new ExpiringCache(); m_bannedRegions.Add(pAgentID, m_idCache, TimeSpan.FromSeconds(newTime)); } - m_idCache.Add(pRegionHandle, DateTime.UtcNow + TimeSpan.FromSeconds(extendTime), TimeSpan.FromSeconds(extendTime)); + m_idCache.Add(pRegionHandle, DateTime.UtcNow + TimeSpan.FromSeconds(extendTime), extendTime); } // Remove the agent from the region's banned list @@ -417,12 +417,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } catch (Exception e) { + m_log.ErrorFormat( "[ENTITY TRANSFER MODULE]: Exception on teleport of {0} from {1}@{2} to {3}@{4}: {5}{6}", sp.Name, sp.AbsolutePosition, sp.Scene.RegionInfo.RegionName, position, destinationRegionName, e.Message, e.StackTrace); - - sp.ControllingClient.SendTeleportFailed("Internal error"); + if(sp != null && sp.ControllingClient != null && !sp.IsDeleted) + sp.ControllingClient.SendTeleportFailed("Internal error"); } finally { @@ -527,15 +528,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { string homeURI = Scene.GetAgentHomeURI(sp.ControllingClient.AgentId); - string message; - finalDestination = GetFinalDestination(reg, sp.ControllingClient.AgentId, homeURI, out message); + string reason = String.Empty; + finalDestination = GetFinalDestination(reg, sp.ControllingClient.AgentId, homeURI, out reason); if (finalDestination == null) { m_log.WarnFormat( "{0} Final destination is having problems. Unable to teleport {1} {2}: {3}", - LogHeader, sp.Name, sp.UUID, message); + LogHeader, sp.Name, sp.UUID, reason); - sp.ControllingClient.SendTeleportFailed(message); + sp.ControllingClient.SendTeleportFailed(reason); return; } @@ -548,17 +549,12 @@ 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; } - if (message != null) - sp.ControllingClient.SendAgentAlertMessage(message, true); - // // This is it // @@ -735,8 +731,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer IPEndPoint endPoint = finalDestination.ExternalEndPoint; if (endPoint == null || endPoint.Address == null) { - sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); - + sp.ControllingClient.SendTeleportFailed("Could not resolve destination Address"); return; } @@ -776,30 +771,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else if (sp.Flying) teleportFlags |= (uint)TeleportFlags.IsFlying; + sp.IsInLocalTransit = finalDestination.RegionLocY != 0; // HG sp.IsInTransit = true; + if (DisableInterRegionTeleportCancellation) teleportFlags |= (uint)TeleportFlags.DisableCancel; // 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) - // closing the child agents, so save it here (we need a copy as it is Clear()-ed). - //List childRegions = avatar.KnownRegionHandles; - // Compared to ScenePresence.CrossToNewRegion(), there's no obvious code to handle a teleport - // failure at this point (unlike a border crossing failure). So perhaps this can never fail - // once we reach here... - //avatar.Scene.RemoveCapsHandler(avatar.UUID); - + AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); AgentCircuitData agentCircuit = sp.ControllingClient.RequestClientInfo(); agentCircuit.startpos = position; agentCircuit.child = true; -// agentCircuit.Appearance = sp.Appearance; -// agentCircuit.Appearance = new AvatarAppearance(sp.Appearance, true, false); agentCircuit.Appearance = new AvatarAppearance(); agentCircuit.Appearance.AvatarHeight = sp.Appearance.AvatarHeight; @@ -813,8 +800,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agentCircuit.Id0 = currentAgentCircuit.Id0; } - IClientIPEndpoint ipepClient; - uint newRegionX, newRegionY, oldRegionX, oldRegionY; Util.RegionHandleToRegionLoc(destinationHandle, out newRegionX, out newRegionY); Util.RegionHandleToRegionLoc(sourceRegion.RegionHandle, out oldRegionX, out oldRegionY); @@ -833,13 +818,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer finalDestination.RegionName, newRegionX, newRegionY,newSizeX, newSizeY, sp.Name, Scene.Name); //sp.ControllingClient.SendTeleportProgress(teleportFlags, "Creating agent..."); - #region IP Translation for NAT - // Uses ipepClient above - if (sp.ClientView.TryGet(out ipepClient)) - { - endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); - } - #endregion agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); } else @@ -867,6 +845,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Name, Scene.Name, finalDestination.RegionName); string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + List childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + if(agentCircuit.ChildrenCapSeeds != null) + { + foreach(ulong handler in childRegionsToClose) + { + agentCircuit.ChildrenCapSeeds.Remove(handler); + } + } // Let's create an agent there if one doesn't exist yet. // NOTE: logout will always be false for a non-HG teleport. @@ -952,7 +938,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.Position = agentCircuit.startpos; SetCallbackURL(agent, sp.Scene.RegionInfo); - // We will check for an abort before UpdateAgent since UpdateAgent will require an active viewer to // establish th econnection to the destination which makes it return true. if (m_entityTransferStateMachine.GetAgentTransferState(sp.UUID) == AgentTransferState.Aborting) @@ -1051,7 +1036,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return; } - /* // TODO: This may be 0.6. Check if still needed // For backwards compatibility @@ -1065,7 +1049,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); - sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + if(logout) + sp.closeAllChildAgents(); + else + sp.CloseChildAgents(childRegionsToClose); // call HG hook AgentHasMovedAway(sp, logout); @@ -1091,9 +1078,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // This sleep can be increased if necessary. However, whilst it's active, // an agent cannot teleport back to this region if it has teleported away. Thread.Sleep(2000); -// if (m_eqModule != null && !sp.DoNotCloseAfterTeleport) -// m_eqModule.DisableSimulator(sourceRegionHandle,sp.UUID); - Thread.Sleep(500); sp.Scene.CloseAgent(sp.UUID, false); } sp.IsInTransit = false; @@ -1103,7 +1087,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer IPEndPoint endPoint, uint teleportFlags, bool OutSideViewRange, EntityTransferContext ctx, out string reason) { ulong destinationHandle = finalDestination.RegionHandle; - AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); + + List childRegionsToClose = sp.GetChildAgentsToClose(destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + + if(agentCircuit.ChildrenCapSeeds != null) + { + foreach(ulong handler in childRegionsToClose) + { + agentCircuit.ChildrenCapSeeds.Remove(handler); + } + } string capsPath = finalDestination.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath);; @@ -1203,20 +1196,17 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer "[ENTITY TRANSFER MODULE]: UpdateAgent failed on teleport of {0} to {1}. Keeping avatar in {2}", sp.Name, finalDestination.RegionName, sp.Scene.Name); - Fail(sp, finalDestination, logout, currentAgentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); + Fail(sp, finalDestination, logout, agentCircuit.SessionID.ToString(), "Connection between viewer and destination region could not be established."); sp.IsInTransit = false; return; } m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.CleaningUp); - // Need to signal neighbours whether child agents may need closing irrespective of whether this - // one needed closing. We also need to close child agents as quickly as possible to avoid complicated - // race conditions with rapid agent releporting (e.g. from A1 to a non-neighbour B, back - // to a neighbour A2 then off to a non-neighbour C). Closing child agents any later requires complex - // distributed checks to avoid problems in rapid reteleporting scenarios and where child agents are - // abandoned without proper close by viewer but then re-used by an incoming connection. - sp.CloseChildAgents(logout, destinationHandle, finalDestination.RegionSizeX, finalDestination.RegionSizeY); + if(logout) + sp.closeAllChildAgents(); + else + sp.CloseChildAgents(childRegionsToClose); sp.HasMovedAway(!(OutSideViewRange || logout)); @@ -1243,9 +1233,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // IN THE AVIE BEING PLACED IN INFINITY FOR A COUPLE OF SECONDS. Thread.Sleep(15000); -// if (m_eqModule != null && !sp.DoNotCloseAfterTeleport) -// m_eqModule.DisableSimulator(sourceRegionHandle,sp.UUID); -// Thread.Sleep(1000); // OK, it got this agent. Let's close everything // If we shouldn't close the agent due to some other region renewing the connection @@ -1255,13 +1242,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Scene.CloseAgent(sp.UUID, false); } -/* - else - { - // now we have a child agent in this region. - sp.Reset(); - } - */ sp.IsInTransit = false; } @@ -1513,11 +1493,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Math.Max(scene.RegionInfo.RegionSizeX, scene.RegionInfo.RegionSizeY)); if (neighbourRegion == null) - { return null; - } + if (m_bannedRegionCache.IfBanned(neighbourRegion.RegionHandle, agentID)) { + failureReason = "Access Denied or Temporary not possible"; return null; } @@ -1529,13 +1509,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer pos.Z); string homeURI = scene.GetAgentHomeURI(agentID); - + if (!scene.SimulationService.QueryAccess( neighbourRegion, agentID, homeURI, false, newpos, scene.GetFormatsOffered(), ctx, out failureReason)) { // remember the fail m_bannedRegionCache.Add(neighbourRegion.RegionHandle, agentID); + if(String.IsNullOrWhiteSpace(failureReason)) + failureReason = "Access Denied"; return null; } @@ -1544,6 +1526,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer public bool Cross(ScenePresence agent, bool isFlying) { + agent.IsInLocalTransit = true; agent.IsInTransit = true; CrossAsyncDelegate d = CrossAsync; d.BeginInvoke(agent, isFlying, CrossCompleted, d); @@ -1555,13 +1538,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer CrossAsyncDelegate icon = (CrossAsyncDelegate)iar.AsyncState; ScenePresence agent = icon.EndInvoke(iar); - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); if(!agent.IsChildAgent) { // crossing failed agent.CrossToNewRegionFail(); } + else + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); + agent.IsInTransit = false; } @@ -1662,7 +1647,73 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer icon.EndInvoke(iar); } + public bool CrossAgentCreateFarChild(ScenePresence agent, GridRegion neighbourRegion, Vector3 pos, EntityTransferContext ctx) + { + ulong regionhandler = neighbourRegion.RegionHandle; + if(agent.knowsNeighbourRegion(regionhandler)) + return true; + + string reason; + ulong currentRegionHandler = agent.Scene.RegionInfo.RegionHandle; + GridRegion source = new GridRegion(agent.Scene.RegionInfo); + + AgentCircuitData currentAgentCircuit = + agent.Scene.AuthenticateHandler.GetAgentCircuitData(agent.ControllingClient.CircuitCode); + AgentCircuitData agentCircuit = agent.ControllingClient.RequestClientInfo(); + agentCircuit.startpos = pos; + agentCircuit.child = true; + + agentCircuit.Appearance = new AvatarAppearance(); + agentCircuit.Appearance.AvatarHeight = agent.Appearance.AvatarHeight; + + if (currentAgentCircuit != null) + { + agentCircuit.ServiceURLs = currentAgentCircuit.ServiceURLs; + agentCircuit.IPAddress = currentAgentCircuit.IPAddress; + agentCircuit.Viewer = currentAgentCircuit.Viewer; + agentCircuit.Channel = currentAgentCircuit.Channel; + agentCircuit.Mac = currentAgentCircuit.Mac; + agentCircuit.Id0 = currentAgentCircuit.Id0; + } + + agentCircuit.CapsPath = CapsUtil.GetRandomCapsObjectPath(); + agent.AddNeighbourRegion(neighbourRegion, agentCircuit.CapsPath); + + IPEndPoint endPoint = neighbourRegion.ExternalEndPoint; + if(endPoint == null) + { + m_log.DebugFormat("CrossAgentCreateFarChild failed to resolve neighbour address {0}", neighbourRegion.ExternalHostName); + return false; + } + if (!Scene.SimulationService.CreateAgent(source, neighbourRegion, agentCircuit, (int)TeleportFlags.Default, ctx, out reason)) + { + agent.RemoveNeighbourRegion(regionhandler); + return false; + } + + string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentCircuit.CapsPath); + int newSizeX = neighbourRegion.RegionSizeX; + int newSizeY = neighbourRegion.RegionSizeY; + + if (m_eqModule != null) + { + m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + + "and EstablishAgentCommunication with seed cap {8}", LogHeader, + source.RegionName, agent.Name, + neighbourRegion.RegionName, neighbourRegion.RegionLocX, neighbourRegion.RegionLocY, newSizeX, newSizeY , capsPath); + + m_eqModule.EnableSimulator(regionhandler, + endPoint, agent.UUID, newSizeX, newSizeY); + m_eqModule.EstablishAgentCommunication(agent.UUID, endPoint, capsPath, + regionhandler, newSizeX, newSizeY); + } + else + { + agent.ControllingClient.InformClientOfNeighbour(regionhandler, endPoint); + } + return true; + } /// /// This Closes child agents on neighbouring regions @@ -1683,39 +1734,51 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return agent; } - m_entityTransferStateMachine.SetInTransit(agent.UUID); - agent.RemoveFromPhysicalScene(); - - if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying, ctx)) + IPEndPoint endpoint = neighbourRegion.ExternalEndPoint; + if(endpoint == null) { - m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); - m_entityTransferStateMachine.ResetFromTransit(agent.UUID); + m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: failed to resolve neighbour address {0} ",neighbourRegion.ExternalHostName); return agent; } - CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, ctx); + m_entityTransferStateMachine.SetInTransit(agent.UUID); + agent.RemoveFromPhysicalScene(); + + if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, endpoint, isFlying, ctx)) + { + m_log.DebugFormat("{0}: CrossAgentToNewRegionAsync: cross main failed. Resetting transfer state", LogHeader); + m_entityTransferStateMachine.ResetFromTransit(agent.UUID); + } } catch (Exception e) { m_log.Error(string.Format("{0}: CrossAgentToNewRegionAsync: failed with exception ", LogHeader), e); } - return agent; } - public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx) + public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, + IPEndPoint endpoint, bool isFlying, EntityTransferContext ctx) { int ts = Util.EnvironmentTickCount(); + bool sucess = true; + string reason = String.Empty; + List childRegionsToClose = null; try { AgentData cAgent = new AgentData(); agent.CopyTo(cAgent,true); -// agent.Appearance.WearableCacheItems = null; - cAgent.Position = pos; cAgent.ChildrenCapSeeds = agent.KnownRegions; + childRegionsToClose = agent.GetChildAgentsToClose(neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); + if(cAgent.ChildrenCapSeeds != null) + { + foreach(ulong regh in childRegionsToClose) + cAgent.ChildrenCapSeeds.Remove(regh); + } + if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; @@ -1725,24 +1788,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Beyond this point, extra cleanup is needed beyond removing transit state m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.Transferring); - if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent, ctx)) + if (sucess && !agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent, ctx)) + { + sucess = false; + reason = "agent update failed"; + } + + if(!sucess) { // region doesn't take it m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); m_log.WarnFormat( - "[ENTITY TRANSFER MODULE]: Region {0} would not accept update for agent {1} on cross attempt. Returning to original region.", - neighbourRegion.RegionName, agent.Name); + "[ENTITY TRANSFER MODULE]: agent {0} crossing to {1} failed: {2}", + agent.Name, neighbourRegion.RegionName, reason); ReInstantiateScripts(agent); if(agent.ParentID == 0 && agent.ParentUUID == UUID.Zero) + { agent.AddToPhysicalScene(isFlying); + } return false; } m_log.DebugFormat("[CrossAgentIntoNewRegionMain] ok, time {0}ms",Util.EnvironmentTickCountSubtract(ts)); - } catch (Exception e) { @@ -1754,19 +1824,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer return false; } - return true; - } - - public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, - bool isFlying, EntityTransferContext ctx) - { - string agentcaps; if (!agent.KnownRegions.TryGetValue(neighbourRegion.RegionHandle, out agentcaps)) { m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: No ENTITY TRANSFER MODULE information for region handle {0}, exiting CrossToNewRegion.", neighbourRegion.RegionHandle); - return; + return false; } // No turning back @@ -1777,21 +1840,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); - Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); + Vector3 vel2 = Vector3.Zero; + if((agent.crossingFlags & 2) != 0) + vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); if (m_eqModule != null) { m_eqModule.CrossRegion( neighbourRegion.RegionHandle, pos, vel2 /* agent.Velocity */, - neighbourRegion.ExternalEndPoint, - capsPath, agent.UUID, agent.ControllingClient.SessionId, + endpoint, capsPath, agent.UUID, agent.ControllingClient.SessionId, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); } else { m_log.ErrorFormat("{0} Using old CrossRegion packet. Varregion will not work!!", LogHeader); - agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, - capsPath); + agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos, agent.Velocity, + endpoint,capsPath); } // SUCCESS! @@ -1800,11 +1864,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); - agent.CloseChildAgents(false, neighbourRegion.RegionHandle, neighbourRegion.RegionSizeX, neighbourRegion.RegionSizeY); + if(childRegionsToClose != null) + agent.CloseChildAgents(childRegionsToClose); // this may need the attachments - agent.HasMovedAway(true); + agent.HasMovedAway((agent.crossingFlags & 8) == 0); agent.MakeChildAgent(neighbourRegion.RegionHandle); @@ -1812,20 +1877,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // but not sure yet what the side effects would be. m_entityTransferStateMachine.ResetFromTransit(agent.UUID); - // 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); -// } - - //m_log.Debug("AFTER CROSS"); - //Scene.DumpChildrenSeeds(UUID); - //DumpKnownRegions(); - - return; + return true; } private void CrossAgentToNewRegionCompleted(IAsyncResult iar) @@ -1888,7 +1940,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer seeds.Add(regionhandler, agent.CapsPath); - // agent.ChildrenCapSeeds = new Dictionary(seeds); agent.ChildrenCapSeeds = null; @@ -2094,6 +2145,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { Thread.Sleep(200); // the original delay that was at InformClientOfNeighbourAsync start int count = 0; + IPEndPoint ipe; foreach (GridRegion neighbour in neighbours) { @@ -2102,8 +2154,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { if (newneighbours.Contains(handler)) { - InformClientOfNeighbourAsync(sp, cagents[count], neighbour, - neighbour.ExternalEndPoint, true); + ipe = neighbour.ExternalEndPoint; + if (ipe != null) + InformClientOfNeighbourAsync(sp, cagents[count], neighbour, ipe, true); + else + { + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: lost DNS resolution for neighbour {0}", neighbour.ExternalHostName); + } count++; } else if (!previousRegionNeighbourHandles.Contains(handler)) @@ -2135,7 +2192,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.Scene.RegionInfo.WorldLocY - neighbour.RegionLocY, 0f); } - + #endregion #region NotFoundLocationCache class // A collection of not found locations to make future lookups 'not found' lookups quick. @@ -2201,6 +2258,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } #endregion // NotFoundLocationCache class + #region getregions private NotFoundLocationCache m_notFoundLocationCache = new NotFoundLocationCache(); protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py) @@ -2218,9 +2276,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer protected GridRegion GetRegionContainingWorldLocation(IGridService pGridService, UUID pScopeID, double px, double py, uint pSizeHint) { - m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py); +// m_log.DebugFormat("{0} GetRegionContainingWorldLocation: call, XY=<{1},{2}>", LogHeader, px, py); GridRegion ret = null; - const double fudge = 2.0; if (m_notFoundLocationCache.Contains(px, py)) { @@ -2318,17 +2375,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (m_eqModule != null) { - #region IP Translation for NAT if(sp == null || sp.IsDeleted || sp.ClientView == null) // something bad already happened return; - IClientIPEndpoint ipepClient; - if (sp.ClientView.TryGet(out ipepClient)) - { - endPoint.Address = NetworkUtil.GetIPFor(ipepClient.EndPoint, endPoint.Address); - } - #endregion - m_log.DebugFormat("{0} {1} is sending {2} EnableSimulator for neighbour region {3}(loc=<{4},{5}>,siz=<{6},{7}>) " + "and EstablishAgentCommunication with seed cap {8}", LogHeader, scene.RegionInfo.RegionName, sp.Name, @@ -2620,7 +2669,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { // FIXME: It would be better to never add the scene object at all rather than add it and then delete // it - if (!Scene.Permissions.CanObjectEntry(so.UUID, true, so.AbsolutePosition)) + if (!Scene.Permissions.CanObjectEntry(so, true, so.AbsolutePosition)) { // Deny non attachments based on parcel settings // diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index 1ce69276b4..56c654f224 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer m_incomingSceneObjectEngine = new JobEngine( string.Format("HG Incoming Scene Object Engine ({0})", scene.Name), - "HG INCOMING SCENE OBJECT ENGINE"); + "HG INCOMING SCENE OBJECT ENGINE", 30000); StatsManager.RegisterStat( new Stat( diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 95e7456d3f..ba3a7c9062 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -541,16 +541,17 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess #region Permissions - private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) + private bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp) { if (m_bypassPermissions) return true; - if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(stealer)) - { - SceneObjectGroup sog = null; - if (m_Scene.TryGetSceneObjectGroup(objectID, out sog) && sog.OwnerID == stealer) - return true; + if(sp == null || sog == null) + return false; + if (!m_OutboundPermission && !UserManagementModule.IsLocalGridUser(sp.UUID)) + { + if (sog.OwnerID == sp.UUID) + return true; return false; } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 010482374c..788ed1c667 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -212,6 +212,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (m_Scene.TryGetScenePresence(remoteClient.AgentId, out presence)) { byte[] data = null; + uint everyonemask = 0; + uint groupmask = 0; if (invType == (sbyte)InventoryType.Landmark && presence != null) { @@ -220,6 +222,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess data = Encoding.ASCII.GetBytes(strdata); name = prefix + name; description += suffix; + groupmask = (uint)PermissionMask.AllAndExport; + everyonemask = (uint)(PermissionMask.AllAndExport & ~PermissionMask.Modify); } AssetBase asset = m_Scene.CreateAsset(name, description, assetType, data, remoteClient.AgentId); @@ -227,9 +231,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_Scene.CreateNewInventoryItem( remoteClient, remoteClient.AgentId.ToString(), string.Empty, folderID, name, description, 0, callbackID, asset.FullID, asset.Type, invType, - (uint)PermissionMask.All | (uint)PermissionMask.Export, // Base - (uint)PermissionMask.All | (uint)PermissionMask.Export, // Current - 0, nextOwnerMask, 0, creationDate, false); // Data from viewer + (uint)PermissionMask.AllAndExport, // Base + (uint)PermissionMask.AllAndExport, // Current + everyonemask, + nextOwnerMask, groupmask, creationDate, false); // Data from viewer } else { @@ -294,15 +299,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess else if ((CustomInventoryType)item.InvType == CustomInventoryType.AnimationSet) { AnimationSet animSet = new AnimationSet(data); - if (!animSet.Validate(x => { + uint res = animSet.Validate(x => { + const int required = (int)(PermissionMask.Transfer | PermissionMask.Copy); int perms = m_Scene.InventoryService.GetAssetPermissions(remoteClient.AgentId, x); - int required = (int)(PermissionMask.Transfer | PermissionMask.Copy); + // enforce previus perm rule if ((perms & required) != required) - return false; - return true; - })) + return 0; + return (uint) perms; + }); + if(res == 0) { - data = animSet.ToBytes(); + remoteClient.SendAgentAlertMessage("Not enought permissions on asset(s) referenced by animation set '{0}', update failed", false); + return UUID.Zero; } } @@ -407,7 +415,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess Dictionary originalPositions = new Dictionary(); Dictionary originalRotations = new Dictionary(); // this possible is not needed if keyframes are saved - Dictionary originalKeyframes = new Dictionary(); +// Dictionary originalKeyframes = new Dictionary(); foreach (SceneObjectGroup objectGroup in objlist) { @@ -418,8 +426,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess objectGroup.RootPart.SetForce(Vector3.Zero); objectGroup.RootPart.SetAngularImpulse(Vector3.Zero, false); - originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion; - objectGroup.RootPart.KeyframeMotion = null; +// originalKeyframes[objectGroup.UUID] = objectGroup.RootPart.KeyframeMotion; +// objectGroup.RootPart.KeyframeMotion = null; Vector3 inventoryStoredPosition = objectGroup.AbsolutePosition; originalPositions[objectGroup.UUID] = inventoryStoredPosition; @@ -427,20 +435,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess originalRotations[objectGroup.UUID] = inventoryStoredRotation; // Restore attachment data after trip through the sim - if (objectGroup.RootPart.AttachPoint > 0) + if (objectGroup.AttachmentPoint > 0) { inventoryStoredPosition = objectGroup.RootPart.AttachedPos; inventoryStoredRotation = objectGroup.RootPart.AttachRotation; - } + if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree && + objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree) + objectGroup.RootPart.Shape.LastAttachPoint = (byte)objectGroup.AttachmentPoint; - // Trees could be attached and it's been done, but it makes - // no sense. State must be preserved because it's the tree type - if (objectGroup.RootPart.Shape.PCode != (byte) PCode.Tree && - objectGroup.RootPart.Shape.PCode != (byte) PCode.NewTree) - { - objectGroup.RootPart.Shape.State = objectGroup.RootPart.AttachPoint; - if (objectGroup.RootPart.AttachPoint > 0) - objectGroup.RootPart.Shape.LastAttachPoint = objectGroup.RootPart.AttachPoint; } objectGroup.AbsolutePosition = inventoryStoredPosition; @@ -477,7 +479,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { objectGroup.AbsolutePosition = originalPositions[objectGroup.UUID]; objectGroup.RootPart.RotationOffset = originalRotations[objectGroup.UUID]; - objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID]; +// objectGroup.RootPart.KeyframeMotion = originalKeyframes[objectGroup.UUID]; if (objectGroup.RootPart.KeyframeMotion != null) objectGroup.RootPart.KeyframeMotion.Resume(); } @@ -579,41 +581,30 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess InventoryItemBase item, SceneObjectGroup so, List objsForEffectivePermissions, IClientAPI remoteClient) { - uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export) | 7; - uint allObjectsNextOwnerPerms = 0x7fffffff; - - // For the porposes of inventory, an object is modify if the prims - // are modify. This allows renaming an object that contains no - // mod items. + uint effectivePerms = (uint)(PermissionMask.Copy | PermissionMask.Transfer | PermissionMask.Modify | PermissionMask.Move | PermissionMask.Export | PermissionMask.FoldedMask); + foreach (SceneObjectGroup grp in objsForEffectivePermissions) { - uint groupPerms = grp.GetEffectivePermissions(true); - if ((grp.RootPart.BaseMask & (uint)PermissionMask.Modify) != 0) - groupPerms |= (uint)PermissionMask.Modify; - - effectivePerms &= groupPerms; + effectivePerms &= grp.CurrentAndFoldedNextPermissions(); } - effectivePerms |= (uint)PermissionMask.Move; - + if (remoteClient != null && (remoteClient.AgentId != so.RootPart.OwnerID) && m_Scene.Permissions.PropagatePermissions()) { - uint perms = effectivePerms; - uint nextPerms = (perms & 7) << 13; - if ((nextPerms & (uint)PermissionMask.Copy) == 0) - perms &= ~(uint)PermissionMask.Copy; - if ((nextPerms & (uint)PermissionMask.Transfer) == 0) - perms &= ~(uint)PermissionMask.Transfer; - if ((nextPerms & (uint)PermissionMask.Modify) == 0) - perms &= ~(uint)PermissionMask.Modify; - - item.BasePermissions = perms & so.RootPart.NextOwnerMask; - item.CurrentPermissions = item.BasePermissions; - item.NextPermissions = perms & so.RootPart.NextOwnerMask; - item.EveryOnePermissions = so.RootPart.EveryoneMask & so.RootPart.NextOwnerMask; - item.GroupPermissions = so.RootPart.GroupMask & so.RootPart.NextOwnerMask; + // apply parts inventory items next owner + PermissionsUtil.ApplyNoModFoldedPermissions(effectivePerms, ref effectivePerms); + // change to next owner + uint basePerms = effectivePerms & so.RootPart.NextOwnerMask; + // fix and update folded + basePerms = PermissionsUtil.FixAndFoldPermissions(basePerms); + + item.BasePermissions = basePerms; + item.CurrentPermissions = basePerms; + item.NextPermissions = basePerms & so.RootPart.NextOwnerMask; + item.EveryOnePermissions = basePerms & so.RootPart.EveryoneMask; + item.GroupPermissions = basePerms & so.RootPart.GroupMask; // apply next owner perms on rez - item.CurrentPermissions |= SceneObjectGroup.SLAM; + item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; } else { @@ -629,7 +620,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess (uint)PermissionMask.Modify | (uint)PermissionMask.Move | (uint)PermissionMask.Export | - 7); // Preserve folded permissions + (uint)PermissionMask.FoldedMask); // Preserve folded permissions ?? } return item; @@ -1001,11 +992,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // one full update during the attachment // process causes some clients to fail to display the // attachment properly. - m_Scene.AddNewSceneObject(group, true, false); if (!attachment) { group.AbsolutePosition = pos + veclist[i]; + m_Scene.AddNewSceneObject(group, true, false); // Fire on_rez group.CreateScriptInstances(0, true, m_Scene.DefaultScriptEngine, 1); @@ -1013,6 +1004,9 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess group.ScheduleGroupForFullUpdate(); } + else + m_Scene.AddNewSceneObject(group, true, false); + // m_log.DebugFormat( // "[INVENTORY ACCESS MODULE]: Rezzed {0} {1} {2} ownermask={3:X} nextownermask={4:X} groupmask={5:X} everyonemask={6:X} for {7}", @@ -1124,7 +1118,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess // rootPart.OwnerID, item.Owner, item.CurrentPermissions); if ((rootPart.OwnerID != item.Owner) || - (item.CurrentPermissions & 16) != 0 || + (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) { //Need to kill the for sale here @@ -1136,32 +1130,46 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectPart part in so.Parts) { part.GroupMask = 0; // DO NOT propagate here - - part.LastOwnerID = part.OwnerID; + if( part.OwnerID != part.GroupID) + part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.RezzerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); - // This applies the base mask from the item as the next - // permissions for the object. This is correct because the - // giver's base mask was masked by the giver's next owner - // mask, so the base mask equals the original next owner mask. - part.NextOwnerMask = item.BasePermissions; + // Reconstruct the original item's base permissions. They + // can be found in the lower (folded) bits. + if ((item.BasePermissions & (uint)PermissionMask.FoldedMask) != 0) + { + // We have permissions stored there so use them + part.NextOwnerMask = ((item.BasePermissions & (uint)PermissionMask.FoldedMask) << (int)PermissionMask.FoldingShift); + part.NextOwnerMask |= (uint)PermissionMask.Move; + } + else + { + // This is a legacy object and we can't avoid the issues that + // caused perms loss or escalation before, treat it the legacy + // way. + part.NextOwnerMask = item.NextPermissions; + } } so.ApplyNextOwnerPermissions(); // In case the user has changed flags on a received item // we have to apply those changes after the slam. Else we - // get a net loss of permissions + // get a net loss of permissions. + // On legacy objects, this opts for a loss of permissions rather + // than the previous handling that allowed escalation. foreach (SceneObjectPart part in so.Parts) { if ((item.Flags & (uint)InventoryItemFlags.ObjectHasMultipleItems) == 0) { + part.GroupMask = item.GroupPermissions & part.BaseMask; part.EveryoneMask = item.EveryOnePermissions & part.BaseMask; part.NextOwnerMask = item.NextPermissions & part.BaseMask; } } + } } else @@ -1180,6 +1188,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } rootPart.TrimPermissions(); + so.InvalidateDeepEffectivePerms(); if (isAttachment) so.FromItemID = item.ID; diff --git a/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs index 924a1a3c1a..2c74c0e0c0 100644 --- a/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs +++ b/OpenSim/Region/CoreModules/Framework/ServiceThrottle/ServiceThrottleModule.cs @@ -119,7 +119,15 @@ namespace OpenSim.Region.CoreModules.Framework if(!client.IsActive) return; - GridRegion r = m_scenes[0].GridService.GetRegionByUUID(UUID.Zero, regionID); + if(m_scenes.Count == 0) + return; + + Scene baseScene = m_scenes[0]; + + if(baseScene == null || baseScene.ShuttingDown) + return; + + GridRegion r = baseScene.GridService.GetRegionByUUID(UUID.Zero, regionID); if(!client.IsActive) return; diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 51f973a4c0..269546430f 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -175,6 +175,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement { client.OnNameFromUUIDRequest -= new UUIDNameRequest(HandleUUIDNameRequest); client.OnAvatarPickerRequest -= new AvatarPickerRequest(HandleAvatarPickerRequest); + client.OnConnectionClosed -= new Action(HandleConnectionClosed); } protected virtual void HandleUUIDNameRequest(UUID uuid, IClientAPI client) @@ -957,9 +958,14 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement public virtual bool IsLocalGridUser(UUID uuid) { - UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid); - if (account == null || (account != null && !account.LocalToGrid)) - return false; + lock (m_Scenes) + { + if (m_Scenes.Count == 0) + return true; + UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, uuid); + if (account == null || (account != null && !account.LocalToGrid)) + return false; + } return true; } diff --git a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs index 5d66d34a2b..8c44ee2f93 100644 --- a/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs +++ b/OpenSim/Region/CoreModules/Hypergrid/HGWorldMapModule.cs @@ -106,6 +106,8 @@ namespace OpenSim.Region.CoreModules.Hypergrid if (!m_Enabled) return; + base.RemoveRegion(scene); + scene.EventManager.OnClientClosed -= EventManager_OnClientClosed; } diff --git a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs index c369d87b05..090cb7d447 100644 --- a/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/DynamicTexture/DynamicTextureModule.cs @@ -135,17 +135,13 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture m_reuseableDynamicTextures.Store( GenerateReusableTextureKey(texture.InputCommands, texture.InputParams), newTextureID); } + updater.newTextureID = newTextureID; } - } - if (updater.UpdateTimer == 0) - { lock (Updaters) { - if (!Updaters.ContainsKey(updater.UpdaterID)) - { + if (Updaters.ContainsKey(updater.UpdaterID)) Updaters.Remove(updater.UpdaterID); - } } } } @@ -172,21 +168,20 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer) + string extraParams) { - return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, updateTimer, false, 255); + return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, false, 255); } public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + string extraParams, bool SetBlending, byte AlphaValue) { - return AddDynamicTextureURL(simID, primID, contentType, url, - extraParams, updateTimer, SetBlending, - (int)(DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); + return AddDynamicTextureURL(simID, primID, contentType, url, extraParams, SetBlending, + (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); } public UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, - string extraParams, int updateTimer, bool SetBlending, + string extraParams, bool SetBlending, int disp, byte AlphaValue, int face) { if (RenderPlugins.ContainsKey(contentType)) @@ -196,7 +191,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.PrimID = primID; updater.ContentType = contentType; updater.Url = url; - updater.UpdateTimer = updateTimer; updater.UpdaterID = UUID.Random(); updater.Params = extraParams; updater.BlendWithOldTexture = SetBlending; @@ -213,26 +207,27 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } RenderPlugins[contentType].AsyncConvertUrl(updater.UpdaterID, url, extraParams); - return updater.UpdaterID; + return updater.newTextureID; } return UUID.Zero; } public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer) + string extraParams) { - return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, false, 255); + return AddDynamicTextureData(simID, primID, contentType, data, extraParams, false, + (DISP_TEMP|DISP_EXPIRE), 255, ALL_SIDES); } public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer, bool SetBlending, byte AlphaValue) + string extraParams, bool SetBlending, byte AlphaValue) { - return AddDynamicTextureData(simID, primID, contentType, data, extraParams, updateTimer, SetBlending, - (int) (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); + return AddDynamicTextureData(simID, primID, contentType, data, extraParams, SetBlending, + (DISP_TEMP|DISP_EXPIRE), AlphaValue, ALL_SIDES); } public UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, - string extraParams, int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face) + string extraParams, bool SetBlending, int disp, byte AlphaValue, int face) { if (!RenderPlugins.ContainsKey(contentType)) return UUID.Zero; @@ -258,7 +253,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.PrimID = primID; updater.ContentType = contentType; updater.BodyData = data; - updater.UpdateTimer = updateTimer; updater.UpdaterID = UUID.Random(); updater.Params = extraParams; updater.BlendWithOldTexture = SetBlending; @@ -314,7 +308,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture updater.UpdatePart(part, (UUID)objReusableTextureUUID); } - return updater.UpdaterID; + return updater.newTextureID; } private string GenerateReusableTextureKey(string data, string extraParams) @@ -404,17 +398,15 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture public byte FrontAlpha = 255; public string Params; public UUID PrimID; - public bool SetNewFrontAlpha = false; public UUID SimUUID; public UUID UpdaterID; - public int UpdateTimer; public int Face; public int Disp; public string Url; + public UUID newTextureID; public DynamicTextureUpdater() { - UpdateTimer = 0; BodyData = null; } @@ -436,16 +428,23 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture // FIXME: Need to return the appropriate ID if only a single face is replaced. oldID = tmptex.DefaultTexture.TextureID; + // not using parts number of faces because that fails on old meshs if (Face == ALL_SIDES) { oldID = tmptex.DefaultTexture.TextureID; tmptex.DefaultTexture.TextureID = textureID; + for(int i = 0; i < tmptex.FaceTextures.Length; i++) + { + if(tmptex.FaceTextures[i] != null) + tmptex.FaceTextures[i].TextureID = textureID; + } } else { try { Primitive.TextureEntryFace texface = tmptex.CreateFace((uint)Face); + oldID = texface.TextureID; texface.TextureID = textureID; tmptex.FaceTextures[Face] = texface; } @@ -455,10 +454,6 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture } } - // 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()); } @@ -491,13 +486,26 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture if (BlendWithOldTexture) { - Primitive.TextureEntryFace defaultFace = part.Shape.Textures.DefaultTexture; - if (defaultFace != null) + Primitive.TextureEntryFace curFace; + if(Face == ALL_SIDES) + curFace = part.Shape.Textures.DefaultTexture; + else { - oldAsset = scene.AssetService.Get(defaultFace.TextureID.ToString()); + try + { + curFace = part.Shape.Textures.GetFace((uint)Face); + } + catch + { + curFace = null; + } + } + if (curFace != null) + { + oldAsset = scene.AssetService.Get(curFace.TextureID.ToString()); if (oldAsset != null) - assetData = BlendTextures(data, oldAsset.Data, SetNewFrontAlpha, FrontAlpha); + assetData = BlendTextures(data, oldAsset.Data, FrontAlpha); } } @@ -548,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture return asset.FullID; } - private byte[] BlendTextures(byte[] frontImage, byte[] backImage, bool setNewAlpha, byte newAlpha) + private byte[] BlendTextures(byte[] frontImage, byte[] backImage, byte newAlpha) { ManagedImage managedImage; Image image; @@ -568,7 +576,7 @@ namespace OpenSim.Region.CoreModules.Scripting.DynamicTexture Bitmap image2 = new Bitmap(image); image.Dispose(); - if (setNewAlpha) + if (newAlpha < 255) SetAlpha(ref image1, newAlpha); using(Bitmap joint = MergeBitMaps(image1, image2)) diff --git a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs index 09891f7876..f5b575bec3 100644 --- a/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs +++ b/OpenSim/Region/CoreModules/Scripting/HttpRequest/ScriptsHttpRequests.cs @@ -223,20 +223,16 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest if (parms.Length - i < 2) break; - //Have we reached the end of the list of headers? - //End is marked by a string with a single digit. - //We already know we have at least one parameter - //so it is safe to do this check at top of loop. - if (Char.IsDigit(parms[i][0])) - break; - if (htc.HttpCustomHeaders == null) htc.HttpCustomHeaders = new List(); htc.HttpCustomHeaders.Add(parms[i]); htc.HttpCustomHeaders.Add(parms[i+1]); + int nexti = i + 2; + if (nexti >= parms.Length || Char.IsDigit(parms[nexti][0])) + break; - i += 2; + i = nexti; } break; @@ -383,9 +379,9 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest if (ThreadPool == null) { STPStartInfo startInfo = new STPStartInfo(); - startInfo.IdleTimeout = 20000; + startInfo.IdleTimeout = 2000; startInfo.MaxWorkerThreads = maxThreads; - startInfo.MinWorkerThreads = 1; + startInfo.MinWorkerThreads = 0; startInfo.ThreadPriority = ThreadPriority.BelowNormal; startInfo.StartSuspended = true; startInfo.ThreadPoolName = "ScriptsHttpReq"; @@ -419,6 +415,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest public void Close() { + ThreadPool.Shutdown(); } public string Name @@ -542,6 +539,7 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest { Request = (HttpWebRequest)WebRequest.Create(Url); Request.AllowAutoRedirect = false; + Request.KeepAlive = false; //This works around some buggy HTTP Servers like Lighttpd Request.ServicePoint.Expect100Continue = false; @@ -667,12 +665,6 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest Status = (int)OSHttpStatusCode.ClientErrorJoker; ResponseBody = e.Message; } - - if (ResponseBody == null) - ResponseBody = String.Empty; - - _finished = true; - return; } catch (Exception e) { @@ -731,13 +723,10 @@ namespace OpenSim.Region.CoreModules.Scripting.HttpRequest else { _finished = true; + if (ResponseBody == null) + ResponseBody = String.Empty; } } - - if (ResponseBody == null) - ResponseBody = String.Empty; - - _finished = true; } public void Stop() diff --git a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs index bb80a88298..11fc513e0d 100644 --- a/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/LSLHttp/UrlModule.cs @@ -26,10 +26,11 @@ */ using System; -using System.Threading; using System.Collections.Generic; using System.Collections; using System.Reflection; +using System.Net; +using System.Net.Sockets; using log4net; using Mono.Addins; using Nini.Config; @@ -83,17 +84,19 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); - private Dictionary m_RequestMap = + protected Dictionary m_RequestMap = new Dictionary(); - private Dictionary m_UrlMap = + protected Dictionary m_UrlMap = new Dictionary(); - private uint m_HttpsPort = 0; - private IHttpServer m_HttpServer = null; - private IHttpServer m_HttpsServer = null; + protected bool m_enabled = false; + protected string m_ErrorStr; + protected uint m_HttpsPort = 0; + protected IHttpServer m_HttpServer = null; + protected IHttpServer m_HttpsServer = null; - public string ExternalHostNameForLSL { get; private set; } + public string ExternalHostNameForLSL { get; protected set; } /// /// The default maximum number of urls @@ -107,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public Type ReplaceableInterface { - get { return null; } + get { return typeof(IUrlModule); } } public string Name @@ -118,6 +121,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void Initialise(IConfigSource config) { IConfig networkConfig = config.Configs["Network"]; + m_enabled = false; if (networkConfig != null) { @@ -128,9 +132,31 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp if (ssl_enabled) m_HttpsPort = (uint)config.Configs["Network"].GetInt("https_port", (int)m_HttpsPort); } + else + { + m_ErrorStr = "[Network] configuration missing, HTTP listener for LSL disabled"; + m_log.Warn("[URL MODULE]: " + m_ErrorStr); + return; + } - if (ExternalHostNameForLSL == null) - ExternalHostNameForLSL = System.Environment.MachineName; + if (String.IsNullOrWhiteSpace(ExternalHostNameForLSL)) + { + m_ErrorStr = "ExternalHostNameForLSL not defined in configuration, HTTP listener for LSL disabled"; + m_log.Warn("[URL MODULE]: " + m_ErrorStr); + return; + } + + IPAddress ia = null; + ia = Util.GetHostFromDNS(ExternalHostNameForLSL); + if (ia == null) + { + m_ErrorStr = "Could not resolve ExternalHostNameForLSL, HTTP listener for LSL disabled"; + m_log.Warn("[URL MODULE]: " + m_ErrorStr); + return; + } + + m_enabled = true; + m_ErrorStr = String.Empty; IConfig llFunctionsConfig = config.Configs["LL-Functions"]; @@ -146,7 +172,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp public void AddRegion(Scene scene) { - if (m_HttpServer == null) + if (m_enabled && m_HttpServer == null) { // There can only be one // @@ -197,11 +223,18 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { UUID urlcode = UUID.Random(); + if(!m_enabled) + { + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr }); + return urlcode; + } + lock (m_UrlMap) { if (m_UrlMap.Count >= TotalUrls) { - engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", + "Too many URLs already open" }); return urlcode; } string url = "http://" + ExternalHostNameForLSL + ":" + m_HttpServer.Port.ToString() + "/lslhttp/" + urlcode.ToString() + "/"; @@ -243,6 +276,12 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { UUID urlcode = UUID.Random(); + if(!m_enabled) + { + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", m_ErrorStr }); + return urlcode; + } + if (m_HttpsServer == null) { engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); @@ -253,7 +292,8 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp { if (m_UrlMap.Count >= TotalUrls) { - engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", "" }); + engine.PostScriptEvent(itemID, "http_request", new Object[] { urlcode.ToString(), "URL_REQUEST_DENIED", + "Too many URLs already open" }); return urlcode; } string url = "https://" + ExternalHostNameForLSL + ":" + m_HttpsServer.Port.ToString() + "/lslhttps/" + urlcode.ToString() + "/"; @@ -453,7 +493,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } - private void RemoveUrl(UrlData data) + protected void RemoveUrl(UrlData data) { if (data.isSsl) m_HttpsServer.RemoveHTTPHandler("", "/lslhttps/"+data.urlcode.ToString()+"/"); @@ -461,7 +501,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp m_HttpServer.RemoveHTTPHandler("", "/lslhttp/"+data.urlcode.ToString()+"/"); } - private Hashtable NoEvents(UUID requestID, UUID sessionID) + protected Hashtable NoEvents(UUID requestID, UUID sessionID) { Hashtable response = new Hashtable(); UrlData url; @@ -499,7 +539,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp return response; } - private bool HasEvents(UUID requestID, UUID sessionID) + protected bool HasEvents(UUID requestID, UUID sessionID) { UrlData url=null; @@ -530,7 +570,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } } } - private Hashtable GetEvents(UUID requestID, UUID sessionID) + protected Hashtable GetEvents(UUID requestID, UUID sessionID) { UrlData url = null; RequestData requestData = null; @@ -735,7 +775,7 @@ namespace OpenSim.Region.CoreModules.Scripting.LSLHttp } } - private void OnScriptReset(uint localID, UUID itemID) + protected void OnScriptReset(uint localID, UUID itemID) { ScriptRemoved(itemID); } diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs index ed255bfcb3..325f7f9ccf 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/Tests/VectorRenderModuleTests.cs @@ -77,8 +77,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests 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)); } @@ -98,8 +97,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -108,8 +106,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -129,8 +126,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -139,8 +135,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "alpha:250", - 0); + "alpha:250"); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -161,8 +156,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -171,8 +165,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -191,8 +184,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests 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)); } @@ -213,8 +205,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -223,8 +214,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -253,8 +243,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "1024", - 0); + "1024"); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -263,8 +252,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "1024", - 0); + "1024"); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -284,8 +272,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -294,8 +281,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "alpha:250", - 0); + "alpha:250"); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } @@ -316,8 +302,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); UUID firstDynamicTextureID = so.RootPart.Shape.Textures.GetFace(0).TextureID; @@ -326,8 +311,7 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender.Tests so.UUID, m_vrm.GetContentType(), dtText, - "", - 0); + ""); Assert.That(firstDynamicTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); } diff --git a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs index f12286dafd..8a26ab7b37 100644 --- a/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/VectorRender/VectorRenderModule.cs @@ -355,30 +355,22 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender lock (this) { if (alpha == 256) - bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); - else - bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); - - 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) { + bitmap = new Bitmap(width, height, PixelFormat.Format32bppRgb); + graph = Graphics.FromImage(bitmap); using (SolidBrush bgFillBrush = new SolidBrush(bgColor)) { graph.FillRectangle(bgFillBrush, 0, 0, width, height); } - } - - for (int w = 0; w < bitmap.Width; w++) + } + else { - if (alpha <= 255) + bitmap = new Bitmap(width, height, PixelFormat.Format32bppArgb); + graph = Graphics.FromImage(bitmap); + Color newbg = Color.FromArgb(alpha,bgColor); + using (SolidBrush bgFillBrush = new SolidBrush(newbg)) { - for (int h = 0; h < bitmap.Height; h++) - { - bitmap.SetPixel(w, h, Color.FromArgb(alpha, bitmap.GetPixel(w, h))); - } + graph.FillRectangle(bgFillBrush, 0, 0, width, height); } } @@ -519,8 +511,32 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender // m_log.DebugFormat("[VECTOR RENDER MODULE]: Processing line '{0}'", nextLine); + if (nextLine.StartsWith("ResetTransf")) + { + graph.ResetTransform(); + } + else if (nextLine.StartsWith("TransTransf")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y); + graph.TranslateTransform(x, y); + } + else if (nextLine.StartsWith("ScaleTransf")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y); + graph.ScaleTransform(x, y); + } + else if (nextLine.StartsWith("RotTransf")) + { + float x = 0; + GetParams(partsDelimiter, ref nextLine, 9, ref x); + graph.RotateTransform(x); + } //replace with switch, or even better, do some proper parsing - if (nextLine.StartsWith("MoveTo")) + else if (nextLine.StartsWith("MoveTo")) { float x = 0; float y = 0; @@ -625,6 +641,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender startPoint.X += endPoint.X; startPoint.Y += endPoint.Y; } + else if (nextLine.StartsWith("FillEllipse")) + { + float x = 0; + float y = 0; + GetParams(partsDelimiter, ref nextLine, 11, ref x, ref y); + endPoint.X = (int)x; + endPoint.Y = (int)y; + graph.FillEllipse(myBrush, startPoint.X, startPoint.Y, endPoint.X, endPoint.Y); + startPoint.X += endPoint.X; + startPoint.Y += endPoint.Y; + } else if (nextLine.StartsWith("FontSize")) { nextLine = nextLine.Remove(0, 8); @@ -790,6 +817,17 @@ namespace OpenSim.Region.CoreModules.Scripting.VectorRender } } + private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x) + { + line = line.Remove(0, startLength); + string[] parts = line.Split(partsDelimiter); + if (parts.Length > 0) + { + string xVal = parts[0].Trim(); + x = Convert.ToSingle(xVal, CultureInfo.InvariantCulture); + } + } + private static void GetParams(char[] partsDelimiter, ref string line, int startLength, ref float x, ref float y) { line = line.Remove(0, startLength); diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index 660e03f232..a5203ea750 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -113,7 +113,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm // wrap this in a try block so that defaults will work if // the config file doesn't specify otherwise. int maxlisteners = 1000; - int maxhandles = 64; + int maxhandles = 65; try { m_whisperdistance = config.Configs["Chat"].GetInt( @@ -130,8 +130,15 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm catch (Exception) { } - if (maxlisteners < 1) maxlisteners = int.MaxValue; - if (maxhandles < 1) maxhandles = int.MaxValue; + + if (maxlisteners < 1) + maxlisteners = int.MaxValue; + if (maxhandles < 1) + maxhandles = int.MaxValue; + + if (maxlisteners < maxhandles) + maxlisteners = maxhandles; + m_listenerManager = new ListenerManager(maxlisteners, maxhandles); m_pendingQ = new Queue(); m_pending = Queue.Synchronized(m_pendingQ); @@ -605,11 +612,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm li.GetHandle().Equals(handle)) { lis.Value.Remove(li); + m_curlisteners--; if (lis.Value.Count == 0) - { - m_listeners.Remove(lis.Key); - m_curlisteners--; - } + m_listeners.Remove(lis.Key); // bailing of loop so this does not smoke // there should be only one, so we bail out early return; } @@ -718,6 +723,9 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm } } + if(handles.Count >= m_maxhandles) + return -1; + // Note: 0 is NOT a valid handle for llListen() to return for (int i = 1; i <= m_maxhandles; i++) { diff --git a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs index aed137231d..6028eefd37 100644 --- a/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/XMLRPC/XMLRPCModule.cs @@ -658,7 +658,7 @@ namespace OpenSim.Region.CoreModules.Scripting.XMLRPC public void Process() { _finished = false; - httpThread = WorkManager.StartThread(SendRequest, "HttpRequestThread", ThreadPriority.BelowNormal, true, false); + httpThread = WorkManager.StartThread(SendRequest, "XMLRPCreqThread", ThreadPriority.BelowNormal, true, false, null, int.MaxValue); } /* diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs index 21483c5e9e..fb8c3065d8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Land/LandServiceInConnectorModule.cs @@ -151,7 +151,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Land x = rx - s.RegionInfo.WorldLocX; y = ry - s.RegionInfo.WorldLocY; regionAccess = s.RegionInfo.AccessLevel; - return s.GetLandData(x, y); + LandData land = s.GetLandData(x, y); + IDwellModule dwellModule = s.RequestModuleInterface(); + if (dwellModule != null) + land.Dwell = dwellModule.GetDwell(land); + return land; } } m_log.DebugFormat("[LAND IN CONNECTOR]: region handle {0} not found", regionHandle); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs index 9e75ee2259..2e6f472399 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs @@ -85,12 +85,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile public LocalUserProfilesServicesConnector() { - m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params"); + //m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector no params"); } public LocalUserProfilesServicesConnector(IConfigSource source) { - m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly."); + //m_log.Debug("[LOCAL USERPROFILES SERVICE CONNECTOR]: LocalUserProfileServicesConnector instantiated directly."); InitialiseService(source); } @@ -104,7 +104,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile IConfig config = source.Configs[ConfigName]; if (config == null) { - m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini"); + //m_log.Error("[LOCAL USERPROFILES SERVICE CONNECTOR]: UserProfilesService missing from OpenSim.ini"); return; } @@ -225,4 +225,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile } #endregion } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index f5aa9716d9..92ae36fbb6 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -209,7 +209,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (m_Cache != null) { - asset = m_Cache.Get(id); + if (!m_Cache.Get(id, out asset)) + return null; if (asset != null) return asset; @@ -238,10 +239,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset public AssetBase GetCached(string id) { + AssetBase asset = null; if (m_Cache != null) - return m_Cache.Get(id); + m_Cache.Get(id, out asset); - return null; + return asset; } public AssetMetadata GetMetadata(string id) @@ -250,8 +252,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (m_Cache != null) { - if (m_Cache != null) - m_Cache.Get(id); + if (!m_Cache.Get(id, out asset)) + return null; if (asset != null) return asset.Metadata; @@ -273,8 +275,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (m_Cache != null) { - if (m_Cache != null) - m_Cache.Get(id); + if (!m_Cache.Get(id, out asset)) + return null; if (asset != null) return asset.Data; @@ -292,7 +294,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset AssetBase asset = null; if (m_Cache != null) - asset = m_Cache.Get(id); + { + if (!m_Cache.Get(id, out asset)) + return false; + } if (asset != null) { @@ -382,7 +387,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset AssetBase asset = null; if (m_Cache != null) - asset = m_Cache.Get(id); + m_Cache.Get(id, out asset); if (asset != null) { diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs index 7190aa09ed..37a48bb752 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/LocalAssetServiceConnector.cs @@ -158,7 +158,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset AssetBase asset = null; if (m_Cache != null) - asset = m_Cache.Get(id); + { + if (!m_Cache.Get(id, out asset)) + return null; + } if (asset == null) { @@ -177,17 +180,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset { // m_log.DebugFormat("[LOCAL ASSET SERVICES CONNECTOR]: Cache request for {0}", id); + AssetBase asset = null; if (m_Cache != null) - return m_Cache.Get(id); + m_Cache.Get(id, out asset); - return null; + return asset; } public AssetMetadata GetMetadata(string id) { AssetBase asset = null; if (m_Cache != null) - asset = m_Cache.Get(id); + { + if (!m_Cache.Get(id, out asset)) + return null; + } if (asset != null) return asset.Metadata; @@ -210,7 +217,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset AssetBase asset = null; if (m_Cache != null) - asset = m_Cache.Get(id); + { + if (!m_Cache.Get(id, out asset)) + return null; + } if (asset != null) return asset.Data; @@ -232,7 +242,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset if (m_Cache != null) { - AssetBase asset = m_Cache.Get(id); + AssetBase asset; + if (!m_Cache.Get(id, out asset)) + return false; if (asset != null) { @@ -287,7 +299,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset { AssetBase asset = null; if (m_Cache != null) - m_Cache.Get(id); + m_Cache.Get(id, out asset); if (asset != null) { asset.Data = data; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs index 84e52f7602..f6fff58aef 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RegionInfoCache.cs @@ -385,7 +385,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid storage[handle] = region; byname[region.RegionName] = handle; byuuid[region.RegionID] = handle; - } public void Remove(GridRegion region) @@ -400,7 +399,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid ulong handle = region.RegionHandle & HANDLEMASK; if(storage != null) - storage.Remove(handle); + { + if(storage.ContainsKey(handle)) + { + storage[handle] = null; + storage.Remove(handle); + } + } removeFromInner(region); if(expires != null) { @@ -424,6 +429,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid if(byuuid != null) byuuid.Remove(r.RegionID); removeFromInner(r); + storage[handle] = null; } storage.Remove(handle); } @@ -581,27 +587,32 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid { if(expires == null || expires.Count == 0) return 0; - + + int expiresCount = expires.Count; List toexpire = new List(); + foreach(KeyValuePair kvp in expires) { if(kvp.Value < now) toexpire.Add(kvp.Key); } - if(toexpire.Count == 0) - return expires.Count; + int toexpireCount = toexpire.Count; + if(toexpireCount == 0) + return expiresCount; - if(toexpire.Count == expires.Count) + if(toexpireCount == expiresCount) { Clear(); return 0; } - foreach(ulong h in toexpire) + if(storage != null) { - if(storage != null) + ulong h; + for(int i = 0; i < toexpireCount; i++) { + h = toexpire[i]; if(storage.ContainsKey(h)) { GridRegion r = storage[h]; @@ -610,14 +621,22 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid if(byuuid != null) byuuid.Remove(r.RegionID); removeFromInner(r); + + storage[h] = null; + storage.Remove(h); } - storage.Remove(h); + if(expires != null) + expires.Remove(h); } - if(expires != null) - expires.Remove(h); + } + else + { + Clear(); + return 0; } - if(expires.Count == 0) + expiresCount = expires.Count; + if(expiresCount == 0) { byname = null; byuuid = null; @@ -626,7 +645,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid return 0; } - return expires.Count; + return expiresCount; } public int Count() @@ -693,7 +712,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public class RegionsExpiringCache { - const double CACHE_PURGE_HZ = 60; // seconds + const double CACHE_PURGE_TIME = 60000; // milliseconds const int MAX_LOCK_WAIT = 10000; // milliseconds /// For thread safety @@ -702,7 +721,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid object isPurging = new object(); Dictionary InfobyScope = new Dictionary(); - private System.Timers.Timer timer = new System.Timers.Timer(TimeSpan.FromSeconds(CACHE_PURGE_HZ).TotalMilliseconds); + private System.Timers.Timer timer = new System.Timers.Timer(CACHE_PURGE_TIME); public RegionsExpiringCache() { @@ -965,7 +984,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid if (expiredscopes.Count > 0) { foreach (UUID sid in expiredscopes) + { + InfobyScope[sid] = null; InfobyScope.Remove(sid); + } } } finally { Monitor.Exit(syncRoot); } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index 5efdd9b7cf..7a4f981da6 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -250,7 +250,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (inventoryURL != null && inventoryURL != string.Empty) { inventoryURL = inventoryURL.Trim(new char[] { '/' }); - m_InventoryURLs[userID] = inventoryURL; + lock (m_InventoryURLs) + m_InventoryURLs[userID] = inventoryURL; m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL); return; } @@ -268,35 +269,42 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (!string.IsNullOrEmpty(inventoryURL)) { inventoryURL = inventoryURL.Trim(new char[] { '/' }); - m_InventoryURLs.Add(userID, inventoryURL); + lock (m_InventoryURLs) + m_InventoryURLs[userID] = inventoryURL; m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Added {0} to the cache of inventory URLs", inventoryURL); } - } - } } private void DropInventoryServiceURL(UUID userID) { lock (m_InventoryURLs) + { if (m_InventoryURLs.ContainsKey(userID)) { string url = m_InventoryURLs[userID]; m_InventoryURLs.Remove(userID); m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Removed {0} from the cache of inventory URLs", url); } + } } public string GetInventoryServiceURL(UUID userID) { - if (m_InventoryURLs.ContainsKey(userID)) - return m_InventoryURLs[userID]; + lock (m_InventoryURLs) + { + if (m_InventoryURLs.ContainsKey(userID)) + return m_InventoryURLs[userID]; + } CacheInventoryServiceURL(userID); - if (m_InventoryURLs.ContainsKey(userID)) - return m_InventoryURLs[userID]; + lock (m_InventoryURLs) + { + if (m_InventoryURLs.ContainsKey(userID)) + return m_InventoryURLs[userID]; + } return null; //it means that the methods should forward to local grid's inventory diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs index cad2061946..8baf41a3d9 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Land/LocalLandServiceConnector.cs @@ -143,6 +143,10 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Land { LandData land = s.GetLandData(x, y); regionAccess = s.RegionInfo.AccessLevel; + IDwellModule dwellModule = s.RequestModuleInterface(); + if (dwellModule != null) + land.Dwell = dwellModule.GetDwell(land); + return land; } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/NeighbourServiceOutConnector.cs similarity index 72% rename from OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs rename to OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/NeighbourServiceOutConnector.cs index e8d01b01c1..60addec12c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/NeighbourServiceOutConnector.cs @@ -25,44 +25,32 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; -using System.Collections.Generic; -using System.Reflection; using log4net; using Mono.Addins; +using System; +using System.Reflection; +using System.Collections.Generic; using Nini.Config; -using OpenMetaverse; using OpenSim.Framework; -using OpenSim.Server.Base; +using OpenSim.Services.Connectors; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; + namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour { - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "LocalNeighbourServicesConnector")] - public class LocalNeighbourServicesConnector : - ISharedRegionModule, INeighbourService + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "NeighbourServicesOutConnector")] + public class NeighbourServicesOutConnector : + NeighbourServicesConnector, ISharedRegionModule, INeighbourService { private static readonly ILog m_log = LogManager.GetLogger( MethodBase.GetCurrentMethod().DeclaringType); private List m_Scenes = new List(); - private bool m_Enabled = false; - public LocalNeighbourServicesConnector() - { - } - - public LocalNeighbourServicesConnector(List scenes) - { - m_Scenes = scenes; - } - - #region ISharedRegionModule - public Type ReplaceableInterface { get { return null; } @@ -70,7 +58,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour public string Name { - get { return "LocalNeighbourServicesConnector"; } + get { return "NeighbourServicesOutConnector"; } } public void Initialise(IConfigSource source) @@ -78,39 +66,32 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour IConfig moduleConfig = source.Configs["Modules"]; if (moduleConfig != null) { - string name = moduleConfig.GetString("NeighbourServices", this.Name); + string name = moduleConfig.GetString("NeighbourServices"); if (name == Name) { - // m_Enabled rules whether this module registers as INeighbourService or not m_Enabled = true; - m_log.Info("[NEIGHBOUR CONNECTOR]: Local neighbour connector enabled"); + m_log.Info("[NEIGHBOUR CONNECTOR]: Neighbour out connector enabled"); } } } + public void PostInitialise() + { + } + public void Close() { } public void AddRegion(Scene scene) { - m_Scenes.Add(scene); - if (!m_Enabled) return; + m_Scenes.Add(scene); scene.RegisterModuleInterface(this); } - public void RegionLoaded(Scene scene) - { - m_log.Info("[NEIGHBOUR CONNECTOR]: Local neighbour connector enabled for region " + scene.RegionInfo.RegionName); - } - - public void PostInitialise() - { - } - public void RemoveRegion(Scene scene) { // Always remove @@ -118,28 +99,36 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour m_Scenes.Remove(scene); } - #endregion ISharedRegionModule + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + + m_GridService = scene.GridService; + m_log.InfoFormat("[NEIGHBOUR CONNECTOR]: Enabled out neighbours for region {0}", scene.RegionInfo.RegionName); + + } #region INeighbourService - public OpenSim.Services.Interfaces.GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion) + public override GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion) { - uint x, y; - Util.RegionHandleToRegionLoc(regionHandle, out x, out y); + if (!m_Enabled) + return null; foreach (Scene s in m_Scenes) { if (s.RegionInfo.RegionHandle == regionHandle) { - m_log.DebugFormat("[LOCAL NEIGHBOUR SERVICE CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}", - thisRegion.RegionName, s.Name, x, y ); - - //m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour"); +// uint x, y; +// Util.RegionHandleToRegionLoc(regionHandle, out x, out y); +// m_log.DebugFormat("[NEIGHBOUR SERVICE OUT CONNECTOR]: HelloNeighbour from region {0} to neighbour {1} at {2}-{3}", +// thisRegion.RegionName, s.Name, x, y ); return s.IncomingHelloNeighbour(thisRegion); } } - //m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: region handle {0} not found", regionHandle); - return null; + + return base.HelloNeighbour(regionHandle, thisRegion); } #endregion INeighbourService diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs deleted file mode 100644 index fcb55216ec..0000000000 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/RemoteNeighourServiceConnector.cs +++ /dev/null @@ -1,157 +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 log4net; -using Mono.Addins; -using System; -using System.Collections.Generic; -using System.Reflection; -using Nini.Config; -using OpenSim.Framework; -using OpenSim.Services.Connectors; -using OpenSim.Region.Framework.Interfaces; -using OpenSim.Region.Framework.Scenes; -using OpenSim.Services.Interfaces; -using OpenSim.Server.Base; - -namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour -{ - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "RemoteNeighbourServicesConnector")] - public class RemoteNeighbourServicesConnector : - NeighbourServicesConnector, ISharedRegionModule, INeighbourService - { - private static readonly ILog m_log = - LogManager.GetLogger( - MethodBase.GetCurrentMethod().DeclaringType); - - private bool m_Enabled = false; - private LocalNeighbourServicesConnector m_LocalService; - //private string serviceDll; - //private List m_Scenes = new List(); - - public Type ReplaceableInterface - { - get { return null; } - } - - public string Name - { - get { return "RemoteNeighbourServicesConnector"; } - } - - public void Initialise(IConfigSource source) - { - IConfig moduleConfig = source.Configs["Modules"]; - if (moduleConfig != null) - { - string name = moduleConfig.GetString("NeighbourServices"); - if (name == Name) - { - m_LocalService = new LocalNeighbourServicesConnector(); - - //IConfig neighbourConfig = source.Configs["NeighbourService"]; - //if (neighbourConfig == null) - //{ - // m_log.Error("[NEIGHBOUR CONNECTOR]: NeighbourService missing from OpenSim.ini"); - // return; - //} - //serviceDll = neighbourConfig.GetString("LocalServiceModule", String.Empty); - //if (serviceDll == String.Empty) - //{ - // m_log.Error("[NEIGHBOUR CONNECTOR]: No LocalServiceModule named in section NeighbourService"); - // return; - //} - - m_Enabled = true; - - m_log.Info("[NEIGHBOUR CONNECTOR]: Remote Neighbour connector enabled"); - } - } - } - - public void PostInitialise() - { - //if (m_Enabled) - //{ - // Object[] args = new Object[] { m_Scenes }; - // m_LocalService = - // ServerUtils.LoadPlugin(serviceDll, - // args); - - // if (m_LocalService == null) - // { - // m_log.Error("[NEIGHBOUR CONNECTOR]: Can't load neighbour service"); - // Unregister(); - // return; - // } - //} - } - - public void Close() - { - } - - public void AddRegion(Scene scene) - { - if (!m_Enabled) - return; - - m_LocalService.AddRegion(scene); - scene.RegisterModuleInterface(this); - } - - public void RemoveRegion(Scene scene) - { - if (m_Enabled) - m_LocalService.RemoveRegion(scene); - } - - public void RegionLoaded(Scene scene) - { - if (!m_Enabled) - return; - - m_GridService = scene.GridService; - - m_log.InfoFormat("[NEIGHBOUR CONNECTOR]: Enabled remote neighbours for region {0}", scene.RegionInfo.RegionName); - - } - - #region INeighbourService - - public override GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion) - { - GridRegion region = m_LocalService.HelloNeighbour(regionHandle, thisRegion); - if (region != null) - return region; - - return base.HelloNeighbour(regionHandle, thisRegion); - } - - #endregion INeighbourService - } -} diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 6ba8cec22f..99ff9b5ac4 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -285,6 +285,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// Dearchive the region embodied in this request. /// public void DearchiveRegion() + { + DearchiveRegion(true); + } + + public void DearchiveRegion(bool shouldStartScripts) { int successfulAssetRestores = 0; int failedAssetRestores = 0; @@ -425,22 +430,25 @@ namespace OpenSim.Region.CoreModules.World.Archiver // 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. - WorkManager.RunInThread(o => + if (shouldStartScripts) { - Thread.Sleep(15000); - m_log.Info("[ARCHIVER]: Starting scripts in scene objects"); - - foreach (DearchiveContext sceneContext in sceneContexts.Values) + WorkManager.RunInThread(o => { - foreach (SceneObjectGroup sceneObject in sceneContext.SceneObjects) - { - sceneObject.CreateScriptInstances(0, false, sceneContext.Scene.DefaultScriptEngine, 0); // StateSource.RegionStart - sceneObject.ResumeScripts(); - } + Thread.Sleep(15000); + m_log.Info("[ARCHIVER]: Starting scripts in scene objects"); - sceneContext.SceneObjects.Clear(); - } - }, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId)); + 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(); + } + }, null, string.Format("ReadArchiveStartScripts (request {0})", m_requestId)); + } m_log.InfoFormat("[ARCHIVER]: Successfully loaded archive"); diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs index 8dabceeba7..11c53d75d0 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequest.cs @@ -181,11 +181,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver // Archive the regions Dictionary assetUuids = new Dictionary(); + HashSet failedIDs = new HashSet(); + HashSet uncertainAssetsUUIDs = new HashSet(); scenesGroup.ForEachScene(delegate(Scene scene) { string regionDir = MultiRegionFormat ? scenesGroup.GetRegionDir(scene.RegionInfo.RegionID) : ""; - ArchiveOneRegion(scene, regionDir, assetUuids); + ArchiveOneRegion(scene, regionDir, assetUuids, failedIDs, uncertainAssetsUUIDs); }); // Archive the assets @@ -193,23 +195,21 @@ namespace OpenSim.Region.CoreModules.World.Archiver 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( + + AssetsRequest ar = new AssetsRequest( new AssetsArchiver(m_archiveWriter), assetUuids, + failedIDs.Count, m_rootScene.AssetService, m_rootScene.UserAccountService, - m_rootScene.RegionInfo.ScopeID, options, ReceivedAllAssets); - - WorkManager.RunInThread(o => ar.Execute(), null, "Archive Assets Request"); - - // CloseArchive() will be called from ReceivedAllAssets() + m_rootScene.RegionInfo.ScopeID, options, null); + ar.Execute(); + assetUuids = null; } else { m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); - CloseArchive(string.Empty); +// CloseArchive(string.Empty); } + CloseArchive(string.Empty); } catch (Exception e) { @@ -218,7 +218,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids) + private void ArchiveOneRegion(Scene scene, string regionDir, Dictionary assetUuids, + HashSet failedIDs, HashSet uncertainAssetsUUIDs) { m_log.InfoFormat("[ARCHIVER]: Writing region {0}", scene.Name); @@ -237,7 +238,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver { SceneObjectGroup sceneObject = (SceneObjectGroup)entity; - if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) + if (!sceneObject.IsDeleted && !sceneObject.IsAttachment && !sceneObject.IsTemporary && !sceneObject.inTransit) { if (!CanUserArchiveObject(scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, FilterContent, permissionsModule)) { @@ -254,17 +255,39 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (SaveAssets) { - UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids); + UuidGatherer assetGatherer = new UuidGatherer(scene.AssetService, assetUuids, failedIDs, uncertainAssetsUUIDs); int prevAssets = assetUuids.Count; foreach (SceneObjectGroup sceneObject in sceneObjects) + { + int curErrorCntr = assetGatherer.ErrorCount; + int possible = assetGatherer.possibleNotAssetCount; assetGatherer.AddForInspection(sceneObject); + assetGatherer.GatherAll(); + curErrorCntr = assetGatherer.ErrorCount - curErrorCntr; + possible = assetGatherer.possibleNotAssetCount - possible; + if(curErrorCntr > 0) + { + m_log.ErrorFormat("[ARCHIVER]: object {0} '{1}', at {2}, contains {3} references to missing or damaged assets", + sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), curErrorCntr); + if(possible > 0) + m_log.WarnFormat("[ARCHIVER Warning]: object also contains {0} references that may be to missing or damaged assets or not a problem", possible); + } + else if(possible > 0) + { + m_log.WarnFormat("[ARCHIVER Warning]: object {0} '{1}', at {2}, contains {3} references that may be to missing or damaged assets or not a problem", + sceneObject.UUID, sceneObject.Name ,sceneObject.AbsolutePosition.ToString(), possible); + } + } assetGatherer.GatherAll(); + int errors = assetGatherer.FailedUUIDs.Count; m_log.DebugFormat( - "[ARCHIVER]: {0} scene objects to serialize requiring save of {1} assets", - sceneObjects.Count, assetUuids.Count - prevAssets); + "[ARCHIVER]: {0} region scene objects to save reference {1} possible assets", + sceneObjects.Count, assetUuids.Count - prevAssets + errors); + if(errors > 0) + m_log.DebugFormat("[ARCHIVER]: {0} of these have problems or are not assets and will be ignored", errors); } if (numObjectsSkippedPermissions > 0) @@ -572,7 +595,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver foreach (SceneObjectGroup sceneObject in sceneObjects) { //m_log.DebugFormat("[ARCHIVER]: Saving {0} {1}, {2}", entity.Name, entity.UUID, entity.GetType()); - + if(sceneObject.IsDeleted || sceneObject.inTransit) + continue; string serializedObject = serializer.SerializeGroupToXml2(sceneObject, m_options); string objectPath = string.Format("{0}{1}", regionDir, ArchiveHelpers.CreateObjectPath(sceneObject)); m_archiveWriter.WriteFile(objectPath, serializedObject); diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs index efacae372f..3092fe0a8d 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsArchiver.cs @@ -46,7 +46,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// /// Post a message to the log every x assets as a progress bar /// - protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 50; + protected static int LOG_ASSET_LOAD_NOTIFICATION_INTERVAL = 100; /// /// Keep a count of the number of assets written so that we can provide status updates diff --git a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs index d380da8d8a..91f4dc354f 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/AssetsRequest.cs @@ -61,28 +61,11 @@ namespace OpenSim.Region.CoreModules.World.Archiver Aborted }; - /// - /// Timeout threshold if we still need assets or missing asset notifications but have stopped receiving them - /// from the asset service - /// - protected const int TIMEOUT = 60 * 1000; - - /// - /// If a timeout does occur, limit the amount of UUID information put to the console. - /// - protected const int MAX_UUID_DISPLAY_ON_TIMEOUT = 3; - - protected System.Timers.Timer m_requestCallbackTimer; - - /// - /// State of this request - /// - private RequestState m_requestState = RequestState.Initial; - /// /// uuids to request /// protected IDictionary m_uuids; + private int m_previousErrorsCount; /// /// Callback used when all the assets requested have been received. @@ -104,6 +87,9 @@ namespace OpenSim.Region.CoreModules.World.Archiver /// private int m_repliesRequired; + private System.Timers.Timer m_timeOutTimer; + private bool m_timeout; + /// /// Asset service used to request the assets /// @@ -117,205 +103,98 @@ namespace OpenSim.Region.CoreModules.World.Archiver protected internal AssetsRequest( AssetsArchiver assetsArchiver, IDictionary uuids, + int previousErrorsCount, IAssetService assetService, IUserAccountService userService, UUID scope, Dictionary options, AssetsRequestCallback assetsRequestCallback) { m_assetsArchiver = assetsArchiver; m_uuids = uuids; + m_previousErrorsCount = previousErrorsCount; m_assetsRequestCallback = assetsRequestCallback; m_assetService = assetService; m_userAccountService = userService; m_scopeID = scope; 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); } protected internal void Execute() { - m_requestState = RequestState.Running; - - m_log.DebugFormat("[ARCHIVER]: AssetsRequest executed looking for {0} possible assets", m_repliesRequired); - + Culture.SetCurrentCulture(); // We can stop here if there are no assets to fetch if (m_repliesRequired == 0) { - m_requestState = RequestState.Completed; PerformAssetsRequestCallback(false); return; } - m_requestCallbackTimer.Enabled = true; + m_timeOutTimer = new System.Timers.Timer(60000); + m_timeOutTimer .AutoReset = false; + m_timeOutTimer.Elapsed += OnTimeout; + m_timeout = false; foreach (KeyValuePair kvp in m_uuids) { -// m_log.DebugFormat("[ARCHIVER]: Requesting asset {0}", kvp.Key); - -// m_assetService.Get(kvp.Key.ToString(), kvp.Value, PreAssetRequestCallback); - AssetBase asset = m_assetService.Get(kvp.Key.ToString()); - PreAssetRequestCallback(kvp.Key.ToString(), kvp.Value, asset); - } - } - - protected void OnRequestCallbackTimeout(object source, ElapsedEventArgs args) - { - bool timedOut = true; - - try - { - lock (this) + string thiskey = kvp.Key.ToString(); + try { - // Take care of the possibilty that this thread started but was paused just outside the lock before - // the final request came in (assuming that such a thing is possible) - if (m_requestState == RequestState.Completed) - { - timedOut = false; - return; - } - - m_requestState = RequestState.Aborted; - } - - // Calculate which uuids were not found. This is an expensive way of doing it, but this is a failure - // case anyway. - List uuids = new List(); - foreach (UUID uuid in m_uuids.Keys) - { - uuids.Add(uuid); - } - - foreach (UUID uuid in m_foundAssetUuids) - { - uuids.Remove(uuid); - } - - foreach (UUID uuid in m_notFoundAssetUuids) - { - uuids.Remove(uuid); - } - - m_log.ErrorFormat( - "[ARCHIVER]: Asset service failed to return information about {0} requested assets", uuids.Count); - - int i = 0; - foreach (UUID uuid in uuids) - { - m_log.ErrorFormat("[ARCHIVER]: No information about asset {0} received", uuid); - - if (++i >= MAX_UUID_DISPLAY_ON_TIMEOUT) + m_timeOutTimer.Enabled = true; + AssetBase asset = m_assetService.Get(thiskey); + if(m_timeout) break; + + m_timeOutTimer.Enabled = false; + + if(asset == null) + { + m_notFoundAssetUuids.Add(new UUID(thiskey)); + continue; + } + + sbyte assetType = kvp.Value; + if (asset != null && assetType == (sbyte)AssetType.Unknown) + { + m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", thiskey, SLUtil.AssetTypeFromCode(assetType)); + asset.Type = assetType; + } + + m_foundAssetUuids.Add(asset.FullID); + m_assetsArchiver.WriteAsset(PostProcess(asset)); } - if (uuids.Count > MAX_UUID_DISPLAY_ON_TIMEOUT) - m_log.ErrorFormat( - "[ARCHIVER]: (... {0} more not shown)", uuids.Count - MAX_UUID_DISPLAY_ON_TIMEOUT); - - m_log.Error("[ARCHIVER]: Archive save aborted. PLEASE DO NOT USE THIS ARCHIVE, IT WILL BE INCOMPLETE."); - } - catch (Exception e) - { - m_log.ErrorFormat("[ARCHIVER]: Timeout handler exception {0}{1}", e.Message, e.StackTrace); - } - finally - { - if (timedOut) - WorkManager.RunInThread(PerformAssetsRequestCallback, true, "Archive Assets Request Callback"); - } - } - - protected void PreAssetRequestCallback(string fetchedAssetID, object assetType, AssetBase fetchedAsset) - { - // Check for broken asset types and fix them with the AssetType gleaned by UuidGatherer - if (fetchedAsset != null && fetchedAsset.Type == (sbyte)AssetType.Unknown) - { - m_log.InfoFormat("[ARCHIVER]: Rewriting broken asset type for {0} to {1}", fetchedAsset.ID, SLUtil.AssetTypeFromCode((sbyte)assetType)); - fetchedAsset.Type = (sbyte)assetType; - } - - AssetRequestCallback(fetchedAssetID, this, fetchedAsset); - } - - /// - /// Called back by the asset cache when it has the asset - /// - /// - /// - public void AssetRequestCallback(string id, object sender, AssetBase asset) - { - Culture.SetCurrentCulture(); - - try - { - lock (this) + catch (Exception e) { - //m_log.DebugFormat("[ARCHIVER]: Received callback for asset {0}", id); - - m_requestCallbackTimer.Stop(); - - if ((m_requestState == RequestState.Aborted) || (m_requestState == RequestState.Completed)) - { - m_log.WarnFormat( - "[ARCHIVER]: Received information about asset {0} while in state {1}. Ignoring.", - id, m_requestState); - - return; - } - - if (asset != null) - { -// m_log.DebugFormat("[ARCHIVER]: Writing asset {0}", id); - m_foundAssetUuids.Add(asset.FullID); - - m_assetsArchiver.WriteAsset(PostProcess(asset)); - } - else - { -// m_log.DebugFormat("[ARCHIVER]: Recording asset {0} as not found", id); - m_notFoundAssetUuids.Add(new UUID(id)); - } - - if (m_foundAssetUuids.Count + m_notFoundAssetUuids.Count >= m_repliesRequired) - { - m_requestState = RequestState.Completed; - if(m_notFoundAssetUuids.Count == 0) - m_log.DebugFormat( - "[ARCHIVER]: Successfully added {0} assets", - m_foundAssetUuids.Count); - else - m_log.DebugFormat( - "[ARCHIVER]: Successfully added {0} assets ({1} assets not found but these may be expected invalid references)", - m_foundAssetUuids.Count, m_notFoundAssetUuids.Count); - - - // We want to stop using the asset cache thread asap - // as we now need to do the work of producing the rest of the archive - WorkManager.RunInThread(PerformAssetsRequestCallback, false, "Archive Assets Request Callback"); - } - else - { - m_requestCallbackTimer.Start(); - } + m_log.ErrorFormat("[ARCHIVER]: Execute failed with {0}", e); } } - catch (Exception e) - { - m_log.ErrorFormat("[ARCHIVER]: AssetRequestCallback failed with {0}", e); - } + + m_timeOutTimer.Dispose(); + int totalerrors = m_notFoundAssetUuids.Count + m_previousErrorsCount; + + if(m_timeout) + m_log.DebugFormat("[ARCHIVER]: Aborted because AssetService request timeout. Successfully added {0} assets", m_foundAssetUuids.Count); + else if(totalerrors == 0) + m_log.DebugFormat("[ARCHIVER]: Successfully added all {0} assets", m_foundAssetUuids.Count); + else + m_log.DebugFormat("[ARCHIVER]: Successfully added {0} assets ({1} of total possible assets requested were not found, were damaged or were not assets)", + m_foundAssetUuids.Count, totalerrors); + + PerformAssetsRequestCallback(m_timeout); + } + + private void OnTimeout(object source, ElapsedEventArgs args) + { + m_timeout = true; } /// /// Perform the callback on the original requester of the assets /// - protected void PerformAssetsRequestCallback(object o) + private void PerformAssetsRequestCallback(object o) { + if(m_assetsRequestCallback == null) + return; Culture.SetCurrentCulture(); Boolean timedOut = (Boolean)o; @@ -331,7 +210,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver } } - protected AssetBase PostProcess(AssetBase asset) + private AssetBase PostProcess(AssetBase asset) { if (asset.Type == (sbyte)AssetType.Object && asset.Data != null && m_options.ContainsKey("home")) { diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs index 7ab92d1a47..5eda8ab02b 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateRequestHandler.cs @@ -60,9 +60,10 @@ namespace OpenSim.Region.CoreModules.World.Estate protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); + body = body.Trim(); // m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body); diff --git a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs index 70c6028176..22480e68df 100644 --- a/OpenSim/Region/CoreModules/World/Land/DwellModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/DwellModule.cs @@ -53,7 +53,7 @@ using GridRegion = OpenSim.Services.Interfaces.GridRegion; namespace OpenSim.Region.CoreModules.World.Land { [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "DefaultDwellModule")] - public class DefaultDwellModule : IDwellModule, INonSharedRegionModule + public class DefaultDwellModule : INonSharedRegionModule, IDwellModule { private Scene m_scene; private IConfigSource m_Config; @@ -88,16 +88,21 @@ namespace OpenSim.Region.CoreModules.World.Land return; m_scene = scene; - - m_scene.EventManager.OnNewClient += OnNewClient; + m_scene.RegisterModuleInterface(this); } public void RegionLoaded(Scene scene) { + if (!m_Enabled) + return; + m_scene.EventManager.OnNewClient += OnNewClient; } public void RemoveRegion(Scene scene) { + if (!m_Enabled) + return; + m_scene.EventManager.OnNewClient -= OnNewClient; } public void Close() @@ -115,12 +120,26 @@ namespace OpenSim.Region.CoreModules.World.Land if (parcel == null) return; - client.SendParcelDwellReply(localID, parcel.LandData.GlobalID, parcel.LandData.Dwell); + LandData land = parcel.LandData; + if(land!= null) + client.SendParcelDwellReply(localID, land.GlobalID, land.Dwell); } + public int GetDwell(UUID parcelID) { + ILandObject parcel = m_scene.LandChannel.GetLandObject(parcelID); + if (parcel != null && parcel.LandData != null) + return (int)(parcel.LandData.Dwell); return 0; } + + public int GetDwell(LandData land) + { + if (land != null) + return (int)(land.Dwell); + return 0; + } + } } diff --git a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs index e4c037371e..5ff063bc31 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandChannel.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandChannel.cs @@ -106,6 +106,15 @@ namespace OpenSim.Region.CoreModules.World.Land return null; } + public ILandObject GetLandObject(UUID GlobalID) + { + if (m_landManagementModule != null) + { + return m_landManagementModule.GetLandObject(GlobalID); + } + return null; + } + public ILandObject GetLandObject(Vector3 position) { return GetLandObject(position.X, position.Y); @@ -167,6 +176,14 @@ namespace OpenSim.Region.CoreModules.World.Land } } + public void SendParcelsOverlay(IClientAPI client) + { + if (m_landManagementModule != null) + { + m_landManagementModule.SendParcelOverlay(client); + } + } + public void Join(int start_x, int start_y, int end_x, int end_y, UUID attempting_user_id) { if (m_landManagementModule != null) diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs index 5d12f8b31a..f422708680 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs @@ -41,6 +41,7 @@ using OpenSim.Framework; using OpenSim.Framework.Capabilities; using OpenSim.Framework.Console; using OpenSim.Framework.Servers; +using OpenSim.Framework.Monitoring; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; @@ -92,6 +93,7 @@ namespace OpenSim.Region.CoreModules.World.Land //ubit: removed the readonly so i can move it around private Dictionary m_landList = new Dictionary(); + private Dictionary m_landUUIDList = new Dictionary(); private int m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; @@ -149,9 +151,11 @@ namespace OpenSim.Region.CoreModules.World.Land parcelInfoCache.Size = 30; // the number of different parcel requests in this region to cache parcelInfoCache.DefaultTTL = new TimeSpan(0, 5, 0); + m_scene.EventManager.OnObjectAddedToScene += EventManagerOnParcelPrimCountAdd; m_scene.EventManager.OnParcelPrimCountAdd += EventManagerOnParcelPrimCountAdd; - m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate; + m_scene.EventManager.OnObjectBeingRemovedFromScene += EventManagerOnObjectBeingRemovedFromScene; + m_scene.EventManager.OnParcelPrimCountUpdate += EventManagerOnParcelPrimCountUpdate; m_scene.EventManager.OnRequestParcelPrimCountUpdate += EventManagerOnRequestParcelPrimCountUpdate; m_scene.EventManager.OnAvatarEnteringNewParcel += EventManagerOnAvatarEnteringNewParcel; @@ -213,6 +217,7 @@ namespace OpenSim.Region.CoreModules.World.Land client.OnParcelEjectUser += ClientOnParcelEjectUser; client.OnParcelFreezeUser += ClientOnParcelFreezeUser; client.OnSetStartLocationRequest += ClientOnSetHome; + client.OnParcelBuyPass += ClientParcelBuyPass; } public void EventMakeChildAgent(ScenePresence avatar) @@ -247,7 +252,10 @@ namespace OpenSim.Region.CoreModules.World.Land lock (m_landList) { if (m_landList.TryGetValue(local_id, out land)) + { land.LandData = newData; + m_landUUIDList[newData.GlobalID] = local_id; + } } if (land != null) @@ -268,7 +276,11 @@ namespace OpenSim.Region.CoreModules.World.Land //Remove all the land objects in the sim and add a blank, full sim land object set to public lock (m_landList) { + foreach(ILandObject parcel in m_landList.Values) + parcel.Clear(); + m_landList.Clear(); + m_landUUIDList.Clear(); m_lastLandLocalID = LandChannel.START_LAND_LOCAL_ID - 1; m_landIDList = new int[m_scene.RegionInfo.RegionSizeX / LandUnit, m_scene.RegionInfo.RegionSizeY / LandUnit]; @@ -287,8 +299,10 @@ namespace OpenSim.Region.CoreModules.World.Land fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)m_scene.RegionInfo.RegionSizeX, (int)m_scene.RegionInfo.RegionSizeY)); - fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; - fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); + LandData ldata = fullSimParcel.LandData; + ldata.SimwideArea = ldata.Area; + ldata.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; + ldata.ClaimDate = Util.UnixTimeSinceEpoch(); return AddLandObject(fullSimParcel); } @@ -525,6 +539,118 @@ namespace OpenSim.Region.CoreModules.World.Land } } + public void ClientParcelBuyPass(IClientAPI remote_client, UUID targetID, int landLocalID) + { + ILandObject land; + lock (m_landList) + { + m_landList.TryGetValue(landLocalID, out land); + } + // trivial checks + if(land == null) + return; + + LandData ldata = land.LandData; + + if(ldata == null) + return; + + if(ldata.OwnerID == targetID) + return; + + if(ldata.PassHours == 0) + return; + + // don't allow passes on group owned until we can give money to groups + if(ldata.IsGroupOwned) + { + remote_client.SendAgentAlertMessage("pass to group owned parcel not suported", false); + return; + } + + if((ldata.Flags & (uint)ParcelFlags.UsePassList) == 0) + return; + + int cost = ldata.PassPrice; + + int idx = land.LandData.ParcelAccessList.FindIndex( + delegate(LandAccessEntry e) + { + if (e.AgentID == targetID && e.Flags == AccessList.Access) + return true; + return false; + }); + int now = Util.UnixTimeSinceEpoch(); + int expires = (int)(3600.0 * ldata.PassHours + 0.5f); + int currenttime = -1; + if (idx != -1) + { + if(ldata.ParcelAccessList[idx].Expires == 0) + { + remote_client.SendAgentAlertMessage("You already have access to parcel", false); + return; + } + + currenttime = ldata.ParcelAccessList[idx].Expires - now; + if(currenttime > (int)(0.25f * expires + 0.5f)) + { + if(currenttime > 3600) + remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.###} hours", + currenttime/3600f), false); + else if(currenttime > 60) + remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.##} minutes", + currenttime/60f), false); + else + remote_client.SendAgentAlertMessage(string.Format("You already have a pass valid for {0:0.#} seconds", + currenttime), false); + return; + } + } + + LandAccessEntry entry = new LandAccessEntry(); + entry.AgentID = targetID; + entry.Flags = AccessList.Access; + entry.Expires = now + expires; + if(currenttime > 0) + entry.Expires += currenttime; + IMoneyModule mm = m_scene.RequestModuleInterface(); + if(cost != 0 && mm != null) + { + WorkManager.RunInThreadPool( + delegate + { + string regionName = m_scene.RegionInfo.RegionName; + + if (!mm.AmountCovered(remote_client.AgentId, cost)) + { + remote_client.SendAgentAlertMessage(String.Format("Insufficient funds in region '{0}' money system", regionName), true); + return; + } + + string payDescription = String.Format("Parcel '{0}' at region '{1} {2:0.###} hours access pass", ldata.Name, regionName, ldata.PassHours); + + if(!mm.MoveMoney(remote_client.AgentId, ldata.OwnerID, cost,MoneyTransactionType.LandPassSale, payDescription)) + { + remote_client.SendAgentAlertMessage("Sorry pass payment processing failed, please try again later", true); + return; + } + + if (idx != -1) + ldata.ParcelAccessList.RemoveAt(idx); + ldata.ParcelAccessList.Add(entry); + m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); + return; + }, null, "ParcelBuyPass"); + } + else + { + if (idx != -1) + ldata.ParcelAccessList.RemoveAt(idx); + ldata.ParcelAccessList.Add(entry); + m_scene.EventManager.TriggerLandObjectUpdated((uint)land.LandData.LocalID, land); + } + } + public void ClientOnParcelAccessListRequest(UUID agentID, UUID sessionID, uint flags, int sequenceID, int landLocalID, IClientAPI remote_client) { @@ -584,10 +710,8 @@ namespace OpenSim.Region.CoreModules.World.Land /// The land object being added. /// Will return null if this overlaps with an existing parcel that has not had its bitmap adjusted. /// - public ILandObject AddLandObject(ILandObject land) + public ILandObject AddLandObject(ILandObject new_land) { - ILandObject new_land = land.Copy(); - // Only now can we add the prim counts to the land object - we rely on the global ID which is generated // as a random UUID inside LandData initialization if (m_primCountModule != null) @@ -652,6 +776,7 @@ namespace OpenSim.Region.CoreModules.World.Land } m_landList.Add(newLandLocalID, new_land); + m_landUUIDList[new_land.LandData.GlobalID] = newLandLocalID; m_lastLandLocalID++; } @@ -668,6 +793,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void removeLandObject(int local_id) { ILandObject land; + UUID landGlobalID = UUID.Zero; lock (m_landList) { for (int x = 0; x < m_landIDList.GetLength(0); x++) @@ -686,9 +812,18 @@ namespace OpenSim.Region.CoreModules.World.Land land = m_landList[local_id]; m_landList.Remove(local_id); + if(land != null && land.LandData != null) + { + landGlobalID = land.LandData.GlobalID; + m_landUUIDList.Remove(landGlobalID); + } } - m_scene.EventManager.TriggerLandObjectRemoved(land.LandData.GlobalID); + if(landGlobalID != UUID.Zero) + { + m_scene.EventManager.TriggerLandObjectRemoved(landGlobalID); + land.Clear(); + } } /// @@ -736,11 +871,29 @@ namespace OpenSim.Region.CoreModules.World.Land } } } - + master.LandData.Dwell += slave.LandData.Dwell; removeLandObject(slave.LandData.LocalID); UpdateLandObject(master.LandData.LocalID, master.LandData); } + public ILandObject GetLandObject(UUID globalID) + { + lock (m_landList) + { + int lid = -1; + if(m_landUUIDList.TryGetValue(globalID, out lid) && lid >= 0) + { + if (m_landList.ContainsKey(lid)) + { + return m_landList[lid]; + } + else + m_landUUIDList.Remove(globalID); // auto heal + } + } + return null; + } + public ILandObject GetLandObject(int parcelLocalID) { lock (m_landList) @@ -813,6 +966,9 @@ namespace OpenSim.Region.CoreModules.World.Land throw new Exception("Error: Parcel not found at point " + x + ", " + y); } + if(m_landList.Count == 0 || m_landIDList == null) + return null; + lock (m_landIDList) { try @@ -824,8 +980,6 @@ namespace OpenSim.Region.CoreModules.World.Land return null; } } - - return m_landList[m_landIDList[x / 4, y / 4]]; } // Create a 'parcel is here' bitmap for the parcel identified by the passed landID @@ -1252,7 +1406,7 @@ namespace OpenSim.Region.CoreModules.World.Land { if (!temp.Contains(currentParcel)) { - if (!currentParcel.IsEitherBannedOrRestricted(remote_client.AgentId)) + if (!currentParcel.IsBannedFromLand(remote_client.AgentId)) { currentParcel.ForceUpdateLandInfo(); temp.Add(currentParcel); @@ -1346,7 +1500,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelObjectOwnerRequest(int local_id, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1355,7 +1509,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (land != null) { m_scene.EventManager.TriggerParcelPrimCountUpdate(); - m_landList[local_id].SendLandObjectOwners(remote_client); + land.SendLandObjectOwners(remote_client); } else { @@ -1365,7 +1519,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelGodForceOwner(int local_id, UUID ownerID, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1388,7 +1542,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelAbandonRequest(int local_id, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1412,7 +1566,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void ClientOnParcelReclaim(int local_id, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(local_id, out land); @@ -1498,17 +1652,16 @@ namespace OpenSim.Region.CoreModules.World.Land void ClientOnParcelDeedToGroup(int parcelLocalID, UUID groupID, IClientAPI remote_client) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(parcelLocalID, out land); } - if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land)) - return; - if (land != null) { + if (!m_scene.Permissions.CanDeedParcel(remote_client.AgentId, land)) + return; land.DeedToGroup(groupID); } } @@ -1576,13 +1729,13 @@ namespace OpenSim.Region.CoreModules.World.Land } } } + FinalizeLandPrimCountUpdate(); // update simarea information } } private void IncomingLandObjectFromStorage(LandData data) { - ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); - new_land.LandData = data.Copy(); + ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene, data); new_land.SetLandBitmapFromByteArray(); AddLandObject(new_land); @@ -1640,9 +1793,9 @@ namespace OpenSim.Region.CoreModules.World.Land foreach (HashSet objs in returns.Values) { List objs2 = new List(objs); - if (m_scene.Permissions.CanReturnObjects(null, remoteClient.AgentId, objs2)) + if (m_scene.Permissions.CanReturnObjects(null, remoteClient, objs2)) { - m_scene.returnObjects(objs2.ToArray(), remoteClient.AgentId); + m_scene.returnObjects(objs2.ToArray(), remoteClient); } else { @@ -1730,7 +1883,7 @@ namespace OpenSim.Region.CoreModules.World.Land land_update.MusicURL = properties.MusicURL; land_update.Name = properties.Name; land_update.ParcelFlags = (uint) properties.ParcelFlags; - land_update.PassHours = (int) properties.PassHours; + land_update.PassHours = properties.PassHours; land_update.PassPrice = (int) properties.PassPrice; land_update.SalePrice = (int) properties.SalePrice; land_update.SnapshotID = properties.SnapshotID; @@ -1757,7 +1910,7 @@ namespace OpenSim.Region.CoreModules.World.Land land_update.GroupAVSounds = true; } - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(parcelID, out land); @@ -1920,6 +2073,9 @@ namespace OpenSim.Region.CoreModules.World.Land if (data.RegionHandle == m_scene.RegionInfo.RegionHandle) { info = new GridRegion(m_scene.RegionInfo); + IDwellModule dwellModule = m_scene.RequestModuleInterface(); + if (dwellModule != null) + data.LandData.Dwell = dwellModule.GetDwell(data.LandData); } else { @@ -1945,7 +2101,7 @@ namespace OpenSim.Region.CoreModules.World.Land public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) { - ILandObject land; + ILandObject land = null; lock (m_landList) { m_landList.TryGetValue(localID, out land); @@ -2035,7 +2191,7 @@ namespace OpenSim.Region.CoreModules.World.Land { SceneObjectGroup[] objs = new SceneObjectGroup[1]; objs[0] = obj; - ((Scene)client.Scene).returnObjects(objs, client.AgentId); + ((Scene)client.Scene).returnObjects(objs, client); } Dictionary Timers = new Dictionary(); @@ -2242,7 +2398,7 @@ namespace OpenSim.Region.CoreModules.World.Land if (!ConsoleUtil.TryParseConsoleInt(MainConsole.Instance, args[2], out landLocalId)) return; - ILandObject lo; + ILandObject lo = null; lock (m_landList) { diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 73b4cb57a0..07d11f96a6 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -58,6 +58,7 @@ namespace OpenSim.Region.CoreModules.World.Land protected ExpiringCache m_groupMemberCache = new ExpiringCache(); protected TimeSpan m_groupMemberCacheTimeout = TimeSpan.FromSeconds(30); // cache invalidation after 30 seconds + IDwellModule m_dwellModule; private bool[,] m_landBitmap; public bool[,] LandBitmap @@ -268,27 +269,46 @@ namespace OpenSim.Region.CoreModules.World.Land { LandData = landData.Copy(); m_scene = scene; + m_scene.EventManager.OnFrame += OnFrame; + m_dwellModule = m_scene.RequestModuleInterface(); } - public LandObject(UUID owner_id, bool is_group_owned, Scene scene) + public LandObject(UUID owner_id, bool is_group_owned, Scene scene, LandData data = null) { m_scene = scene; if (m_scene == null) LandBitmap = new bool[Constants.RegionSize / landUnit, Constants.RegionSize / landUnit]; else + { LandBitmap = new bool[m_scene.RegionInfo.RegionSizeX / landUnit, m_scene.RegionInfo.RegionSizeY / landUnit]; + m_dwellModule = m_scene.RequestModuleInterface(); + } + + if(data == null) + LandData = new LandData(); + else + LandData = data; - LandData = new LandData(); LandData.OwnerID = owner_id; if (is_group_owned) LandData.GroupID = owner_id; - else - LandData.GroupID = UUID.Zero; + LandData.IsGroupOwned = is_group_owned; + if(m_dwellModule == null) + LandData.Dwell = 0; + m_scene.EventManager.OnFrame += OnFrame; } + public void Clear() + { + if(m_scene != null) + m_scene.EventManager.OnFrame -= OnFrame; + LandData = null; + } + + #endregion #region Member Functions @@ -356,6 +376,7 @@ namespace OpenSim.Region.CoreModules.World.Land } } + // the total prims a parcel owner can have on a region public int GetSimulatorMaxPrimCount() { if (overrideSimulatorMaxPrimCount != null) @@ -370,7 +391,7 @@ namespace OpenSim.Region.CoreModules.World.Land * (double)m_scene.RegionInfo.RegionSettings.ObjectBonus / (long)(m_scene.RegionInfo.RegionSizeX * m_scene.RegionInfo.RegionSizeY) +0.5 ); - + // sanity check if(simMax > m_scene.RegionInfo.ObjectCapacity) simMax = m_scene.RegionInfo.ObjectCapacity; //m_log.DebugFormat("Simwide Area: {0}, Capacity {1}, SimMax {2}, SimWidePrims {3}", @@ -519,7 +540,8 @@ namespace OpenSim.Region.CoreModules.World.Land ParcelFlags.UseEstateVoiceChan); } - if (m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false)) + // don't allow passes on group owned until we can give money to groups + if (!newData.IsGroupOwned && m_scene.Permissions.CanEditParcelProperties(remote_client.AgentId,this, GroupPowers.LandManagePasses, false)) { newData.PassHours = args.PassHours; newData.PassPrice = args.PassPrice; @@ -1043,7 +1065,8 @@ namespace OpenSim.Region.CoreModules.World.Land else LandData.AABBMax = new Vector3(tx, ty, (float)m_scene.Heightmap[tx - 1, ty - 1]); - LandData.Area = tempArea * landUnit * landUnit; + tempArea *= landUnit * landUnit; + LandData.Area = tempArea; } #endregion @@ -1647,8 +1670,7 @@ namespace OpenSim.Region.CoreModules.World.Land { foreach (SceneObjectGroup obj in primsOverMe) { - if (obj.OwnerID == previousOwner && obj.GroupID == UUID.Zero && - (obj.GetEffectivePermissions() & (uint)(OpenSim.Framework.PermissionMask.Transfer)) != 0) + if(m_scene.Permissions.CanSellObject(previousOwner,obj, (byte)SaleType.Original)) m_BuySellModule.BuyObject(sp.ControllingClient, UUID.Zero, obj.LocalId, 1, 0); } } @@ -1662,7 +1684,7 @@ namespace OpenSim.Region.CoreModules.World.Land { SceneObjectGroup[] objs = new SceneObjectGroup[1]; objs[0] = obj; - m_scene.returnObjects(objs, obj.OwnerID); + m_scene.returnObjects(objs, null); } public void ReturnLandObjects(uint type, UUID[] owners, UUID[] tasks, IClientAPI remote_client) @@ -1693,6 +1715,8 @@ namespace OpenSim.Region.CoreModules.World.Land { if (obj.GroupID == LandData.GroupID) { + if (obj.OwnerID == LandData.OwnerID) + continue; if (!returns.ContainsKey(obj.OwnerID)) returns[obj.OwnerID] = new List(); @@ -1734,8 +1758,8 @@ namespace OpenSim.Region.CoreModules.World.Land foreach (List ol in returns.Values) { - if (m_scene.Permissions.CanReturnObjects(this, remote_client.AgentId, ol)) - m_scene.returnObjects(ol.ToArray(), remote_client.AgentId); + if (m_scene.Permissions.CanReturnObjects(this, remote_client, ol)) + m_scene.returnObjects(ol.ToArray(), remote_client); } } @@ -1809,6 +1833,37 @@ namespace OpenSim.Region.CoreModules.World.Land ExpireAccessList(); m_expiryCounter = 0; } + + // need to update dwell here bc landdata has no parent info + if(LandData != null && m_dwellModule != null) + { + double now = Util.GetTimeStampMS(); + double elapsed = now - LandData.LastDwellTimeMS; + if(elapsed > 150000) //2.5 minutes resolution / throttle + { + float dwell = LandData.Dwell; + double cur = dwell * 60000.0; + double decay = 1.5e-8 * cur * elapsed; + cur -= decay; + if(cur < 0) + cur = 0; + + UUID lgid = LandData.GlobalID; + m_scene.ForEachRootScenePresence(delegate(ScenePresence sp) + { + if(sp.IsNPC || sp.IsLoggingIn || sp.IsDeleted || sp.currentParcelUUID != lgid) + return; + cur += (now - sp.ParcelDwellTickMS); + sp.ParcelDwellTickMS = now; + }); + + float newdwell = (float)(cur * 1.666666666667e-5); + LandData.Dwell = newdwell; + + if(Math.Abs(newdwell - dwell) >= 0.9) + m_scene.EventManager.TriggerLandObjectAdded(this); + } + } } private void ExpireAccessList() diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs index 857f919a06..2a720db660 100644 --- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs +++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs @@ -92,10 +92,8 @@ namespace OpenSim.Region.CoreModules.World.Land m_Scene.RegisterModuleInterface(this); m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd; - m_Scene.EventManager.OnObjectBeingRemovedFromScene += - OnObjectBeingRemovedFromScene; - m_Scene.EventManager.OnParcelPrimCountTainted += - OnParcelPrimCountTainted; + m_Scene.EventManager.OnObjectBeingRemovedFromScene += OnObjectBeingRemovedFromScene; + m_Scene.EventManager.OnParcelPrimCountTainted += OnParcelPrimCountTainted; m_Scene.EventManager.OnLandObjectAdded += delegate(ILandObject lo) { OnParcelPrimCountTainted(); }; } @@ -215,29 +213,15 @@ namespace OpenSim.Region.CoreModules.World.Land else parcelCounts.Users[obj.OwnerID] = partCount; - if (obj.IsSelected) - { + if (obj.IsSelected || obj.GetSittingAvatarsCount() > 0) parcelCounts.Selected += partCount; - } + + if (obj.OwnerID == landData.OwnerID) + parcelCounts.Owner += partCount; + else if (landData.GroupID != UUID.Zero && obj.GroupID == landData.GroupID) + parcelCounts.Group += partCount; else - { - if (landData.IsGroupOwned) - { - if (obj.OwnerID == landData.GroupID) - parcelCounts.Owner += partCount; - else if (landData.GroupID != UUID.Zero && obj.GroupID == landData.GroupID) - parcelCounts.Group += partCount; - else - parcelCounts.Others += partCount; - } - else - { - if (obj.OwnerID == landData.OwnerID) - parcelCounts.Owner += partCount; - else - parcelCounts.Others += partCount; - } - } + parcelCounts.Others += partCount; } } @@ -393,7 +377,6 @@ namespace OpenSim.Region.CoreModules.World.Land count = counts.Owner; count += counts.Group; count += counts.Others; - count += counts.Selected; } } diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs index 0d8ece7cdf..a349aa1be5 100644 --- a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs +++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs @@ -151,7 +151,7 @@ namespace OpenSim.Region.CoreModules.World.Land.Tests SceneObjectGroup sog = SceneHelpers.CreateSceneObject(3, m_userId, "a", 0x01); m_scene.AddNewSceneObject(sog, false); - m_scene.SceneGraph.DuplicateObject(sog.LocalId, Vector3.Zero, 0, m_userId, UUID.Zero, Quaternion.Identity); + m_scene.SceneGraph.DuplicateObject(sog.LocalId, Vector3.Zero, m_userId, UUID.Zero, Quaternion.Identity, false); Assert.That(pc.Owner, Is.EqualTo(6)); Assert.That(pc.Group, Is.EqualTo(0)); diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs index 283735889f..6a8f4c04af 100644 --- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs @@ -89,28 +89,23 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell if (part == null) return; - if (part.ParentGroup.IsDeleted) + SceneObjectGroup sog = part.ParentGroup; + if (sog == null || sog.IsDeleted) return; - if (part.OwnerID != part.GroupID && part.OwnerID != client.AgentId && (!m_scene.Permissions.IsGod(client.AgentId))) - return; - - if (part.OwnerID == part.GroupID) // Group owned + // Does the user have the power to put the object on sale? + if (!m_scene.Permissions.CanSellObject(client, sog, saleType)) { - // Does the user have the power to put the object on sale? - if (!m_scene.Permissions.CanSellGroupObject(client.AgentId, part.GroupID, m_scene)) - { - client.SendAgentAlertMessage("You don't have permission to set group-owned objects on sale", false); - return; - } + client.SendAgentAlertMessage("You don't have permission to set object on sale", false); + return; } - part = part.ParentGroup.RootPart; + part = sog.RootPart; part.ObjectSaleType = saleType; part.SalePrice = salePrice; - part.ParentGroup.HasGroupChanged = true; + sog.HasGroupChanged = true; part.SendPropertiesToClient(client); } @@ -123,11 +118,16 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell return false; SceneObjectGroup group = part.ParentGroup; + if(group == null || group.IsDeleted || group.inTransit) + return false; + + // make sure we are not buying a child part + part = group.RootPart; switch (saleType) { case 1: // Sell as original (in-place sale) - uint effectivePerms = group.GetEffectivePermissions(); + uint effectivePerms = group.EffectiveOwnerPerms; if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) { @@ -136,8 +136,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell return false; } - group.SetOwnerId(remoteClient.AgentId); - group.SetRootPartOwner(part, remoteClient.AgentId, remoteClient.ActiveGroupId); + group.SetOwner(remoteClient.AgentId, remoteClient.ActiveGroupId); if (m_scene.Permissions.PropagatePermissions()) { @@ -147,6 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell child.TriggerScriptChangedEvent(Changed.OWNER); child.ApplyNextOwnerPermissions(); } + group.InvalidateDeepEffectivePerms(); } part.ObjectSaleType = 0; @@ -162,19 +162,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell break; case 2: // Sell a copy - Vector3 inventoryStoredPosition = new Vector3( - Math.Min(group.AbsolutePosition.X, m_scene.RegionInfo.RegionSizeX - 6), - Math.Min(group.AbsolutePosition.Y, m_scene.RegionInfo.RegionSizeY - 6), - group.AbsolutePosition.Z); - - Vector3 originalPosition = group.AbsolutePosition; - - group.AbsolutePosition = inventoryStoredPosition; - - string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(group); - group.AbsolutePosition = originalPosition; - - uint perms = group.GetEffectivePermissions(); + uint perms = group.EffectiveOwnerPerms; if ((perms & (uint)PermissionMask.Transfer) == 0) { @@ -190,6 +178,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell return false; } + string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(group); + AssetBase asset = m_scene.CreateAsset( group.GetPartName(localID), group.GetPartDescription(localID), @@ -210,22 +200,21 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell item.AssetType = asset.Type; item.InvType = (int)InventoryType.Object; item.Folder = categoryID; + + perms = group.CurrentAndFoldedNextPermissions(); + // apply parts inventory next perms + PermissionsUtil.ApplyNoModFoldedPermissions(perms, ref perms); + // change to next owner perms + perms &= part.NextOwnerMask; + // update folded + perms = PermissionsUtil.FixAndFoldPermissions(perms); - uint nextPerms=(perms & 7) << 13; - if ((nextPerms & (uint)PermissionMask.Copy) == 0) - perms &= ~(uint)PermissionMask.Copy; - if ((nextPerms & (uint)PermissionMask.Transfer) == 0) - perms &= ~(uint)PermissionMask.Transfer; - if ((nextPerms & (uint)PermissionMask.Modify) == 0) - perms &= ~(uint)PermissionMask.Modify; + item.BasePermissions = perms; + item.CurrentPermissions = perms; + item.NextPermissions = part.NextOwnerMask & perms; + item.EveryOnePermissions = part.EveryoneMask & perms; + item.GroupPermissions = part.GroupMask & perms; - item.BasePermissions = perms & part.NextOwnerMask; - item.CurrentPermissions = perms & part.NextOwnerMask; - item.NextPermissions = part.NextOwnerMask; - item.EveryOnePermissions = part.EveryoneMask & - part.NextOwnerMask; - item.GroupPermissions = part.GroupMask & - part.NextOwnerMask; item.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; item.CreationDate = Util.UnixTimeSinceEpoch(); diff --git a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs index 79c47133be..5a2a173835 100644 --- a/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/Commands/ObjectCommandsModule.cs @@ -123,8 +123,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Objects", false, "delete object pos", - "delete object pos to ", - "Delete scene objects within the given area.", + "delete object pos ", + "Delete scene objects within the given volume.", ConsoleUtil.CoordHelp, HandleDeleteObject); @@ -162,8 +162,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Objects", false, "show object pos", - "show object pos [--full] to ", - "Show details of scene objects within the given area.", + "show object pos [--full] ", + "Show details of scene objects within give volume", "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, @@ -189,8 +189,8 @@ namespace OpenSim.Region.CoreModules.World.Objects.Commands "Objects", false, "show part pos", - "show part pos to ", - "Show details of scene object parts within the given area.", + "show part pos ", + "Show details of scene object parts within the given volume.", ConsoleUtil.CoordHelp, HandleShowPartByPos); diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 75d90f363f..45c1c561e7 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -49,6 +49,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected Scene m_scene; + protected ScenePermissions scenePermissions; protected bool m_Enabled; private InventoryFolderImpl m_libraryRootFolder; @@ -69,15 +70,6 @@ namespace OpenSim.Region.CoreModules.World.Permissions } #region Constants - // These are here for testing. They will be taken out - - //private uint PERM_ALL = (uint)2147483647; - private uint PERM_COPY = (uint)32768; - //private uint PERM_MODIFY = (uint)16384; - private uint PERM_MOVE = (uint)524288; - private uint PERM_TRANS = (uint)8192; - private uint PERM_LOCKED = (uint)540672; - /// /// Different user set names that come in from the configuration file. /// @@ -96,14 +88,12 @@ namespace OpenSim.Region.CoreModules.World.Permissions private bool m_bypassPermissionsValue = true; private bool m_propagatePermissions = false; private bool m_debugPermissions = false; - private bool m_allowGridGods = false; - private bool m_RegionOwnerIsGod = false; - private bool m_RegionManagerIsGod = false; - private bool m_forceGridGodsOnly; - private bool m_forceGodModeAlwaysOn; - private bool m_allowGodActionsWithoutGodMode; - - private bool m_SimpleBuildPermissions = false; + private bool m_allowGridAdmins = false; + private bool m_RegionOwnerIsAdmin = false; + private bool m_RegionManagerIsAdmin = false; + private bool m_forceGridAdminsOnly; + private bool m_forceAdminModeAlwaysOn; + private bool m_allowAdminActionsWithoutGodMode; /// /// The set of users that are allowed to create scripts. This is only active if permissions are not being @@ -172,25 +162,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions string[] sections = new string[] { "Startup", "Permissions" }; - m_allowGridGods = Util.GetConfigVarFromSections(config, "allow_grid_gods", sections, false); + m_allowGridAdmins = Util.GetConfigVarFromSections(config, "allow_grid_gods", sections, false); m_bypassPermissions = !Util.GetConfigVarFromSections(config, "serverside_object_permissions", sections, true); m_propagatePermissions = Util.GetConfigVarFromSections(config, "propagate_permissions", sections, true); - m_forceGridGodsOnly = Util.GetConfigVarFromSections(config, "force_grid_gods_only", sections, false); - if(!m_forceGridGodsOnly) + m_forceGridAdminsOnly = Util.GetConfigVarFromSections(config, "force_grid_gods_only", sections, false); + if(!m_forceGridAdminsOnly) { - m_RegionOwnerIsGod = Util.GetConfigVarFromSections(config, "region_owner_is_god",sections, true); - m_RegionManagerIsGod = Util.GetConfigVarFromSections(config, "region_manager_is_god",sections, false); + m_RegionOwnerIsAdmin = Util.GetConfigVarFromSections(config, "region_owner_is_god",sections, true); + m_RegionManagerIsAdmin = Util.GetConfigVarFromSections(config, "region_manager_is_god",sections, false); } else - m_allowGridGods = true; + m_allowGridAdmins = true; - m_forceGodModeAlwaysOn = Util.GetConfigVarFromSections(config, "automatic_gods", sections, false); - m_allowGodActionsWithoutGodMode = Util.GetConfigVarFromSections(config, "implicit_gods", sections, false); - if(m_allowGodActionsWithoutGodMode) - m_forceGodModeAlwaysOn = false; - - m_SimpleBuildPermissions = Util.GetConfigVarFromSections(config, "simple_build_permissions",sections, false); + m_forceAdminModeAlwaysOn = Util.GetConfigVarFromSections(config, "automatic_gods", sections, false); + m_allowAdminActionsWithoutGodMode = Util.GetConfigVarFromSections(config, "implicit_gods", sections, false); + if(m_allowAdminActionsWithoutGodMode) + m_forceAdminModeAlwaysOn = false; m_allowedScriptCreators = ParseUserSetConfigSetting(config, "allowed_script_creators", m_allowedScriptCreators); @@ -266,63 +254,79 @@ namespace OpenSim.Region.CoreModules.World.Permissions m_scene = scene; scene.RegisterModuleInterface(this); + scenePermissions = m_scene.Permissions; //Register functions with Scene External Checks! - m_scene.Permissions.OnBypassPermissions += BypassPermissions; - m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; - m_scene.Permissions.OnPropagatePermissions += PropagatePermissions; - m_scene.Permissions.OnGenerateClientFlags += GenerateClientFlags; - m_scene.Permissions.OnAbandonParcel += CanAbandonParcel; - m_scene.Permissions.OnReclaimParcel += CanReclaimParcel; - m_scene.Permissions.OnDeedParcel += CanDeedParcel; - m_scene.Permissions.OnDeedObject += CanDeedObject; - m_scene.Permissions.OnIsGod += IsGod; - m_scene.Permissions.OnIsGridGod += IsGridGod; - m_scene.Permissions.OnIsAdministrator += IsAdministrator; - m_scene.Permissions.OnIsEstateManager += IsEstateManager; - m_scene.Permissions.OnDuplicateObject += CanDuplicateObject; - m_scene.Permissions.OnDeleteObject += CanDeleteObject; - m_scene.Permissions.OnEditObject += CanEditObject; - m_scene.Permissions.OnEditParcelProperties += CanEditParcelProperties; - m_scene.Permissions.OnInstantMessage += CanInstantMessage; - m_scene.Permissions.OnInventoryTransfer += CanInventoryTransfer; - m_scene.Permissions.OnIssueEstateCommand += CanIssueEstateCommand; - m_scene.Permissions.OnMoveObject += CanMoveObject; - m_scene.Permissions.OnObjectEntry += CanObjectEntry; - m_scene.Permissions.OnReturnObjects += CanReturnObjects; - m_scene.Permissions.OnRezObject += CanRezObject; - m_scene.Permissions.OnRunConsoleCommand += CanRunConsoleCommand; - m_scene.Permissions.OnRunScript += CanRunScript; - m_scene.Permissions.OnCompileScript += CanCompileScript; - m_scene.Permissions.OnSellParcel += CanSellParcel; - m_scene.Permissions.OnTakeObject += CanTakeObject; - m_scene.Permissions.OnSellGroupObject += CanSellGroupObject; - m_scene.Permissions.OnTakeCopyObject += CanTakeCopyObject; - m_scene.Permissions.OnTerraformLand += CanTerraformLand; - m_scene.Permissions.OnLinkObject += CanLinkObject; - m_scene.Permissions.OnDelinkObject += CanDelinkObject; - m_scene.Permissions.OnBuyLand += CanBuyLand; + scenePermissions.OnBypassPermissions += BypassPermissions; + scenePermissions.OnSetBypassPermissions += SetBypassPermissions; + scenePermissions.OnPropagatePermissions += PropagatePermissions; - m_scene.Permissions.OnViewNotecard += CanViewNotecard; - m_scene.Permissions.OnViewScript += CanViewScript; - m_scene.Permissions.OnEditNotecard += CanEditNotecard; - m_scene.Permissions.OnEditScript += CanEditScript; + scenePermissions.OnIsGridGod += IsGridAdministrator; + scenePermissions.OnIsAdministrator += IsAdministrator; + scenePermissions.OnIsEstateManager += IsEstateManager; - m_scene.Permissions.OnCreateObjectInventory += CanCreateObjectInventory; - m_scene.Permissions.OnEditObjectInventory += CanEditObjectInventory; - m_scene.Permissions.OnCopyObjectInventory += CanCopyObjectInventory; - m_scene.Permissions.OnDeleteObjectInventory += CanDeleteObjectInventory; - m_scene.Permissions.OnResetScript += CanResetScript; + scenePermissions.OnGenerateClientFlags += GenerateClientFlags; - m_scene.Permissions.OnCreateUserInventory += CanCreateUserInventory; - m_scene.Permissions.OnCopyUserInventory += CanCopyUserInventory; - m_scene.Permissions.OnEditUserInventory += CanEditUserInventory; - m_scene.Permissions.OnDeleteUserInventory += CanDeleteUserInventory; + scenePermissions.OnIssueEstateCommand += CanIssueEstateCommand; + scenePermissions.OnRunConsoleCommand += CanRunConsoleCommand; - m_scene.Permissions.OnTeleport += CanTeleport; + scenePermissions.OnTeleport += CanTeleport; - m_scene.Permissions.OnControlPrimMedia += CanControlPrimMedia; - m_scene.Permissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia; + scenePermissions.OnInstantMessage += CanInstantMessage; + + scenePermissions.OnAbandonParcel += CanAbandonParcel; + scenePermissions.OnReclaimParcel += CanReclaimParcel; + scenePermissions.OnDeedParcel += CanDeedParcel; + scenePermissions.OnSellParcel += CanSellParcel; + scenePermissions.OnEditParcelProperties += CanEditParcelProperties; + scenePermissions.OnTerraformLand += CanTerraformLand; + scenePermissions.OnBuyLand += CanBuyLand; + + scenePermissions.OnReturnObjects += CanReturnObjects; + + scenePermissions.OnRezObject += CanRezObject; + scenePermissions.OnObjectEntry += CanObjectEntry; + scenePermissions.OnObjectEnterWithScripts += OnObjectEnterWithScripts; + + scenePermissions.OnDuplicateObject += CanDuplicateObject; + scenePermissions.OnDeleteObjectByIDs += CanDeleteObjectByIDs; + scenePermissions.OnDeleteObject += CanDeleteObject; + scenePermissions.OnEditObjectByIDs += CanEditObjectByIDs; + scenePermissions.OnEditObject += CanEditObject; + scenePermissions.OnEditObjectPerms += CanEditObjectPerms; + scenePermissions.OnInventoryTransfer += CanInventoryTransfer; + scenePermissions.OnMoveObject += CanMoveObject; + scenePermissions.OnTakeObject += CanTakeObject; + scenePermissions.OnTakeCopyObject += CanTakeCopyObject; + scenePermissions.OnLinkObject += CanLinkObject; + scenePermissions.OnDelinkObject += CanDelinkObject; + scenePermissions.OnDeedObject += CanDeedObject; + scenePermissions.OnSellGroupObject += CanSellGroupObject; + scenePermissions.OnSellObjectByUserID += CanSellObjectByUserID; + scenePermissions.OnSellObject += CanSellObject; + + scenePermissions.OnCreateObjectInventory += CanCreateObjectInventory; + scenePermissions.OnEditObjectInventory += CanEditObjectInventory; + scenePermissions.OnCopyObjectInventory += CanCopyObjectInventory; + scenePermissions.OnDeleteObjectInventory += CanDeleteObjectInventory; + scenePermissions.OnDoObjectInvToObjectInv += CanDoObjectInvToObjectInv; + scenePermissions.OnDropInObjectInv += CanDropInObjectInv; + + scenePermissions.OnViewNotecard += CanViewNotecard; + scenePermissions.OnViewScript += CanViewScript; + scenePermissions.OnEditNotecard += CanEditNotecard; + scenePermissions.OnEditScript += CanEditScript; + scenePermissions.OnResetScript += CanResetScript; + scenePermissions.OnRunScript += CanRunScript; + scenePermissions.OnCompileScript += CanCompileScript; + + scenePermissions.OnCreateUserInventory += CanCreateUserInventory; + scenePermissions.OnCopyUserInventory += CanCopyUserInventory; + scenePermissions.OnEditUserInventory += CanEditUserInventory; + scenePermissions.OnDeleteUserInventory += CanDeleteUserInventory; + + scenePermissions.OnControlPrimMedia += CanControlPrimMedia; + scenePermissions.OnInteractWithPrimMedia += CanInteractWithPrimMedia; m_scene.AddCommand("Users", this, "bypass permissions", "bypass permissions ", @@ -351,6 +355,79 @@ namespace OpenSim.Region.CoreModules.World.Permissions return; m_scene.UnregisterModuleInterface(this); + + scenePermissions.OnBypassPermissions -= BypassPermissions; + scenePermissions.OnSetBypassPermissions -= SetBypassPermissions; + scenePermissions.OnPropagatePermissions -= PropagatePermissions; + + scenePermissions.OnIsGridGod -= IsGridAdministrator; + scenePermissions.OnIsAdministrator -= IsAdministrator; + scenePermissions.OnIsEstateManager -= IsEstateManager; + + scenePermissions.OnGenerateClientFlags -= GenerateClientFlags; + + scenePermissions.OnIssueEstateCommand -= CanIssueEstateCommand; + scenePermissions.OnRunConsoleCommand -= CanRunConsoleCommand; + + scenePermissions.OnTeleport -= CanTeleport; + + scenePermissions.OnInstantMessage -= CanInstantMessage; + + scenePermissions.OnAbandonParcel -= CanAbandonParcel; + scenePermissions.OnReclaimParcel -= CanReclaimParcel; + scenePermissions.OnDeedParcel -= CanDeedParcel; + scenePermissions.OnSellParcel -= CanSellParcel; + scenePermissions.OnEditParcelProperties -= CanEditParcelProperties; + scenePermissions.OnTerraformLand -= CanTerraformLand; + scenePermissions.OnBuyLand -= CanBuyLand; + + scenePermissions.OnRezObject -= CanRezObject; + scenePermissions.OnObjectEntry -= CanObjectEntry; + scenePermissions.OnObjectEnterWithScripts -= OnObjectEnterWithScripts; + + scenePermissions.OnReturnObjects -= CanReturnObjects; + + scenePermissions.OnDuplicateObject -= CanDuplicateObject; + scenePermissions.OnDeleteObjectByIDs -= CanDeleteObjectByIDs; + scenePermissions.OnDeleteObject -= CanDeleteObject; + scenePermissions.OnEditObjectByIDs -= CanEditObjectByIDs; + scenePermissions.OnEditObject -= CanEditObject; + scenePermissions.OnEditObjectPerms -= CanEditObjectPerms; + scenePermissions.OnInventoryTransfer -= CanInventoryTransfer; + scenePermissions.OnMoveObject -= CanMoveObject; + scenePermissions.OnTakeObject -= CanTakeObject; + scenePermissions.OnTakeCopyObject -= CanTakeCopyObject; + scenePermissions.OnLinkObject -= CanLinkObject; + scenePermissions.OnDelinkObject -= CanDelinkObject; + scenePermissions.OnDeedObject -= CanDeedObject; + + scenePermissions.OnSellGroupObject -= CanSellGroupObject; + scenePermissions.OnSellObjectByUserID -= CanSellObjectByUserID; + scenePermissions.OnSellObject -= CanSellObject; + + scenePermissions.OnCreateObjectInventory -= CanCreateObjectInventory; + scenePermissions.OnEditObjectInventory -= CanEditObjectInventory; + scenePermissions.OnCopyObjectInventory -= CanCopyObjectInventory; + scenePermissions.OnDeleteObjectInventory -= CanDeleteObjectInventory; + scenePermissions.OnDoObjectInvToObjectInv -= CanDoObjectInvToObjectInv; + scenePermissions.OnDropInObjectInv -= CanDropInObjectInv; + + scenePermissions.OnViewNotecard -= CanViewNotecard; + scenePermissions.OnViewScript -= CanViewScript; + scenePermissions.OnEditNotecard -= CanEditNotecard; + scenePermissions.OnEditScript -= CanEditScript; + scenePermissions.OnResetScript -= CanResetScript; + scenePermissions.OnRunScript -= CanRunScript; + scenePermissions.OnCompileScript -= CanCompileScript; + + scenePermissions.OnCreateUserInventory -= CanCreateUserInventory; + scenePermissions.OnCopyUserInventory -= CanCopyUserInventory; + scenePermissions.OnEditUserInventory -= CanEditUserInventory; + scenePermissions.OnDeleteUserInventory -= CanDeleteUserInventory; + + scenePermissions.OnControlPrimMedia -= CanControlPrimMedia; + scenePermissions.OnInteractWithPrimMedia -= CanInteractWithPrimMedia; + } public void Close() @@ -480,6 +557,36 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; } + protected bool GroupMemberPowers(UUID groupID, UUID userID, ref ulong powers) + { + powers = 0; + if (null == GroupsModule) + return false; + + GroupMembershipData gmd = GroupsModule.GetMembershipData(groupID, userID); + + if (gmd != null) + { + powers = gmd.GroupPowers; + return true; + } + return false; + } + + protected bool GroupMemberPowers(UUID groupID, ScenePresence sp, ref ulong powers) + { + powers = 0; + IClientAPI client = sp.ControllingClient; + if (client == null) + return false; + + if(!client.IsGroupMember(groupID)) + return false; + + powers = client.GetGroupPowers(groupID); + return true; + } + /// /// Parse a user set configuration setting /// @@ -526,13 +633,13 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (user == UUID.Zero) return false; - if (m_scene.RegionInfo.EstateSettings.EstateOwner == user && m_RegionOwnerIsGod) + if (m_RegionOwnerIsAdmin && m_scene.RegionInfo.EstateSettings.EstateOwner == user) return true; - if (IsEstateManager(user) && m_RegionManagerIsGod) + if (m_RegionManagerIsAdmin && IsEstateManager(user)) return true; - if (IsGridGod(user, null)) + if (IsGridAdministrator(user)) return true; return false; @@ -544,14 +651,15 @@ namespace OpenSim.Region.CoreModules.World.Permissions /// The user /// Unused, can be null /// - protected bool IsGridGod(UUID user, Scene scene) + protected bool IsGridAdministrator(UUID user) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - if (user == UUID.Zero) return false; + if (user == UUID.Zero) + return false; - if (m_allowGridGods) + if (m_allowGridAdmins) { ScenePresence sp = m_scene.GetScenePresence(user); if (sp != null) @@ -567,10 +675,10 @@ namespace OpenSim.Region.CoreModules.World.Permissions protected bool IsFriendWithPerms(UUID user, UUID objectOwner) { - if (user == UUID.Zero) + if (FriendsModule == null) return false; - if (FriendsModule == null) + if (user == UUID.Zero) return false; int friendPerms = FriendsModule.GetRightsGrantedByFriend(user, objectOwner); @@ -606,75 +714,178 @@ namespace OpenSim.Region.CoreModules.World.Permissions #region Object Permissions - public uint GenerateClientFlags(UUID user, UUID objID) + const uint DEFAULT_FLAGS = (uint)( + PrimFlags.ObjectCopy | // Tells client you can copy the object + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object + ); + + const uint NOT_DEFAULT_FLAGS = (uint)~( + PrimFlags.ObjectCopy | // Tells client you can copy the object + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object + ); + + const uint EXTRAOWNERMASK = (uint)( + PrimFlags.ObjectYouOwner | + PrimFlags.ObjectAnyOwner + ); + + const uint EXTRAGODMASK = (uint)( + PrimFlags.ObjectYouOwner | + PrimFlags.ObjectAnyOwner | + PrimFlags.ObjectOwnerModify | + PrimFlags.ObjectModify | + PrimFlags.ObjectMove + ); + + const uint GOD_FLAGS = (uint)( + PrimFlags.ObjectCopy | // Tells client you can copy the object + PrimFlags.ObjectModify | // tells client you can modify the object + PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object + PrimFlags.ObjectOwnerModify // Tells client that you're the owner of the object + ); + + const uint LOCKED_GOD_FLAGS = (uint)( + PrimFlags.ObjectCopy | // Tells client you can copy the object + PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it + PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object + PrimFlags.ObjectAnyOwner // Tells client that someone owns the object + ); + + const uint SHAREDMASK = (uint)( + PermissionMask.Move | + PermissionMask.Modify | + PermissionMask.Copy + ); + + public uint GenerateClientFlags(SceneObjectPart task, ScenePresence sp, uint curEffectivePerms) { - // Here's the way this works, - // ObjectFlags and Permission flags are two different enumerations - // ObjectFlags, however, tells the client to change what it will allow the user to do. - // So, that means that all of the permissions type ObjectFlags are /temporary/ and only - // supposed to be set when customizing the objectflags for the client. - - // These temporary objectflags get computed and added in this function based on the - // Permission mask that's appropriate! - // Outside of this method, they should never be added to objectflags! - // -teravus - - SceneObjectPart task = m_scene.GetSceneObjectPart(objID); - - // this shouldn't ever happen.. return no permissions/objectflags. - if (task == null) - return (uint)0; - - uint objflags = task.GetEffectiveObjectFlags(); - UUID objectOwner = task.OwnerID; - + if(sp == null || task == null || curEffectivePerms == 0) + return 0; // Remove any of the objectFlags that are temporary. These will get added back if appropriate - // in the next bit of code + uint objflags = curEffectivePerms & NOT_DEFAULT_FLAGS ; - // libomv will moan about PrimFlags.ObjectYouOfficer being - // deprecated -#pragma warning disable 0612 - objflags &= (uint) - ~(PrimFlags.ObjectCopy | // Tells client you can copy the object - PrimFlags.ObjectModify | // tells client you can modify the object - PrimFlags.ObjectMove | // tells client that you can move the object (only, no mod) - PrimFlags.ObjectTransfer | // tells the client that you can /take/ the object if you don't own it - PrimFlags.ObjectYouOwner | // Tells client that you're the owner of the object - PrimFlags.ObjectAnyOwner | // Tells client that someone owns the object - PrimFlags.ObjectOwnerModify | // Tells client that you're the owner of the object - PrimFlags.ObjectYouOfficer // Tells client that you've got group object editing permission. Used when ObjectGroupOwned is set - ); -#pragma warning restore 0612 + uint returnMask; - // Creating the three ObjectFlags options for this method to choose from. - // Customize the OwnerMask - uint objectOwnerMask = ApplyObjectModifyMasks(task.OwnerMask, objflags); - objectOwnerMask |= (uint)PrimFlags.ObjectYouOwner | (uint)PrimFlags.ObjectAnyOwner | (uint)PrimFlags.ObjectOwnerModify; + SceneObjectGroup grp = task.ParentGroup; + if(grp == null) + return 0; - // Customize the GroupMask - uint objectGroupMask = ApplyObjectModifyMasks(task.GroupMask, objflags); + UUID taskOwnerID = task.OwnerID; + UUID spID = sp.UUID; - // Customize the EveryoneMask - uint objectEveryoneMask = ApplyObjectModifyMasks(task.EveryoneMask, objflags); - if (objectOwner != UUID.Zero) - objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; + bool unlocked = (grp.RootPart.OwnerMask & (uint)PermissionMask.Move) != 0; - PermissionClass permissionClass = GetPermissionClass(user, task); - - switch (permissionClass) + if(sp.IsGod) { - case PermissionClass.Owner: - return objectOwnerMask; - case PermissionClass.Group: - return objectGroupMask | objectEveryoneMask; - case PermissionClass.Everyone: - default: - return objectEveryoneMask; + // do locked on objects owned by admin + if(!unlocked && spID == taskOwnerID) + return objflags | LOCKED_GOD_FLAGS; + else + return objflags | GOD_FLAGS; } + + //bypass option == owner rights + if (m_bypassPermissions) + { + returnMask = ApplyObjectModifyMasks(task.OwnerMask, objflags, true); //?? + returnMask |= EXTRAOWNERMASK; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + + // owner + if (spID == taskOwnerID) + { + returnMask = ApplyObjectModifyMasks(grp.EffectiveOwnerPerms, objflags, unlocked); + returnMask |= EXTRAOWNERMASK; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + + // if not god or owner, do attachments as everyone + if(task.ParentGroup.IsAttachment) + { + returnMask = ApplyObjectModifyMasks(grp.EffectiveEveryOnePerms, objflags, unlocked); + if (taskOwnerID != UUID.Zero) + returnMask |= (uint)PrimFlags.ObjectAnyOwner; + return returnMask; + } + + UUID taskGroupID = task.GroupID; + bool notGroupdOwned = taskOwnerID != taskGroupID; + + // if friends with rights then owner + if (notGroupdOwned && IsFriendWithPerms(spID, taskOwnerID)) + { + returnMask = ApplyObjectModifyMasks(grp.EffectiveOwnerPerms, objflags, unlocked); + returnMask |= EXTRAOWNERMASK; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + + // group owned or shared ? + IClientAPI client = sp.ControllingClient; + ulong powers = 0; + if(taskGroupID != UUID.Zero && GroupMemberPowers(taskGroupID, sp, ref powers)) + { + if(notGroupdOwned) + { + // group sharing or everyone + returnMask = ApplyObjectModifyMasks(grp.EffectiveGroupOrEveryOnePerms, objflags, unlocked); + if (taskOwnerID != UUID.Zero) + returnMask |= (uint)PrimFlags.ObjectAnyOwner; + return returnMask; + } + + // object is owned by group, check role powers + if((powers & (ulong)GroupPowers.ObjectManipulate) == 0) + { + // group sharing or everyone + returnMask = ApplyObjectModifyMasks(grp.EffectiveGroupOrEveryOnePerms, objflags, unlocked); + returnMask |= + (uint)PrimFlags.ObjectGroupOwned | + (uint)PrimFlags.ObjectAnyOwner; + return returnMask; + } + + // we may have copy without transfer + uint grpEffectiveOwnerPerms = grp.EffectiveOwnerPerms; + if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0) + grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy; + returnMask = ApplyObjectModifyMasks(grpEffectiveOwnerPerms, objflags, unlocked); + returnMask |= + (uint)PrimFlags.ObjectGroupOwned | + (uint)PrimFlags.ObjectYouOwner; + if((returnMask & (uint)PrimFlags.ObjectModify) != 0) + returnMask |= (uint)PrimFlags.ObjectOwnerModify; + return returnMask; + } + + // fallback is everyone rights + returnMask = ApplyObjectModifyMasks(grp.EffectiveEveryOnePerms, objflags, unlocked); + if (taskOwnerID != UUID.Zero) + returnMask |= (uint)PrimFlags.ObjectAnyOwner; + return returnMask; } - private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) + private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask, bool unlocked) { // We are adding the temporary objectflags to the object's objectflags based on the // permission flag given. These change the F flags on the client. @@ -684,14 +895,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions objectFlagsMask |= (uint)PrimFlags.ObjectCopy; } - if ((setPermissionMask & (uint)PermissionMask.Move) != 0) + if (unlocked) { - objectFlagsMask |= (uint)PrimFlags.ObjectMove; - } + if ((setPermissionMask & (uint)PermissionMask.Move) != 0) + { + objectFlagsMask |= (uint)PrimFlags.ObjectMove; + } - if ((setPermissionMask & (uint)PermissionMask.Modify) != 0) - { - objectFlagsMask |= (uint)PrimFlags.ObjectModify; + if ((setPermissionMask & (uint)PermissionMask.Modify) != 0) + { + objectFlagsMask |= (uint)PrimFlags.ObjectModify; + } } if ((setPermissionMask & (uint)PermissionMask.Transfer) != 0) @@ -702,6 +916,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return objectFlagsMask; } + // OARs still need this method that handles offline users public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj) { if (obj == null) @@ -715,136 +930,199 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (user == objectOwner) return PermissionClass.Owner; - if (IsFriendWithPerms(user, objectOwner) && !obj.ParentGroup.IsAttachment) - return PermissionClass.Owner; - - // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set - if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) - return PermissionClass.Owner; - // Admin should be able to edit anything in the sim (including admin objects) if (IsAdministrator(user)) return PermissionClass.Owner; -/* to review later - // Users should be able to edit what is over their land. - Vector3 taskPos = obj.AbsolutePosition; - ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); - if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod) + if(!obj.ParentGroup.IsAttachment) { - // Admin objects should not be editable by the above - if (!IsAdministrator(objectOwner)) + if (IsFriendWithPerms(user, objectOwner) ) return PermissionClass.Owner; + + // Group permissions + if (obj.GroupID != UUID.Zero && IsGroupMember(obj.GroupID, user, 0)) + return PermissionClass.Group; } -*/ - // Group permissions - if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0)) - return PermissionClass.Group; return PermissionClass.Everyone; } - /// - /// General permissions checks for any operation involving an object. These supplement more specific checks - /// implemented by callers. - /// - /// - /// This is a scene object group UUID - /// - /// - protected bool GenericObjectPermission(UUID currentUser, UUID objId, bool denyOnLocked) + // get effective object permissions using user UUID. User rights will be fixed + protected uint GetObjectPermissions(UUID currentUser, SceneObjectGroup group, bool denyOnLocked) { - // Default: deny - bool permission = false; - bool locked = false; + if (group == null) + return 0; - SceneObjectPart part = m_scene.GetSceneObjectPart(objId); - - if (part == null) - return false; - - SceneObjectGroup group = part.ParentGroup; + SceneObjectPart root = group.RootPart; + if (root == null) + return 0; UUID objectOwner = group.OwnerID; - locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); + bool locked = denyOnLocked && ((root.OwnerMask & (uint)PermissionMask.Move) == 0); - // People shouldn't be able to do anything with locked objects, except the Administrator - // The 'set permissions' runs through a different permission check, so when an object owner - // sets an object locked, the only thing that they can do is unlock it. - // - // Nobody but the object owner can set permissions on an object - // - if (locked && (!IsAdministrator(currentUser)) && denyOnLocked) - { - return false; - } - - // Object owners should be able to edit their own content - if (currentUser == objectOwner) - { - // there is no way that later code can change this back to false - // so just return true immediately and short circuit the more - // expensive group checks - return true; - - //permission = true; - } - else if (group.IsAttachment) - { - permission = false; - } - -// m_log.DebugFormat( -// "[PERMISSIONS]: group.GroupID = {0}, part.GroupMask = {1}, isGroupMember = {2} for {3}", -// group.GroupID, -// m_scene.GetSceneObjectPart(objId).GroupMask, -// IsGroupMember(group.GroupID, currentUser, 0), -// currentUser); - - // Group members should be able to edit group objects - if ((group.GroupID != UUID.Zero) - && ((m_scene.GetSceneObjectPart(objId).GroupMask & (uint)PermissionMask.Modify) != 0) - && IsGroupMember(group.GroupID, currentUser, 0)) - { - // Return immediately, so that the administrator can shares group objects - return true; - } - - // Friends with benefits should be able to edit the objects too - if (IsFriendWithPerms(currentUser, objectOwner)) - { - // Return immediately, so that the administrator can share objects with friends - return true; - } - - // Users should be able to edit what is over their land. - ILandObject parcel = m_scene.LandChannel.GetLandObject(group.AbsolutePosition.X, group.AbsolutePosition.Y); - if ((parcel != null) && (parcel.LandData.OwnerID == currentUser)) - { - permission = true; - } - - // Estate users should be able to edit anything in the sim - if (IsEstateManager(currentUser)) - { - permission = true; - } - - // Admin objects should not be editable by the above - if (IsAdministrator(objectOwner)) - { - permission = false; - } - - // Admin should be able to edit anything in the sim (including admin objects) if (IsAdministrator(currentUser)) { - permission = true; + // do lock on admin owned objects + if(locked && currentUser == objectOwner) + return (uint)(PermissionMask.AllEffective & ~(PermissionMask.Modify | PermissionMask.Move)); + return (uint)PermissionMask.AllEffective; } - return permission; + uint lockmask = (uint)PermissionMask.AllEffective; + if(locked) + lockmask &= ~(uint)(PermissionMask.Modify | PermissionMask.Move); + + if (currentUser == objectOwner) + return group.EffectiveOwnerPerms & lockmask; + + if (group.IsAttachment) + return 0; + + UUID sogGroupID = group.GroupID; + bool notgroudOwned = sogGroupID != objectOwner; + + if (notgroudOwned && IsFriendWithPerms(currentUser, objectOwner)) + return group.EffectiveOwnerPerms & lockmask; + + ulong powers = 0; + if (sogGroupID != UUID.Zero && GroupMemberPowers(sogGroupID, currentUser, ref powers)) + { + if(notgroudOwned) + return group.EffectiveGroupOrEveryOnePerms & lockmask; + + if((powers & (ulong)GroupPowers.ObjectManipulate) == 0) + return group.EffectiveGroupOrEveryOnePerms & lockmask; + + uint grpEffectiveOwnerPerms = group.EffectiveOwnerPerms & lockmask; + if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0) + grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy; + return grpEffectiveOwnerPerms; + } + + return group.EffectiveEveryOnePerms & lockmask; } + // get effective object permissions using present presence. So some may depend on requested rights (ie God) + protected uint GetObjectPermissions(ScenePresence sp, SceneObjectGroup group, bool denyOnLocked) + { + if (sp == null || sp.IsDeleted || group == null || group.IsDeleted) + return 0; + + SceneObjectPart root = group.RootPart; + if (root == null) + return 0; + + UUID spID = sp.UUID; + UUID objectOwner = group.OwnerID; + + bool locked = denyOnLocked && ((root.OwnerMask & (uint)PermissionMask.Move) == 0); + + if (sp.IsGod) + { + if(locked && spID == objectOwner) + return (uint)(PermissionMask.AllEffective & ~(PermissionMask.Modify | PermissionMask.Move)); + return (uint)PermissionMask.AllEffective; + } + + uint lockmask = (uint)PermissionMask.AllEffective; + if(locked) + lockmask &= ~(uint)(PermissionMask.Modify | PermissionMask.Move); + + if (spID == objectOwner) + return group.EffectiveOwnerPerms & lockmask; + + if (group.IsAttachment) + return 0; + + UUID sogGroupID = group.GroupID; + bool notgroudOwned = sogGroupID != objectOwner; + + if (notgroudOwned && IsFriendWithPerms(spID, objectOwner)) + return group.EffectiveOwnerPerms & lockmask; + + ulong powers = 0; + if (sogGroupID != UUID.Zero && GroupMemberPowers(sogGroupID, sp, ref powers)) + { + if(notgroudOwned) + return group.EffectiveGroupOrEveryOnePerms & lockmask; + + if((powers & (ulong)GroupPowers.ObjectManipulate) == 0) + return group.EffectiveGroupOrEveryOnePerms & lockmask; + + uint grpEffectiveOwnerPerms = group.EffectiveOwnerPerms & lockmask; + if((grpEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0) + grpEffectiveOwnerPerms &= ~(uint)PermissionMask.Copy; + return grpEffectiveOwnerPerms; + } + + return group.EffectiveEveryOnePerms & lockmask; + } + + private uint GetObjectItemPermissions(UUID userID, TaskInventoryItem ti) + { + UUID tiOwnerID = ti.OwnerID; + if(tiOwnerID == userID) + return ti.CurrentPermissions; + + if(IsAdministrator(userID)) + return (uint)PermissionMask.AllEffective; + // ?? + if (IsFriendWithPerms(userID, tiOwnerID)) + return ti.CurrentPermissions; + + UUID tiGroupID = ti.GroupID; + if(tiGroupID != UUID.Zero) + { + ulong powers = 0; + if(GroupMemberPowers(tiGroupID, userID, ref powers)) + { + if(tiGroupID == ti.OwnerID) + { + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + return ti.CurrentPermissions; + } + return ti.GroupPermissions; + } + } + + return 0; + } + + private uint GetObjectItemPermissions(ScenePresence sp, TaskInventoryItem ti, bool notEveryone) + { + UUID tiOwnerID = ti.OwnerID; + UUID spID = sp.UUID; + + if(tiOwnerID == spID) + return ti.CurrentPermissions; + + // ?? + if (IsFriendWithPerms(spID, tiOwnerID)) + return ti.CurrentPermissions; + + UUID tiGroupID = ti.GroupID; + if(tiGroupID != UUID.Zero) + { + ulong powers = 0; + if(GroupMemberPowers(tiGroupID, spID, ref powers)) + { + if(tiGroupID == ti.OwnerID) + { + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + return ti.CurrentPermissions; + } + uint p = ti.GroupPermissions; + if(!notEveryone) + p |= ti.EveryonePermissions; + return p; + } + } + + if(notEveryone) + return 0; + + return ti.EveryonePermissions; + } #endregion #region Generic Permissions @@ -869,89 +1147,37 @@ namespace OpenSim.Region.CoreModules.World.Permissions public bool GenericEstatePermission(UUID user) { - // Default: deny - bool permission = false; - // Estate admins should be able to use estate tools if (IsEstateManager(user)) - permission = true; + return true; // Administrators always have permission if (IsAdministrator(user)) - permission = true; + return true; - return permission; - } - - protected bool GenericParcelPermission(UUID user, ILandObject parcel, ulong groupPowers) - { - bool permission = false; - - if (parcel.LandData.OwnerID == user) - { - permission = true; - } - - if ((parcel.LandData.GroupID != UUID.Zero) && IsGroupMember(parcel.LandData.GroupID, user, groupPowers)) - { - permission = true; - } - - if (IsEstateManager(user)) - { - permission = true; - } - - if (IsAdministrator(user)) - { - permission = true; - } - - if (m_SimpleBuildPermissions && - (parcel.LandData.Flags & (uint)ParcelFlags.UseAccessList) == 0 && parcel.IsInLandAccessList(user)) - permission = true; - - return permission; + return false; } protected bool GenericParcelOwnerPermission(UUID user, ILandObject parcel, ulong groupPowers, bool allowEstateManager) { if (parcel.LandData.OwnerID == user) - { - // Returning immediately so that group deeded objects on group deeded land don't trigger a NRE on - // the subsequent redundant checks when using lParcelMediaCommandList() - // See http://opensimulator.org/mantis/view.php?id=3999 for more details return true; - } if (parcel.LandData.IsGroupOwned && IsGroupMember(parcel.LandData.GroupID, user, groupPowers)) - { return true; - } if (allowEstateManager && IsEstateManager(user)) - { return true; - } if (IsAdministrator(user)) - { return true; - } return false; } - - protected bool GenericParcelPermission(UUID user, Vector3 pos, ulong groupPowers) - { - ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); - if (parcel == null) return false; - return GenericParcelPermission(user, parcel, groupPowers); - } #endregion #region Permission Checks - private bool CanAbandonParcel(UUID user, ILandObject parcel, Scene scene) + private bool CanAbandonParcel(UUID user, ILandObject parcel) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -959,7 +1185,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandRelease, false); } - private bool CanReclaimParcel(UUID user, ILandObject parcel, Scene scene) + private bool CanReclaimParcel(UUID user, ILandObject parcel) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -967,108 +1193,252 @@ namespace OpenSim.Region.CoreModules.World.Permissions return GenericParcelOwnerPermission(user, parcel, 0,true); } - private bool CanDeedParcel(UUID user, ILandObject parcel, Scene scene) + private bool CanDeedParcel(UUID user, ILandObject parcel) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; + if(parcel.LandData.GroupID == UUID.Zero) + return false; + + if (IsAdministrator(user)) + return true; + if (parcel.LandData.OwnerID != user) // Only the owner can deed! return false; - ScenePresence sp = scene.GetScenePresence(user); - IClientAPI client = sp.ControllingClient; - - if ((client.GetGroupPowers(parcel.LandData.GroupID) & (ulong)GroupPowers.LandDeed) == 0) + ScenePresence sp = m_scene.GetScenePresence(user); + if(sp == null) return false; - return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandDeed, false); - } - - private bool CanDeedObject(UUID user, UUID group, Scene scene) - { - DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; - - ScenePresence sp = scene.GetScenePresence(user); IClientAPI client = sp.ControllingClient; - - if ((client.GetGroupPowers(group) & (ulong)GroupPowers.DeedObject) == 0) + if ((client.GetGroupPowers(parcel.LandData.GroupID) & (ulong)GroupPowers.LandDeed) == 0) return false; return true; } - private bool IsGod(UUID user, Scene scene) + private bool CanDeedObject(ScenePresence sp, SceneObjectGroup sog, UUID targetGroupID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return IsAdministrator(user); + if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted || targetGroupID == UUID.Zero) + return false; + + // object has group already? + if(sog.GroupID != targetGroupID) + return false; + + // is effectivelly shared? + if(sog.EffectiveGroupPerms == 0) + return false; + + if(sp.IsGod) + return true; + + // owned by requester? + if(sog.OwnerID != sp.UUID) + return false; + + // owner can transfer? + if((sog.EffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0) + return false; + + // group member ? + ulong powers = 0; + if(!GroupMemberPowers(targetGroupID, sp, ref powers)) + return false; + + // has group rights? + if ((powers & (ulong)GroupPowers.DeedObject) == 0) + return false; + + return true; } - private bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition) + private bool CanDuplicateObject(SceneObjectGroup sog, ScenePresence sp) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - if (!GenericObjectPermission(owner, objectID, true)) - { - //They can't even edit the object - return false; - } - - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - if (part == null) + if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted) return false; - if (part.OwnerID == owner) - { - if ((part.OwnerMask & PERM_COPY) == 0) - return false; - } - else if (part.GroupID != UUID.Zero) - { - if ((part.OwnerID == part.GroupID) && ((owner != part.LastOwnerID) || ((part.GroupMask & PERM_TRANS) == 0))) - return false; + uint perms = GetObjectPermissions(sp, sog, false); + if((perms & (uint)PermissionMask.Copy) == 0) + return false; - if ((part.GroupMask & PERM_COPY) == 0) - return false; - } + if(sog.OwnerID != sp.UUID && (perms & (uint)PermissionMask.Transfer) == 0) + return false; //If they can rez, they can duplicate - return CanRezObject(objectCount, owner, objectPosition, scene); + return CanRezObject(0, sp.UUID, sog.AbsolutePosition); } - private bool CanDeleteObject(UUID objectID, UUID deleter, Scene scene) + private bool CanDeleteObject(SceneObjectGroup sog, ScenePresence sp) + { + // ignoring locked. viewers should warn and ask for confirmation + + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted) + return false; + + if(sog.IsAttachment) + return false; + + UUID sogOwnerID = sog.OwnerID; + UUID spID = sp.UUID; + + if(sogOwnerID == spID) + return true; + + if (sp.IsGod) + return true; + + if (IsFriendWithPerms(sog.UUID, sogOwnerID)) + return true; + + UUID sogGroupID = sog.GroupID; + if (sogGroupID != UUID.Zero) + { + ulong powers = 0; + if(GroupMemberPowers(sogGroupID, sp, ref powers)) + { + if(sogGroupID == sogOwnerID) + { + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + return true; + } + return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0; + } + } + return false; + } + + private bool CanDeleteObjectByIDs(UUID objectID, UUID userID) + { + // ignoring locked. viewers should warn and ask for confirmation + + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID); + if (sog == null) + return false; + + if(sog.IsAttachment) + return false; + + UUID sogOwnerID = sog.OwnerID; + + if(sogOwnerID == userID) + return true; + + if (IsAdministrator(userID)) + return true; + + if (IsFriendWithPerms(objectID, sogOwnerID)) + return true; + + UUID sogGroupID = sog.GroupID; + if (sogGroupID != UUID.Zero) + { + ulong powers = 0; + if(GroupMemberPowers(sogGroupID, userID, ref powers)) + { + if(sogGroupID == sogOwnerID) + { + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + return true; + } + return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0; + } + } + return false; + } + + private bool CanEditObjectByIDs(UUID objectID, UUID userID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(deleter, objectID, false); + SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID); + if (sog == null) + return false; + + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + return true; } - private bool CanEditObject(UUID objectID, UUID editorID, Scene scene) + private bool CanEditObject(SceneObjectGroup sog, ScenePresence sp) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted) + return false; + + uint perms = GetObjectPermissions(sp, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + return true; } - private bool CanEditObjectInventory(UUID objectID, UUID editorID, Scene scene) + private bool CanEditObjectPerms(SceneObjectGroup sog, UUID userID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(editorID, objectID, false); + if (sog == null) + return false; + + if(sog.OwnerID == userID || IsAdministrator(userID)) + return true; + + UUID sogGroupID = sog.GroupID; + if(sogGroupID == UUID.Zero || sogGroupID != sog.OwnerID) + return false; + + uint perms = sog.EffectiveOwnerPerms; + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + + ulong powers = 0; + if(GroupMemberPowers(sogGroupID, userID, ref powers)) + { + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + return true; + } + + return false; } - private bool CanEditParcelProperties(UUID user, ILandObject parcel, GroupPowers p, Scene scene, bool allowManager) + private bool CanEditObjectInventory(UUID objectID, UUID userID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericParcelOwnerPermission(user, parcel, (ulong)p, false); + SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID); + if (sog == null) + return false; + + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + return true; + } + + private bool CanEditParcelProperties(UUID userID, ILandObject parcel, GroupPowers p, bool allowManager) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + return GenericParcelOwnerPermission(userID, parcel, (ulong)p, false); } /// @@ -1079,18 +1449,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions /// /// /// - private bool CanEditScript(UUID script, UUID objectID, UUID user, Scene scene) + private bool CanEditScript(UUID script, UUID objectID, UUID userID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(user)) + if (m_allowedScriptEditors == UserSet.Administrators && !IsAdministrator(userID)) return false; // Ordinarily, if you can view it, you can edit it // There is no viewing a no mod script // - return CanViewScript(script, objectID, user, scene); + return CanViewScript(script, objectID, userID); } /// @@ -1101,7 +1471,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions /// /// /// - private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) + private bool CanEditNotecard(UUID notecard, UUID objectID, UUID user) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -1132,69 +1502,68 @@ namespace OpenSim.Region.CoreModules.World.Permissions } else // Prim inventory { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); if (part == null) return false; - if (part.OwnerID != user) - { - if (part.GroupID == UUID.Zero) - return false; - - if (!IsGroupMember(part.GroupID, user, 0)) - return false; - - if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) - return false; - } - else - { - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + SceneObjectGroup sog = part.ParentGroup; + if (sog == null) + return false; + + // check object mod right + uint perms = GetObjectPermissions(user, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) return false; - } TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); - if (ti == null) return false; - + if (ti.OwnerID != user) { - if (ti.GroupID == UUID.Zero) + UUID tiGroupID = ti.GroupID; + if (tiGroupID == UUID.Zero) return false; - if (!IsGroupMember(ti.GroupID, user, 0)) + ulong powers = 0; + if(!GroupMemberPowers(tiGroupID, user, ref powers)) return false; + + if(tiGroupID == ti.OwnerID && (powers & (ulong)GroupPowers.ObjectManipulate) != 0) + { + if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) == + ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) + return true; + } + if ((ti.GroupPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) == + ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) + return true; + return false; } // Require full perms - if ((ti.CurrentPermissions & - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy)) != - ((uint)PermissionMask.Modify | - (uint)PermissionMask.Copy)) + if ((ti.CurrentPermissions & ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) != + ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy)) return false; } - return true; } - private bool CanInstantMessage(UUID user, UUID target, Scene startScene) + private bool CanInstantMessage(UUID user, UUID target) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; // If the sender is an object, check owner instead // - SceneObjectPart part = startScene.GetSceneObjectPart(user); + SceneObjectPart part = m_scene.GetSceneObjectPart(user); if (part != null) user = part.OwnerID; return GenericCommunicationPermission(user, target); } - private bool CanInventoryTransfer(UUID user, UUID target, Scene startScene) + private bool CanInventoryTransfer(UUID user, UUID target) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -1202,7 +1571,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return GenericCommunicationPermission(user, target); } - private bool CanIssueEstateCommand(UUID user, Scene requestFromScene, bool ownerCommand) + private bool CanIssueEstateCommand(UUID user, bool ownerCommand) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -1210,178 +1579,161 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (IsAdministrator(user)) return true; - if (m_scene.RegionInfo.EstateSettings.IsEstateOwner(user)) - return true; - if (ownerCommand) - return false; + return m_scene.RegionInfo.EstateSettings.IsEstateOwner(user); - return GenericEstatePermission(user); + return IsEstateManager(user); } - private bool CanMoveObject(UUID objectID, UUID moverID, Scene scene) + private bool CanMoveObject(SceneObjectGroup sog, ScenePresence sp) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + + if(sog == null || sog.IsDeleted || sp == null || sp.IsDeleted) + return false; + if (m_bypassPermissions) { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - if (part.OwnerID != moverID) - { - if (!part.ParentGroup.IsDeleted) - { - if (part.ParentGroup.IsAttachment) - return false; - } - } + if (sog.OwnerID != sp.UUID && sog.IsAttachment) + return false; return m_bypassPermissionsValue; } - bool permission = GenericObjectPermission(moverID, objectID, true); - if (!permission) - { - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } - - // The client - // may request to edit linked parts, and therefore, it needs - // to also check for SceneObjectPart - - // If it's not an object, we cant edit it. - if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) - { - return false; - } - - - SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; - - - // UUID taskOwner = null; - // Added this because at this point in time it wouldn't be wise for - // the administrator object permissions to take effect. - // UUID objectOwner = task.OwnerID; - - // Anyone can move - if ((task.RootPart.EveryoneMask & PERM_MOVE) != 0) - permission = true; - - // Locked - if ((task.RootPart.OwnerMask & PERM_LOCKED) == 0) - permission = false; - } - else - { - bool locked = false; - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } - - // If it's not an object, we cant edit it. - if ((!(m_scene.Entities[objectID] is SceneObjectGroup))) - { - return false; - } - - SceneObjectGroup group = (SceneObjectGroup)m_scene.Entities[objectID]; - - UUID objectOwner = group.OwnerID; - locked = ((group.RootPart.OwnerMask & PERM_LOCKED) == 0); - - // This is an exception to the generic object permission. - // Administrators who lock their objects should not be able to move them, - // however generic object permission should return true. - // This keeps locked objects from being affected by random click + drag actions by accident - // and allows the administrator to grab or delete a locked object. - - // Administrators and estate managers are still able to click+grab locked objects not - // owned by them in the scene - // This is by design. - - if (locked && (moverID == objectOwner)) - return false; - } - return permission; + uint perms = GetObjectPermissions(sp, sog, true); + if((perms & (uint)PermissionMask.Move) == 0) + return false; + return true; } - private bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) + private bool CanObjectEntry(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; + float newX = newPoint.X; + float newY = newPoint.Y; - // allow outide region?? - if (newPoint.X < -1f || newPoint.Y < -1f) + // allow outside region this is needed for crossings + if (newX < -1f || newX > (m_scene.RegionInfo.RegionSizeX + 1.0f) || + newY < -1f || newY > (m_scene.RegionInfo.RegionSizeY + 1.0f) ) return true; - if (newPoint.X > scene.RegionInfo.RegionSizeX + 1.0f || newPoint.Y > scene.RegionInfo.RegionSizeY + 1.0f) - { + + if(sog == null || sog.IsDeleted) + return false; + + if (m_bypassPermissions) + return m_bypassPermissionsValue; + + ILandObject parcel = m_scene.LandChannel.GetLandObject(newX, newY); + if (parcel == null) + return false; + + if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowAPrimitiveEntry)) != 0) return true; - } - - SceneObjectGroup task = (SceneObjectGroup)m_scene.Entities[objectID]; - - ILandObject land = m_scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); if (!enteringRegion) { - ILandObject fromland = m_scene.LandChannel.GetLandObject(task.AbsolutePosition.X, task.AbsolutePosition.Y); - - if (fromland == land) // Not entering + Vector3 oldPoint = sog.AbsolutePosition; + ILandObject fromparcel = m_scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); + if (fromparcel != null && fromparcel.Equals(parcel)) // it already entered parcel ???? return true; } - if (land == null) - { - return false; - } + UUID userID = sog.OwnerID; + LandData landdata = parcel.LandData; - if ((land.LandData.Flags & ((int)ParcelFlags.AllowAPrimitiveEntry)) != 0) - { + if (landdata.OwnerID == userID) return true; - } - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } - - // If it's not an object, we cant edit it. - if (!(m_scene.Entities[objectID] is SceneObjectGroup)) - { - return false; - } - - - if (GenericParcelPermission(task.OwnerID, newPoint, 0)) - { + if (IsAdministrator(userID)) return true; + + UUID landGroupID = landdata.GroupID; + if (landGroupID != UUID.Zero) + { + if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowGroupObjectEntry)) != 0) + return IsGroupMember(landGroupID, userID, 0); + + if (landdata.IsGroupOwned && IsGroupMember(landGroupID, userID, (ulong)GroupPowers.AllowRez)) + return true; } //Otherwise, false! return false; } - private bool CanReturnObjects(ILandObject land, UUID user, List objects, Scene scene) + private bool OnObjectEnterWithScripts(SceneObjectGroup sog, ILandObject parcel) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + + if(sog == null || sog.IsDeleted) + return false; + + if (m_bypassPermissions) + return m_bypassPermissionsValue; + + if (parcel == null) + return true; + + int checkflags = ((int)ParcelFlags.AllowAPrimitiveEntry); + bool scripts = (sog.ScriptCount() > 0); + if(scripts) + checkflags |= ((int)ParcelFlags.AllowOtherScripts); + + if ((parcel.LandData.Flags & checkflags) == checkflags) + return true; + + UUID userID = sog.OwnerID; + LandData landdata = parcel.LandData; + + if (landdata.OwnerID == userID) + return true; + + if (IsAdministrator(userID)) + return true; + + UUID landGroupID = landdata.GroupID; + if (landGroupID != UUID.Zero) + { + checkflags = (int)ParcelFlags.AllowGroupObjectEntry; + if(scripts) + checkflags |= ((int)ParcelFlags.AllowGroupScripts); + + if ((parcel.LandData.Flags & checkflags) == checkflags) + return IsGroupMember(landGroupID, userID, 0); + + if (landdata.IsGroupOwned && IsGroupMember(landGroupID, userID, (ulong)GroupPowers.AllowRez)) + return true; + } + + //Otherwise, false! + return false; + } + + private bool CanReturnObjects(ILandObject land, ScenePresence sp, List objects) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - GroupPowers powers; - ILandObject l; + if(sp == null) + return true; // assuming that in this case rights are as owner - ScenePresence sp = scene.GetScenePresence(user); - if (sp == null) - return false; + UUID userID = sp.UUID; + bool isPrivUser = sp.IsGod || IsEstateManager(userID); IClientAPI client = sp.ControllingClient; + ulong powers = 0; + ILandObject l; + foreach (SceneObjectGroup g in new List(objects)) { - // Any user can return their own objects at any time - // - if (GenericObjectPermission(user, g.UUID, false)) + if(g.IsAttachment) + { + objects.Remove(g); + continue; + } + + if (isPrivUser || g.OwnerID == userID) continue; // This is a short cut for efficiency. If land is non-null, @@ -1395,39 +1747,40 @@ namespace OpenSim.Region.CoreModules.World.Permissions else { Vector3 pos = g.AbsolutePosition; - - l = scene.LandChannel.GetLandObject(pos.X, pos.Y); + l = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); } // If it's not over any land, then we can't do a thing - if (l == null) + if (l == null || l.LandData == null) { objects.Remove(g); continue; } + LandData ldata = l.LandData; // If we own the land outright, then allow // - if (l.LandData.OwnerID == user) + if (ldata.OwnerID == userID) continue; // Group voodoo // - if (l.LandData.IsGroupOwned) + if (ldata.IsGroupOwned) { - powers = (GroupPowers)client.GetGroupPowers(l.LandData.GroupID); + UUID lGroupID = ldata.GroupID; // Not a group member, or no rights at all // - if (powers == (GroupPowers)0) + powers = client.GetGroupPowers(lGroupID); + if(powers == 0) { objects.Remove(g); continue; } - + // Group deeded object? // - if (g.OwnerID == l.LandData.GroupID && - (powers & GroupPowers.ReturnGroupOwned) == (GroupPowers)0) + if (g.OwnerID == lGroupID && + (powers & (ulong)GroupPowers.ReturnGroupOwned) == 0) { objects.Remove(g); continue; @@ -1435,14 +1788,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions // Group set object? // - if (g.GroupID == l.LandData.GroupID && - (powers & GroupPowers.ReturnGroupSet) == (GroupPowers)0) + if (g.GroupID == lGroupID && + (powers & (ulong)GroupPowers.ReturnGroupSet) == 0) { objects.Remove(g); continue; } - if ((powers & GroupPowers.ReturnNonGroup) == (GroupPowers)0) + if ((powers & (ulong)GroupPowers.ReturnNonGroup) == 0) { objects.Remove(g); continue; @@ -1465,41 +1818,41 @@ namespace OpenSim.Region.CoreModules.World.Permissions return true; } - private bool CanRezObject(int objectCount, UUID owner, Vector3 objectPosition, Scene scene) + private bool CanRezObject(int objectCount, UUID userID, Vector3 objectPosition) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); - if (m_bypassPermissions) return m_bypassPermissionsValue; + if (m_bypassPermissions) + return m_bypassPermissionsValue; // m_log.DebugFormat("[PERMISSIONS MODULE]: Checking rez object at {0} in {1}", objectPosition, m_scene.Name); ILandObject parcel = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); - if (parcel == null) + if (parcel == null || parcel.LandData == null) return false; - if ((parcel.LandData.Flags & (uint)ParcelFlags.CreateObjects) != 0) - { + LandData landdata = parcel.LandData; + if ((userID == landdata.OwnerID)) return true; - } - else if ((owner == parcel.LandData.OwnerID) || IsAdministrator(owner)) - { + + if ((landdata.Flags & (uint)ParcelFlags.CreateObjects) != 0) return true; - } - else if (((parcel.LandData.Flags & (uint)ParcelFlags.CreateGroupObjects) != 0) - && (parcel.LandData.GroupID != UUID.Zero) && IsGroupMember(parcel.LandData.GroupID, owner, 0)) - { + + if(IsAdministrator(userID)) return true; - } - else if (parcel.LandData.GroupID != UUID.Zero && IsGroupMember(parcel.LandData.GroupID, owner, (ulong)GroupPowers.AllowRez)) + + if(landdata.GroupID != UUID.Zero) { - return true; - } - else - { - return false; + if ((landdata.Flags & (uint)ParcelFlags.CreateGroupObjects) != 0) + return IsGroupMember(landdata.GroupID, userID, 0); + + if (landdata.IsGroupOwned && IsGroupMember(landdata.GroupID, userID, (ulong)GroupPowers.AllowRez)) + return true; } + + return false; } - private bool CanRunConsoleCommand(UUID user, Scene requestFromScene) + private bool CanRunConsoleCommand(UUID user) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -1508,15 +1861,43 @@ namespace OpenSim.Region.CoreModules.World.Permissions return IsAdministrator(user); } - private bool CanRunScript(UUID script, UUID objectID, UUID user, Scene scene) + private bool CanRunScript(TaskInventoryItem scriptitem, SceneObjectPart part) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return true; + if(scriptitem == null || part == null) + return false; + + SceneObjectGroup sog = part.ParentGroup; + if(sog == null) + return false; + + Vector3 pos = sog.AbsolutePosition; + ILandObject parcel = m_scene.LandChannel.GetLandObject(pos.X, pos.Y); + if (parcel == null) + return false; + + LandData ldata = parcel.LandData; + if(ldata == null) + return false; + + uint lflags = ldata.Flags; + + if ((lflags & (uint)ParcelFlags.AllowOtherScripts) != 0) + return true; + + if ((part.OwnerID == ldata.OwnerID)) + return true; + + if (((lflags & (uint)ParcelFlags.AllowGroupScripts) != 0) + && (ldata.GroupID != UUID.Zero) && (ldata.GroupID == part.GroupID)) + return true; + + return GenericEstatePermission(part.OwnerID); } - private bool CanSellParcel(UUID user, ILandObject parcel, Scene scene) + private bool CanSellParcel(UUID user, ILandObject parcel) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -1524,7 +1905,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return GenericParcelOwnerPermission(user, parcel, (ulong)GroupPowers.LandSetSale, true); } - private bool CanSellGroupObject(UUID userID, UUID groupID, Scene scene) + private bool CanSellGroupObject(UUID userID, UUID groupID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -1532,66 +1913,162 @@ namespace OpenSim.Region.CoreModules.World.Permissions return IsGroupMember(groupID, userID, (ulong)GroupPowers.ObjectSetForSale); } - private bool CanTakeObject(UUID objectID, UUID stealer, Scene scene) + private bool CanSellObjectByUserID(SceneObjectGroup sog, UUID userID, byte saleType) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(stealer,objectID, false); + if (sog == null || sog.IsDeleted || userID == UUID.Zero) + return false; + + // sell is not a attachment op + if(sog.IsAttachment) + return false; + + if(IsAdministrator(userID)) + return true; + + uint sogEffectiveOwnerPerms = sog.EffectiveOwnerPerms; + if((sogEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0) + return false; + + if(saleType == (byte)SaleType.Copy && + (sogEffectiveOwnerPerms & (uint)PermissionMask.Copy) == 0) + return false; + + UUID sogOwnerID = sog.OwnerID; + + if(sogOwnerID == userID) + return true; + + // else only group owned can be sold by members with powers + UUID sogGroupID = sog.GroupID; + if(sog.OwnerID != sogGroupID || sogGroupID == UUID.Zero) + return false; + + return IsGroupMember(sogGroupID, userID, (ulong)GroupPowers.ObjectSetForSale); } - private bool CanTakeCopyObject(UUID objectID, UUID userID, Scene inScene) + private bool CanSellObject(SceneObjectGroup sog, ScenePresence sp, byte saleType) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - bool permission = GenericObjectPermission(userID, objectID, false); + if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted) + return false; - SceneObjectGroup so = (SceneObjectGroup)m_scene.Entities[objectID]; + // sell is not a attachment op + if(sog.IsAttachment) + return false; - if (!permission) - { - if (!m_scene.Entities.ContainsKey(objectID)) - { - return false; - } + if(sp.IsGod) + return true; - // If it's not an object, we cant edit it. - if (!(m_scene.Entities[objectID] is SceneObjectGroup)) - { - return false; - } + uint sogEffectiveOwnerPerms = sog.EffectiveOwnerPerms; + if((sogEffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0) + return false; - // UUID taskOwner = null; - // Added this because at this point in time it wouldn't be wise for - // the administrator object permissions to take effect. - // UUID objectOwner = task.OwnerID; + if(saleType == (byte)SaleType.Copy && + (sogEffectiveOwnerPerms & (uint)PermissionMask.Copy) == 0) + return false; - if ((so.RootPart.EveryoneMask & PERM_COPY) != 0) - permission = true; - } + UUID userID = sp.UUID; + UUID sogOwnerID = sog.OwnerID; - if (so.OwnerID != userID) - { - if ((so.GetEffectivePermissions() & (PERM_COPY | PERM_TRANS)) != (PERM_COPY | PERM_TRANS)) - permission = false; - } - else - { - if ((so.GetEffectivePermissions() & PERM_COPY) != PERM_COPY) - permission = false; - } + if(sogOwnerID == userID) + return true; - return permission; + // else only group owned can be sold by members with powers + UUID sogGroupID = sog.GroupID; + if(sog.OwnerID != sogGroupID || sogGroupID == UUID.Zero) + return false; + + ulong powers = 0; + if(!GroupMemberPowers(sogGroupID, sp, ref powers)) + return false; + + if((powers & (ulong)GroupPowers.ObjectSetForSale) == 0) + return false; + + return true; } - private bool CanTerraformLand(UUID user, Vector3 position, Scene requestFromScene) + private bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp) + { + // ignore locked, viewers shell ask for confirmation + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted) + return false; + + // take is not a attachment op + if(sog.IsAttachment) + return false; + + UUID sogOwnerID = sog.OwnerID; + UUID spID = sp.UUID; + + if(sogOwnerID == spID) + return true; + + if (sp.IsGod) + return true; + + if((sog.EffectiveOwnerPerms & (uint)PermissionMask.Transfer) == 0) + return false; + + if (IsFriendWithPerms(sog.UUID, sogOwnerID)) + return true; + + UUID sogGroupID = sog.GroupID; + if (sogGroupID != UUID.Zero) + { + ulong powers = 0; + if(GroupMemberPowers(sogGroupID, sp, ref powers)) + { + if(sogGroupID == sogOwnerID) + { + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + return true; + } + return (sog.EffectiveGroupPerms & (uint)PermissionMask.Modify) != 0; + } + } + return false; + } + + private bool CanTakeCopyObject(SceneObjectGroup sog, ScenePresence sp) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + if (m_bypassPermissions) return m_bypassPermissionsValue; + + if (sog == null || sog.IsDeleted || sp == null || sp.IsDeleted) + return false; + + // refuse on attachments + if(sog.IsAttachment && !sp.IsGod) + return false; + + uint perms = GetObjectPermissions(sp, sog, true); + if((perms & (uint)PermissionMask.Copy) == 0) + { + sp.ControllingClient.SendAgentAlertMessage("Copying this item has been denied by the permissions system", false); + return false; + } + + if(sog.OwnerID != sp.UUID && (perms & (uint)PermissionMask.Transfer) == 0) + return false; + return true; + } + + private bool CanTerraformLand(UUID userID, Vector3 position) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; // Estate override - if (GenericEstatePermission(user)) + if (GenericEstatePermission(userID)) return true; float X = position.X; @@ -1609,13 +2086,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions ILandObject parcel = m_scene.LandChannel.GetLandObject(X, Y); if (parcel == null) return false; - - // Others allowed to terraform? - if ((parcel.LandData.Flags & ((int)ParcelFlags.AllowTerraform)) != 0) + + LandData landdata = parcel.LandData; + if (landdata == null) + return false; + + if ((landdata.Flags & ((int)ParcelFlags.AllowTerraform)) != 0) return true; - // Land owner can terraform too - if (parcel != null && GenericParcelPermission(user, parcel, (ulong)GroupPowers.AllowEditLand)) + if(landdata.OwnerID == userID) + return true; + + if (landdata.IsGroupOwned && parcel.LandData.GroupID != UUID.Zero && + IsGroupMember(landdata.GroupID, userID, (ulong)GroupPowers.AllowEditLand)) return true; return false; @@ -1629,15 +2112,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions /// /// /// - private bool CanViewScript(UUID script, UUID objectID, UUID user, Scene scene) + private bool CanViewScript(UUID script, UUID objectID, UUID userID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; + // A god is a god is a god + if (IsAdministrator(userID)) + return true; + if (objectID == UUID.Zero) // User inventory { IInventoryService invService = m_scene.InventoryService; - InventoryItemBase assetRequestItem = invService.GetItem(user, script); + InventoryItemBase assetRequestItem = invService.GetItem(userID, script); if (assetRequestItem == null && LibraryRootFolder != null) // Library item { assetRequestItem = LibraryRootFolder.FindItem(script); @@ -1657,60 +2144,53 @@ namespace OpenSim.Region.CoreModules.World.Permissions // readable only if it's really full perms // if ((assetRequestItem.CurrentPermissions & +/* ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) +*/ + (uint)(PermissionMask.Modify | PermissionMask.Copy)) != + (uint)(PermissionMask.Modify | PermissionMask.Copy)) return false; } else // Prim inventory { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); if (part == null) return false; - if (part.OwnerID != user) - { - if (part.GroupID == UUID.Zero) - return false; + SceneObjectGroup sog = part.ParentGroup; + if (sog == null) + return false; - if (!IsGroupMember(part.GroupID, user, 0)) - return false; - - if ((part.GroupMask & (uint)PermissionMask.Modify) == 0) - return false; - } - else - { - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return false; - } + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; TaskInventoryItem ti = part.Inventory.GetInventoryItem(script); - if (ti == null) +// if (ti == null || ti.InvType != (int)InventoryType.LSL) + if (ti == null) // legacy may not have type return false; - if (ti.OwnerID != user) - { - if (ti.GroupID == UUID.Zero) - return false; - - if (!IsGroupMember(ti.GroupID, user, 0)) - return false; - } + uint itperms = GetObjectItemPermissions(userID, ti); // Require full perms - if ((ti.CurrentPermissions & - ((uint)PermissionMask.Modify | + + if ((itperms & +/* + ((uint)(PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) != ((uint)PermissionMask.Modify | (uint)PermissionMask.Copy | (uint)PermissionMask.Transfer)) +*/ + (uint)(PermissionMask.Modify | PermissionMask.Copy)) != + (uint)(PermissionMask.Modify | PermissionMask.Copy)) return false; } @@ -1725,15 +2205,19 @@ namespace OpenSim.Region.CoreModules.World.Permissions /// /// /// - private bool CanViewNotecard(UUID notecard, UUID objectID, UUID user, Scene scene) + private bool CanViewNotecard(UUID notecard, UUID objectID, UUID userID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; + // A god is a god is a god + if (IsAdministrator(userID)) + return true; + if (objectID == UUID.Zero) // User inventory { IInventoryService invService = m_scene.InventoryService; - InventoryItemBase assetRequestItem = invService.GetItem(user, notecard); + InventoryItemBase assetRequestItem = invService.GetItem(userID, notecard); if (assetRequestItem == null && LibraryRootFolder != null) // Library item { assetRequestItem = LibraryRootFolder.FindItem(notecard); @@ -1751,40 +2235,29 @@ namespace OpenSim.Region.CoreModules.World.Permissions } else // Prim inventory { - SceneObjectPart part = scene.GetSceneObjectPart(objectID); - + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); if (part == null) return false; - if (part.OwnerID != user) - { - if (part.GroupID == UUID.Zero) - return false; + SceneObjectGroup sog = part.ParentGroup; + if (sog == null) + return false; - if (!IsGroupMember(part.GroupID, user, 0)) - return false; - } - - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) return false; TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); +// if (ti == null || ti.InvType != (int)InventoryType.Notecard) if (ti == null) return false; - if (ti.OwnerID != user) - { - if (ti.GroupID == UUID.Zero) - return false; - - if (!IsGroupMember(ti.GroupID, user, 0)) - return false; - } + uint itperms = GetObjectItemPermissions(userID, ti); // Notecards are always readable unless no copy // - if ((ti.CurrentPermissions & + if ((itperms & (uint)PermissionMask.Copy) != (uint)PermissionMask.Copy) return false; @@ -1800,7 +2273,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(userID, objectID, false); + SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID); + if (sog == null) + return false; + + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + return true; } private bool CanDelinkObject(UUID userID, UUID objectID) @@ -1808,10 +2288,17 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - return GenericObjectPermission(userID, objectID, false); + SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID); + if (sog == null) + return false; + + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + return true; } - private bool CanBuyLand(UUID userID, ILandObject parcel, Scene scene) + private bool CanBuyLand(UUID userID, ILandObject parcel) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; @@ -1824,6 +2311,138 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) + return false; + + SceneObjectGroup sog = part.ParentGroup; + if (sog == null) + return false; + + if(sog.OwnerID == userID || IsAdministrator(userID)) + return true; + + if(sog.IsAttachment) + return false; + + UUID sogGroupID = sog.GroupID; + + if(sogGroupID == UUID.Zero || sogGroupID != sog.OwnerID) + return false; + + TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); + if(ti == null) + return false; + + ulong powers = 0; + if(GroupMemberPowers(sogGroupID, userID, ref powers)) + { + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + return true; + + if((ti.EveryonePermissions & (uint)PermissionMask.Copy) != 0) + return true; + } + return false; + } + + // object inventory to object inventory item drag and drop + private bool CanDoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + + if (sourcePart == null || destPart == null || item == null) + return false; + + if (m_bypassPermissions) + return m_bypassPermissionsValue; + + SceneObjectGroup srcsog = sourcePart.ParentGroup; + SceneObjectGroup destsog = destPart.ParentGroup; + if (srcsog == null || destsog == null) + return false; + + // dest is locked + if((destsog.EffectiveOwnerPerms & (uint)PermissionMask.Move) == 0) + return false; + + uint itperms = item.CurrentPermissions; + + // if item is no copy the source is modifed + if((itperms & (uint)PermissionMask.Copy) == 0 && (srcsog.EffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0) + return false; + + UUID srcOwner = srcsog.OwnerID; + UUID destOwner = destsog.OwnerID; + bool notSameOwner = srcOwner != destOwner; + + if(notSameOwner) + { + if((itperms & (uint)PermissionMask.Transfer) == 0) + return false; + + // scripts can't be droped + if(item.InvType == (int)InventoryType.LSL) + return false; + + if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) + return false; + } + else + { + if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0 && + (destsog.EffectiveOwnerPerms & (uint)PermissionMask.Modify) == 0) + return false; + } + + return true; + } + + private bool CanDropInObjectInv(InventoryItemBase item, ScenePresence sp, SceneObjectPart destPart) + { + DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); + + if (sp == null || sp.IsDeleted || destPart == null || item == null) + return false; + + SceneObjectGroup destsog = destPart.ParentGroup; + if (destsog == null || destsog.IsDeleted) + return false; + + if (m_bypassPermissions) + return m_bypassPermissionsValue; + + if(sp.IsGod) + return true; + + // dest is locked + if((destsog.EffectiveOwnerPerms & (uint)PermissionMask.Move) == 0) + return false; + + UUID destOwner = destsog.OwnerID; + UUID spID = sp.UUID; + bool spNotOwner = spID != destOwner; + + // scripts can't be droped + if(spNotOwner && item.InvType == (int)InventoryType.LSL) + return false; + + if(spNotOwner || item.Owner != destOwner) + { + // no copy item will be moved if it has transfer + uint itperms = item.CurrentPermissions; + if((itperms & (uint)PermissionMask.Transfer) == 0) + return false; + } + + // allowdrop is a root part thing and does bypass modify rights + if((destsog.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0) + return true; + + uint perms = GetObjectPermissions(spID, destsog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + return true; } @@ -1832,6 +2451,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; + SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); + if (part == null) + return false; + + SceneObjectGroup sog = part.ParentGroup; + if (sog == null) + return false; + + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + + TaskInventoryItem ti = part.Inventory.GetInventoryItem(itemID); + if(ti == null) + return false; + + //TODO item perm ? return true; } @@ -1848,26 +2484,23 @@ namespace OpenSim.Region.CoreModules.World.Permissions DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); ScenePresence p = m_scene.GetScenePresence(userID); - if (part == null || p == null) + if (p == null) return false; - if (!IsAdministrator(userID)) + SceneObjectGroup sog = m_scene.GetGroupByPrim(objectID); + if (sog == null) + return false; + + uint perms = GetObjectPermissions(userID, sog, true); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + + if ((int)InventoryType.LSL == invType) { - if (part.OwnerID != userID) - { - // Group permissions - if ((part.GroupID == UUID.Zero) || (p.ControllingClient.GetGroupPowers(part.GroupID) == 0) || ((part.GroupMask & (uint)PermissionMask.Modify) == 0)) - return false; - } else { - if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) - return false; - } - if ((int)InventoryType.LSL == invType) - if (m_allowedScriptCreators == UserSet.Administrators) - return false; + if (m_allowedScriptCreators == UserSet.Administrators) + return false; } return true; @@ -1941,22 +2574,22 @@ namespace OpenSim.Region.CoreModules.World.Permissions return true; } - private bool CanResetScript(UUID prim, UUID script, UUID agentID, Scene scene) + private bool CanResetScript(UUID primID, UUID script, UUID agentID) { DebugPermissionInformation(MethodInfo.GetCurrentMethod().Name); if (m_bypassPermissions) return m_bypassPermissionsValue; - SceneObjectPart part = m_scene.GetSceneObjectPart(prim); + SceneObjectGroup sog = m_scene.GetGroupByPrim(primID); + if (sog == null) + return false; - // If we selected a sub-prim to reset, prim won't represent the object, but only a part. - // We have to check the permissions of the object, though. - if (part.ParentID != 0) prim = part.ParentUUID; - - // You can reset the scripts in any object you can edit - return GenericObjectPermission(agentID, prim, false); + uint perms = GetObjectPermissions(agentID, sog, false); + if((perms & (uint)PermissionMask.Modify) == 0) // ?? + return false; + return true; } - private bool CanCompileScript(UUID ownerUUID, int scriptType, Scene scene) + private bool CanCompileScript(UUID ownerUUID, int scriptType) { //m_log.DebugFormat("check if {0} is allowed to compile {1}", ownerUUID, scriptType); switch (scriptType) { @@ -2014,7 +2647,14 @@ namespace OpenSim.Region.CoreModules.World.Permissions // "[PERMISSIONS]: Checking CanControlPrimMedia for {0} on {1} face {2} with control permissions {3}", // agentID, primID, face, me.ControlPermissions); - return GenericObjectPermission(agentID, part.ParentGroup.UUID, true); + SceneObjectGroup sog = part.ParentGroup; + if (sog == null) + return false; + + uint perms = GetObjectPermissions(agentID, sog, false); + if((perms & (uint)PermissionMask.Modify) == 0) + return false; + return true; } private bool CanInteractWithPrimMedia(UUID agentID, UUID primID, int face) diff --git a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs index 8bac9e6623..bb3b8605b5 100644 --- a/OpenSim/Region/CoreModules/World/Region/RestartModule.cs +++ b/OpenSim/Region/CoreModules/World/Region/RestartModule.cs @@ -61,6 +61,8 @@ namespace OpenSim.Region.CoreModules.World.Region protected IDialogModule m_DialogModule = null; protected string m_MarkerPath = String.Empty; private int[] m_CurrentAlerts = null; + protected bool m_shortCircuitDelays = false; + protected bool m_rebootAll = false; public void Initialise(IConfigSource config) { @@ -69,6 +71,9 @@ namespace OpenSim.Region.CoreModules.World.Region { m_MarkerPath = restartConfig.GetString("MarkerPath", String.Empty); } + IConfig startupConfig = config.Configs["Startup"]; + m_shortCircuitDelays = startupConfig.GetBoolean("SkipDelayOnEmptyRegion", false); + m_rebootAll = startupConfig.GetBoolean("InworldRestartShutsDown", false); } public void AddRegion(Scene scene) @@ -250,6 +255,14 @@ namespace OpenSim.Region.CoreModules.World.Region private void OnTimer(object source, ElapsedEventArgs e) { int nextInterval = DoOneNotice(true); + if (m_shortCircuitDelays) + { + if (CountAgents() == 0) + { + m_Scene.RestartNow(); + return; + } + } SetTimer(nextInterval); } @@ -349,5 +362,35 @@ namespace OpenSim.Region.CoreModules.World.Region { } } + + int CountAgents() + { + m_log.Info("[RESTART MODULE]: Counting affected avatars"); + int agents = 0; + + if (m_rebootAll) + { + foreach (Scene s in SceneManager.Instance.Scenes) + { + foreach (ScenePresence sp in s.GetScenePresences()) + { + if (!sp.IsChildAgent && !sp.IsNPC) + agents++; + } + } + } + else + { + foreach (ScenePresence sp in m_Scene.GetScenePresences()) + { + if (!sp.IsChildAgent && !sp.IsNPC) + agents++; + } + } + + m_log.InfoFormat("[RESTART MODULE]: Avatars in region: {0}", agents); + + return agents; + } } } diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs index 04b6f00a39..4cee7a5f3b 100644 --- a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs +++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs @@ -105,8 +105,9 @@ namespace OpenSim.Region.CoreModules.World.Vegetation if (rootPart.Shape.PCode != (byte)PCode.Grass) AdaptTree(ref shape); - m_scene.AddNewSceneObject(sceneObject, true); sceneObject.SetGroup(groupID, null); + m_scene.AddNewSceneObject(sceneObject, true); + sceneObject.InvalidateDeepEffectivePerms(); return sceneObject; } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index 5dcf3266a9..03a4d3475e 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -215,6 +215,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap m_scene.EventManager.OnNewClient -= OnNewClient; m_scene.EventManager.OnRegisterCaps -= OnRegisterCaps; + m_scene.UnregisterModuleInterface(this); + string regionimage = "regionImage" + m_scene.RegionInfo.RegionID.ToString(); regionimage = regionimage.Replace("-", ""); MainServer.Instance.RemoveLLSDHandler("/MAP/MapItems/" + m_scene.RegionInfo.RegionHandle.ToString(), @@ -714,12 +716,11 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { while (true) { - Watchdog.UpdateThread(); - av = null; st = null; - st = requests.Dequeue(4900); // timeout to make watchdog happy + st = requests.Dequeue(4500); + Watchdog.UpdateThread(); if (st == null || st.agentID == UUID.Zero) continue; @@ -1148,7 +1149,13 @@ namespace OpenSim.Region.CoreModules.World.WorldMap List thisRunData = new List(); while (true) { - m_mapBlockRequestEvent.WaitOne(); + while(!m_mapBlockRequestEvent.WaitOne(4900)) + { + Watchdog.UpdateThread(); + if(m_scene == null) + return; + } + Watchdog.UpdateThread(); lock (m_mapBlockRequestEvent) { int total = 0; diff --git a/OpenSim/Region/Framework/Interfaces/IDwellModule.cs b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs index db504393a2..ebef5a4749 100644 --- a/OpenSim/Region/Framework/Interfaces/IDwellModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IDwellModule.cs @@ -33,5 +33,6 @@ namespace OpenSim.Region.Framework.Interfaces public interface IDwellModule { int GetDwell(UUID parcelID); + int GetDwell(LandData land); } } diff --git a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs index 441076dd23..093ea9c801 100644 --- a/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs +++ b/OpenSim/Region/Framework/Interfaces/IDynamicTextureManager.cs @@ -44,14 +44,13 @@ namespace OpenSim.Region.Framework.Interfaces /// void ReturnData(UUID id, IDynamicTexture texture); + UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams); UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, - int updateTimer); + bool SetBlending, byte AlphaValue); UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, - int updateTimer, bool SetBlending, byte AlphaValue); - UUID AddDynamicTextureURL(UUID simID, UUID primID, string contentType, string url, string extraParams, - int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face); - UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, - int updateTimer); + bool SetBlending, int disp, byte AlphaValue, int face); + + UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams); /// Apply a dynamically generated texture to all sides of the given prim. The texture is not persisted to the /// asset service. @@ -62,8 +61,6 @@ namespace OpenSim.Region.Framework.Interfaces /// based texture or "image" to create a texture from an image at a particular URL /// The data for the generator /// Parameters for the generator that don't form part of the main data. - /// If zero, the image is never updated after the first generation. If positive - /// the image is updated at the given interval. Not implemented for /// /// If true, the newly generated texture is blended with the appropriate existing ones on the prim /// @@ -76,7 +73,7 @@ namespace OpenSim.Region.Framework.Interfaces /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID /// UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, - int updateTimer, bool SetBlending, byte AlphaValue); + bool SetBlending, byte AlphaValue); /// /// Apply a dynamically generated texture to the given prim. @@ -87,8 +84,6 @@ namespace OpenSim.Region.Framework.Interfaces /// based texture or "image" to create a texture from an image at a particular URL /// The data for the generator /// Parameters for the generator that don't form part of the main data. - /// If zero, the image is never updated after the first generation. If positive - /// the image is updated at the given interval. Not implemented for /// /// If true, the newly generated texture is blended with the appropriate existing ones on the prim /// @@ -109,9 +104,8 @@ namespace OpenSim.Region.Framework.Interfaces /// to obtain it directly from the SceneObjectPart. For instance, if ALL_SIDES is set then this texture /// can be obtained as SceneObjectPart.Shape.Textures.DefaultTexture.TextureID /// - UUID AddDynamicTextureData( - UUID simID, UUID primID, string contentType, string data, string extraParams, - int updateTimer, bool SetBlending, int disp, byte AlphaValue, int face); + UUID AddDynamicTextureData(UUID simID, UUID primID, string contentType, string data, string extraParams, + bool SetBlending, int disp, byte AlphaValue, int face); void GetDrawStringSize(string contentType, string text, string fontName, int fontSize, out double xSize, out double ySize); diff --git a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs index 0c4017eb88..e7c2428708 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityInventory.cs @@ -278,6 +278,8 @@ namespace OpenSim.Region.Framework.Interfaces /// void ProcessInventoryBackup(ISimulationDataService datastore); + void AggregateInnerPerms(ref uint owner, ref uint group, ref uint everyone); + uint MaskEffectivePermissions(); void ApplyNextOwnerPermissions(); diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 9585082719..1b690bad3f 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -102,6 +102,8 @@ namespace OpenSim.Region.Framework.Interfaces ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, EntityTransferContext ctx); + bool CrossAgentCreateFarChild(ScenePresence agent, GridRegion neighbourRegion, Vector3 pos, EntityTransferContext ctx); + bool HandleIncomingSceneObject(SceneObjectGroup so, Vector3 newPosition); } diff --git a/OpenSim/Region/Framework/Interfaces/IEtcdModule.cs b/OpenSim/Region/Framework/Interfaces/IEtcdModule.cs new file mode 100644 index 0000000000..123cb67308 --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IEtcdModule.cs @@ -0,0 +1,37 @@ +/* + * 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; + +public interface IEtcdModule +{ + bool Store(string k, string v); + bool Store(string k, string v, int ttl); + string Get(string k); + void Watch(string k, Action callback); + void Delete(string k); +} diff --git a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs index 7af56cb809..7edd75aaba 100644 --- a/OpenSim/Region/Framework/Interfaces/IEventQueue.cs +++ b/OpenSim/Region/Framework/Interfaces/IEventQueue.cs @@ -39,7 +39,7 @@ namespace OpenSim.Region.Framework.Interfaces bool Enqueue(OSD o, UUID avatarID); // These are required to decouple Scenes from EventQueueHelper - void DisableSimulator(ulong handle, UUID avatarID); +// void DisableSimulator(ulong handle, UUID avatarID); void EnableSimulator(ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY); void EstablishAgentCommunication(UUID avatarID, IPEndPoint endPoint, string capsPath, ulong regionHandle, int regionSizeX, int regionSizeY); diff --git a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs index 6b31555fb6..5c33f1272e 100644 --- a/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs +++ b/OpenSim/Region/Framework/Scenes/Animation/ScenePresenceAnimator.cs @@ -618,13 +618,147 @@ namespace OpenSim.Region.Framework.Scenes.Animation int rnditerations = 3; BinBVHAnimation anim = new BinBVHAnimation(); List parts = new List(); - parts.Add("mPelvis"); parts.Add("mHead"); parts.Add("mTorso"); - parts.Add("mHipLeft"); parts.Add("mHipRight"); parts.Add("mHipLeft"); parts.Add("mKneeLeft"); - parts.Add("mKneeRight"); parts.Add("mCollarLeft"); parts.Add("mCollarRight"); parts.Add("mNeck"); - parts.Add("mElbowLeft"); parts.Add("mElbowRight"); parts.Add("mWristLeft"); parts.Add("mWristRight"); - parts.Add("mShoulderLeft"); parts.Add("mShoulderRight"); parts.Add("mAnkleLeft"); parts.Add("mAnkleRight"); - parts.Add("mEyeRight"); parts.Add("mChest"); parts.Add("mToeLeft"); parts.Add("mToeRight"); - parts.Add("mFootLeft"); parts.Add("mFootRight"); parts.Add("mEyeLeft"); + + /// Torso and Head + parts.Add("mPelvis"); + parts.Add("mTorso"); + parts.Add("mChest"); + parts.Add("mNeck"); + parts.Add("mHead"); + parts.Add("mSkull"); + parts.Add("mEyeRight"); + parts.Add("mEyeLeft"); + /// Arms + parts.Add("mCollarLeft"); + parts.Add("mShoulderLeft"); + parts.Add("mElbowLeft"); + parts.Add("mWristLeft"); + parts.Add("mCollarRight"); + parts.Add("mShoulderRight"); + parts.Add("mElbowRight"); + parts.Add("mWristRight"); + /// Legs + parts.Add("mHipLeft"); + parts.Add("mKneeLeft"); + parts.Add("mAnkleLeft"); + parts.Add("mFootLeft"); + parts.Add("mToeLeft"); + parts.Add("mHipRight"); + parts.Add("mKneeRight"); + parts.Add("mAnkleRight"); + parts.Add("mFootRight"); + parts.Add("mToeRight"); + ///Hands + parts.Add("mHandThumb1Left"); + parts.Add("mHandThumb1Right"); + parts.Add("mHandThumb2Left"); + parts.Add("mHandThumb2Right"); + parts.Add("mHandThumb3Left"); + parts.Add("mHandThumb3Right"); + parts.Add("mHandIndex1Left"); + parts.Add("mHandIndex1Right"); + parts.Add("mHandIndex2Left"); + parts.Add("mHandIndex2Right"); + parts.Add("mHandIndex3Left"); + parts.Add("mHandIndex3Right"); + parts.Add("mHandMiddle1Left"); + parts.Add("mHandMiddle1Right"); + parts.Add("mHandMiddle2Left"); + parts.Add("mHandMiddle2Right"); + parts.Add("mHandMiddle3Left"); + parts.Add("mHandMiddle3Right"); + parts.Add("mHandRing1Left"); + parts.Add("mHandRing1Right"); + parts.Add("mHandRing2Left"); + parts.Add("mHandRing2Right"); + parts.Add("mHandRing3Left"); + parts.Add("mHandRing3Right"); + parts.Add("mHandPinky1Left"); + parts.Add("mHandPinky1Right"); + parts.Add("mHandPinky2Left"); + parts.Add("mHandPinky2Right"); + parts.Add("mHandPinky3Left"); + parts.Add("mHandPinky3Right"); + ///Face + parts.Add("mFaceForeheadLeft"); + parts.Add("mFaceForeheadCenter"); + parts.Add("mFaceForeheadRight"); + parts.Add("mFaceEyebrowOuterLeft"); + parts.Add("mFaceEyebrowCenterLeft"); + parts.Add("mFaceEyebrowInnerLeft"); + parts.Add("mFaceEyebrowOuterRight"); + parts.Add("mFaceEyebrowCenterRight"); + parts.Add("mFaceEyebrowInnerRight"); + parts.Add("mFaceEyeLidUpperLeft"); + parts.Add("mFaceEyeLidLowerLeft"); + parts.Add("mFaceEyeLidUpperRight"); + parts.Add("mFaceEyeLidLowerRight"); + parts.Add("mFaceEyeAltLeft"); + parts.Add("mFaceEyeAltRight"); + parts.Add("mFaceEyecornerInnerLeft"); + parts.Add("mFaceEyecornerInnerRight"); + parts.Add("mFaceEar1Left"); + parts.Add("mFaceEar2Left"); + parts.Add("mFaceEar1Right"); + parts.Add("mFaceEar2Right"); + parts.Add("mFaceNoseLeft"); + parts.Add("mFaceNoseCenter"); + parts.Add("mFaceNoseRight"); + parts.Add("mFaceNoseBase"); + parts.Add("mFaceNoseBridge"); + parts.Add("mFaceCheekUpperInnerLeft"); + parts.Add("mFaceCheekUpperOuterLeft"); + parts.Add("mFaceCheekUpperInnerRight"); + parts.Add("mFaceCheekUpperOuterRight"); + parts.Add("mFaceJaw"); + parts.Add("mFaceLipUpperLeft"); + parts.Add("mFaceLipUpperCenter"); + parts.Add("mFaceLipUpperRight"); + parts.Add("mFaceLipCornerLeft"); + parts.Add("mFaceLipCornerRight"); + parts.Add("mFaceTongueBase"); + parts.Add("mFaceTongueTip"); + parts.Add("mFaceLipLowerLeft"); + parts.Add("mFaceLipLowerCenter"); + parts.Add("mFaceLipLowerRight"); + parts.Add("mFaceTeethLower"); + parts.Add("mFaceTeethUpper"); + parts.Add("mFaceChin"); + ///Spine + parts.Add("mSpine1"); + parts.Add("mSpine2"); + parts.Add("mSpine3"); + parts.Add("mSpine4"); + ///Wings + parts.Add("mWingsRoot"); + parts.Add("mWing1Left"); + parts.Add("mWing2Left"); + parts.Add("mWing3Left"); + parts.Add("mWing4Left"); + parts.Add("mWing1Right"); + parts.Add("mWing2Right"); + parts.Add("mWing3Right"); + parts.Add("mWing4Right"); + parts.Add("mWing4FanRight"); + parts.Add("mWing4FanLeft"); + ///Hind Limbs + parts.Add("mHindLimbsRoot"); + parts.Add("mHindLimb1Left"); + parts.Add("mHindLimb2Left"); + parts.Add("mHindLimb3Left"); + parts.Add("mHindLimb4Left"); + parts.Add("mHindLimb1Right"); + parts.Add("mHindLimb2Right"); + parts.Add("mHindLimb3Right"); + parts.Add("mHindLimb4Right"); + ///Tail + parts.Add("mTail1"); + parts.Add("mTail2"); + parts.Add("mTail3"); + parts.Add("mTail4"); + parts.Add("mTail5"); + parts.Add("mTail6"); + anim.HandPose = 1; anim.InPoint = 0; anim.OutPoint = (rnditerations * .10f); diff --git a/OpenSim/Region/Framework/Scenes/CollisionSounds.cs b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs index e76fef4a79..63aafcd066 100644 --- a/OpenSim/Region/Framework/Scenes/CollisionSounds.cs +++ b/OpenSim/Region/Framework/Scenes/CollisionSounds.cs @@ -116,16 +116,20 @@ namespace OpenSim.Region.Framework.Scenes public static void PartCollisionSound(SceneObjectPart part, List collidersinfolist) { + if (part.CollisionSoundType < 0) + return; + if (collidersinfolist.Count == 0 || part == null) return; if (part.VolumeDetectActive || (part.Flags & PrimFlags.Physics) == 0) return; - if (part.ParentGroup == null) + SceneObjectGroup sog = part.ParentGroup; + if (sog == null || sog.IsDeleted || sog.inTransit) return; - if (part.CollisionSoundType < 0) + if(sog.CollisionSoundThrottled(part.CollisionSoundType)) return; float volume = part.CollisionSoundVolume; @@ -189,15 +193,23 @@ namespace OpenSim.Region.Framework.Scenes continue; } - SceneObjectPart otherPart = part.ParentGroup.Scene.GetSceneObjectPart(id); + SceneObjectPart otherPart = sog.Scene.GetSceneObjectPart(id); if (otherPart != null) { - if (otherPart.CollisionSoundType < 0 || otherPart.VolumeDetectActive) + SceneObjectGroup othersog = otherPart.ParentGroup; + if(othersog == null || othersog.IsDeleted || othersog.inTransit) + continue; + + int otherType = otherPart.CollisionSoundType; + if (otherType < 0 || otherPart.VolumeDetectActive) continue; if (!HaveSound) { - if (otherPart.CollisionSoundType == 1) + if(othersog.CollisionSoundThrottled(otherType)) + continue; + + if (otherType == 1) { soundID = otherPart.CollisionSound; volume = otherPart.CollisionSoundVolume; @@ -206,7 +218,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (otherPart.CollisionSoundType == 2) + if (otherType == 2) { volume = otherPart.CollisionSoundVolume; if (volume == 0.0f) diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 1e9711d0b4..f76f8828d0 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -855,7 +855,7 @@ namespace OpenSim.Region.Framework.Scenes /// , /// , /// , - /// , + /// , /// /// public event ParcelPrimCountTainted OnParcelPrimCountTainted; @@ -3161,7 +3161,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (Action d in handler.GetInvocationList()) { - m_log.InfoFormat("[EVENT MANAGER]: TriggerSceneShuttingDown invoque {0}", d.Method.Name.ToString()); + m_log.InfoFormat("[EVENT MANAGER]: TriggerSceneShuttingDown invoke {0}", d.Method.Name.ToString()); try { d(s); diff --git a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs index e4aa196497..80ee5101aa 100644 --- a/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs +++ b/OpenSim/Region/Framework/Scenes/KeyframeMotion.cs @@ -295,6 +295,7 @@ namespace OpenSim.Region.Framework.Scenes lock (m_frames) { KeyframeTimer.Add(this); + m_lasttickMS = Util.GetTimeStampMS(); m_timerStopped = false; } } @@ -326,8 +327,8 @@ namespace OpenSim.Region.Framework.Scenes newMotion.m_selected = true; } - newMotion.m_timerStopped = false; - newMotion.m_running = true; +// newMotion.m_timerStopped = false; +// newMotion.m_running = true; newMotion.m_isCrossing = false; newMotion.m_waitingCrossing = false; } @@ -483,9 +484,10 @@ namespace OpenSim.Region.Framework.Scenes m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); -// m_group.RootPart.ScheduleTerseUpdate(); +// m_group.SendGroupRootTerseUpdate(); + m_group.RootPart.ScheduleTerseUpdate(); m_frames.Clear(); + m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId); } public void Pause() @@ -495,8 +497,10 @@ namespace OpenSim.Region.Framework.Scenes m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); -// m_group.RootPart.ScheduleTerseUpdate(); + m_skippedUpdates = 1000; +// m_group.SendGroupRootTerseUpdate(); + m_group.RootPart.ScheduleTerseUpdate(); + m_group.Scene.EventManager.TriggerMovingEndEvent(m_group.RootPart.LocalId); } public void Suspend() @@ -517,6 +521,7 @@ namespace OpenSim.Region.Framework.Scenes return; if (m_running && !m_waitingCrossing) StartTimer(); + m_skippedUpdates = 1000; } } @@ -642,11 +647,17 @@ namespace OpenSim.Region.Framework.Scenes m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); - // m_group.RootPart.ScheduleTerseUpdate(); +// m_group.SendGroupRootTerseUpdate(); + m_group.RootPart.ScheduleTerseUpdate(); m_frames.Clear(); } + [NonSerialized()] Vector3 m_lastPosUpdate; + [NonSerialized()] Quaternion m_lastRotationUpdate; + [NonSerialized()] Vector3 m_currentVel; + [NonSerialized()] int m_skippedUpdates; + [NonSerialized()] double m_lasttickMS; + private void DoOnTimer(double tickDuration) { if (m_skipLoops > 0) @@ -665,7 +676,9 @@ namespace OpenSim.Region.Framework.Scenes if (m_group.RootPart.Velocity != Vector3.Zero) { m_group.RootPart.Velocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); + m_skippedUpdates = 1000; +// m_group.SendGroupRootTerseUpdate(); + m_group.RootPart.ScheduleTerseUpdate(); } return; } @@ -677,7 +690,9 @@ namespace OpenSim.Region.Framework.Scenes // retry to set the position that evtually caused the outbound // if still outside region this will call startCrossing below m_isCrossing = false; + m_skippedUpdates = 1000; m_group.AbsolutePosition = m_nextPosition; + if (!m_isCrossing) { StopTimer(); @@ -686,6 +701,8 @@ namespace OpenSim.Region.Framework.Scenes return; } + double nowMS = Util.GetTimeStampMS(); + if (m_frames.Count == 0) { lock (m_frames) @@ -700,19 +717,27 @@ namespace OpenSim.Region.Framework.Scenes } m_currentFrame = m_frames[0]; - m_currentFrame.TimeMS += (int)tickDuration; } - //force a update on a keyframe transition m_nextPosition = m_group.AbsolutePosition; + m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition; + m_currentVel /= (m_currentFrame.TimeMS * 0.001f); + + m_currentFrame.TimeMS += (int)tickDuration; + m_lasttickMS = nowMS - 50f; update = true; } - m_currentFrame.TimeMS -= (int)tickDuration; + int elapsed = (int)(nowMS - m_lasttickMS); + if( elapsed > 3 * tickDuration) + elapsed = (int)tickDuration; + + m_currentFrame.TimeMS -= elapsed; + m_lasttickMS = nowMS; // Do the frame processing double remainingSteps = (double)m_currentFrame.TimeMS / tickDuration; - if (remainingSteps <= 0.0) + if (remainingSteps <= 1.0) { m_group.RootPart.Velocity = Vector3.Zero; m_group.RootPart.AngularVelocity = Vector3.Zero; @@ -720,94 +745,77 @@ namespace OpenSim.Region.Framework.Scenes m_nextPosition = (Vector3)m_currentFrame.Position; m_group.AbsolutePosition = m_nextPosition; - // we are sending imediate updates, no doing force a extra terseUpdate - // m_group.UpdateGroupRotationR((Quaternion)m_currentFrame.Rotation); - m_group.RootPart.RotationOffset = (Quaternion)m_currentFrame.Rotation; lock (m_frames) { m_frames.RemoveAt(0); if (m_frames.Count > 0) + { m_currentFrame = m_frames[0]; + m_currentVel = (Vector3)m_currentFrame.Position - m_nextPosition; + m_currentVel /= (m_currentFrame.TimeMS * 0.001f); + m_group.RootPart.Velocity = m_currentVel; + m_currentFrame.TimeMS += (int)tickDuration; + } + else + m_group.RootPart.Velocity = Vector3.Zero; } - update = true; } else { - float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; - bool lastStep = m_currentFrame.TimeMS <= tickDuration; +// bool lastSteps = remainingSteps < 4; + + Vector3 currentPosition = m_group.AbsolutePosition; + Vector3 motionThisFrame = (Vector3)m_currentFrame.Position - currentPosition; + motionThisFrame /= (float)remainingSteps; + + m_nextPosition = currentPosition + motionThisFrame; - Vector3 v = (Vector3)m_currentFrame.Position - m_group.AbsolutePosition; - Vector3 motionThisFrame = v / (float)remainingSteps; - v = v * 1000 / m_currentFrame.TimeMS; - - m_nextPosition = m_group.AbsolutePosition + motionThisFrame; - - if (Vector3.Mag(motionThisFrame) >= 0.05f) - update = true; - - //int totalSteps = m_currentFrame.TimeTotal / (int)tickDuration; - //m_log.DebugFormat("KeyframeMotion.OnTimer: step {0}/{1}, curPosition={2}, finalPosition={3}, motionThisStep={4} (scene {5})", - // totalSteps - remainingSteps + 1, totalSteps, m_group.AbsolutePosition, m_currentFrame.Position, motionThisStep, m_scene.RegionInfo.RegionName); - - if ((Quaternion)m_currentFrame.Rotation != m_group.GroupRotation) + Quaternion currentRotation = m_group.GroupRotation; + if ((Quaternion)m_currentFrame.Rotation != currentRotation) { - Quaternion current = m_group.GroupRotation; - + float completed = ((float)m_currentFrame.TimeTotal - (float)m_currentFrame.TimeMS) / (float)m_currentFrame.TimeTotal; Quaternion step = Quaternion.Slerp(m_currentFrame.StartRotation, (Quaternion)m_currentFrame.Rotation, completed); step.Normalize(); - /* use simpler change detection - * float angle = 0; - - float aa = current.X * current.X + current.Y * current.Y + current.Z * current.Z + current.W * current.W; - float bb = step.X * step.X + step.Y * step.Y + step.Z * step.Z + step.W * step.W; - float aa_bb = aa * bb; - - if (aa_bb == 0) - { - angle = 0; - } - else - { - float ab = current.X * step.X + - current.Y * step.Y + - current.Z * step.Z + - current.W * step.W; - float q = (ab * ab) / aa_bb; - - if (q > 1.0f) - { - angle = 0; - } - else - { - angle = (float)Math.Acos(2 * q - 1); - } - } - - if (angle > 0.01f) - */ - if (Math.Abs(step.X - current.X) > 0.001f - || Math.Abs(step.Y - current.Y) > 0.001f - || Math.Abs(step.Z - current.Z) > 0.001f) - // assuming w is a dependente var - { -// m_group.UpdateGroupRotationR(step); - m_group.RootPart.RotationOffset = step; - - //m_group.RootPart.UpdateAngularVelocity(m_currentFrame.AngularVelocity / 2); + m_group.RootPart.RotationOffset = step; +/* + if (Math.Abs(step.X - m_lastRotationUpdate.X) > 0.001f + || Math.Abs(step.Y - m_lastRotationUpdate.Y) > 0.001f + || Math.Abs(step.Z - m_lastRotationUpdate.Z) > 0.001f) update = true; - } +*/ } - } - if (update) - { m_group.AbsolutePosition = m_nextPosition; - m_group.SendGroupRootTerseUpdate(); +// if(lastSteps) +// m_group.RootPart.Velocity = Vector3.Zero; +// else + m_group.RootPart.Velocity = m_currentVel; +/* + if(!update && ( +// lastSteps || + m_skippedUpdates * tickDuration > 0.5 || + Math.Abs(m_nextPosition.X - currentPosition.X) > 5f || + Math.Abs(m_nextPosition.Y - currentPosition.Y) > 5f || + Math.Abs(m_nextPosition.Z - currentPosition.Z) > 5f + )) + { + update = true; + } + else + m_skippedUpdates++; +*/ } +// if(update) +// { +// m_lastPosUpdate = m_nextPosition; +// m_lastRotationUpdate = m_group.GroupRotation; +// m_skippedUpdates = 0; +// m_group.SendGroupRootTerseUpdate(); + m_group.RootPart.ScheduleTerseUpdate(); +// } } public Byte[] Serialize() @@ -850,8 +858,9 @@ namespace OpenSim.Region.Framework.Scenes if (m_group.RootPart.Velocity != Vector3.Zero) { m_group.RootPart.Velocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); -// m_group.RootPart.ScheduleTerseUpdate(); + m_skippedUpdates = 1000; +// m_group.SendGroupRootTerseUpdate(); + m_group.RootPart.ScheduleTerseUpdate(); } } @@ -862,8 +871,9 @@ namespace OpenSim.Region.Framework.Scenes if (m_group != null) { m_group.RootPart.Velocity = Vector3.Zero; - m_group.SendGroupRootTerseUpdate(); -// m_group.RootPart.ScheduleTerseUpdate(); + m_skippedUpdates = 1000; +// m_group.SendGroupRootTerseUpdate(); + m_group.RootPart.ScheduleTerseUpdate(); if (m_running) { diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index cbf40c80c5..53ca849fb1 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -172,14 +172,22 @@ namespace OpenSim.Region.Framework.Scenes if (entity is SceneObjectPart) { + SceneObjectGroup sog = ((SceneObjectPart)entity).ParentGroup; // Attachments are high priority, - if (((SceneObjectPart)entity).ParentGroup.IsAttachment) + if (sog.IsAttachment) return 2; + + + if(presence.ParentPart != null) + { + if(presence.ParentPart.ParentGroup == sog) + return 2; + } pqueue = ComputeDistancePriority(client, entity, false); // Non physical prims are lower priority than physical prims - PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; + PhysicsActor physActor = sog.RootPart.PhysActor; if (physActor == null || !physActor.IsPhysical) pqueue++; } @@ -302,6 +310,17 @@ namespace OpenSim.Region.Framework.Scenes else { SceneObjectGroup group = (entity as SceneObjectPart).ParentGroup; + if(presence.ParentPart != null) + { + if(presence.ParentPart.ParentGroup == group) + return pqueue; + } + if(group.IsAttachment) + { + if(group.RootPart.LocalId == presence.LocalId) + return pqueue; + } + float bradius = group.GetBoundsRadius(); Vector3 grppos = group.AbsolutePosition + group.getBoundsCenter(); distance = Vector3.Distance(presencePos, grppos); diff --git a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs index 651c52eee5..d38ef615ef 100644 --- a/OpenSim/Region/Framework/Scenes/SOPMaterial.cs +++ b/OpenSim/Region/Framework/Scenes/SOPMaterial.cs @@ -28,6 +28,7 @@ using System; using System.Collections.Generic; using OpenMetaverse; +using OpenMetaverse.StructuredData; using OpenSim.Framework; namespace OpenSim.Region.Framework.Scenes @@ -90,6 +91,87 @@ namespace OpenSim.Region.Framework.Scenes else return 0; } + } + public class FaceMaterial + { + public UUID ID; + public UUID NormalMapID = UUID.Zero; + public float NormalOffsetX = 0.0f; + public float NormalOffsetY = 0.0f; + public float NormalRepeatX = 1.0f; + public float NormalRepeatY = 1.0f; + public float NormalRotation = 0.0f; + + public UUID SpecularMapID = UUID.Zero; + public float SpecularOffsetX = 0.0f; + public float SpecularOffsetY = 0.0f; + public float SpecularRepeatX = 1.0f; + public float SpecularRepeatY = 1.0f; + public float SpecularRotation = 0.0f; + + public Color4 SpecularLightColor = new Color4(255,255,255,255); + public Byte SpecularLightExponent = 51; + public Byte EnvironmentIntensity = 0; + public Byte DiffuseAlphaMode = 1; + public Byte AlphaMaskCutoff = 0; + + public FaceMaterial() + { } + + public FaceMaterial(UUID pID, OSDMap mat) + { + ID = pID; + if(mat == null) + return; + float scale = 0.0001f; + NormalMapID = mat["NormMap"].AsUUID(); + NormalOffsetX = scale * (float)mat["NormOffsetX"].AsReal(); + NormalOffsetY = scale * (float)mat["NormOffsetY"].AsReal(); + NormalRepeatX = scale * (float)mat["NormRepeatX"].AsReal(); + NormalRepeatY = scale * (float)mat["NormRepeatY"].AsReal(); + NormalRotation = scale * (float)mat["NormRotation"].AsReal(); + + SpecularMapID = mat["SpecMap"].AsUUID(); + SpecularOffsetX = scale * (float)mat["SpecOffsetX"].AsReal(); + SpecularOffsetY = scale * (float)mat["SpecOffsetY"].AsReal(); + SpecularRepeatX = scale * (float)mat["SpecRepeatX"].AsReal(); + SpecularRepeatY = scale * (float)mat["SpecRepeatY"].AsReal(); + SpecularRotation = scale * (float)mat["SpecRotation"].AsReal(); + + SpecularLightColor = mat["SpecColor"].AsColor4(); + SpecularLightExponent = (Byte)mat["SpecExp"].AsUInteger(); + EnvironmentIntensity = (Byte)mat["EnvIntensity"].AsUInteger(); + DiffuseAlphaMode = (Byte)mat["DiffuseAlphaMode"].AsUInteger(); + AlphaMaskCutoff = (Byte)mat["AlphaMaskCutoff"].AsUInteger(); + } + + public OSDMap toOSD() + { + OSDMap mat = new OSDMap(); + float scale = 10000f; + + mat["NormMap"] = NormalMapID; + mat["NormOffsetX"] = (int) (scale * NormalOffsetX); + mat["NormOffsetY"] = (int) (scale * NormalOffsetY); + mat["NormRepeatX"] = (int) (scale * NormalRepeatX); + mat["NormRepeatY"] = (int) (scale * NormalRepeatY); + mat["NormRotation"] = (int) (scale * NormalRotation); + + mat["SpecMap"] = SpecularMapID; + mat["SpecOffsetX"] = (int) (scale * SpecularOffsetX); + mat["SpecOffsetY"] = (int) (scale * SpecularOffsetY); + mat["SpecRepeatX"] = (int) (scale * SpecularRepeatX); + mat["SpecRepeatY"] = (int) (scale * SpecularRepeatY); + mat["SpecRotation"] = (int) (scale * SpecularRotation); + + mat["SpecColor"] = SpecularLightColor; + mat["SpecExp"] = SpecularLightExponent; + mat["EnvIntensity"] = EnvironmentIntensity; + mat["DiffuseAlphaMode"] = DiffuseAlphaMode; + mat["AlphaMaskCutoff"] = AlphaMaskCutoff; + + return mat; + } } } \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs index 8d11331740..351eda35ed 100644 --- a/OpenSim/Region/Framework/Scenes/SOPVehicle.cs +++ b/OpenSim/Region/Framework/Scenes/SOPVehicle.cs @@ -425,25 +425,25 @@ namespace OpenSim.Region.Framework.Scenes private void XWfloat(string name, float f) { - writer.WriteElementString(name, f.ToString(Utils.EnUsCulture)); + writer.WriteElementString(name, f.ToString(Culture.FormatProvider)); } private void XWVector(string name, Vector3 vec) { writer.WriteStartElement(name); - writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture)); + writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider)); + writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider)); + writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider)); writer.WriteEndElement(); } private void XWQuat(string name, Quaternion quat) { writer.WriteStartElement(name); - writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture)); - writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture)); + writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider)); + writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider)); + writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider)); + writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider)); writer.WriteEndElement(); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index cb06540de5..057ca17b0d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -338,6 +338,7 @@ namespace OpenSim.Region.Framework.Scenes // Update item with new asset item.AssetID = asset.FullID; group.UpdateInventoryItem(item); + group.InvalidateEffectivePerms(); part.SendPropertiesToClient(remoteClient); @@ -647,7 +648,8 @@ namespace OpenSim.Region.Framework.Scenes // Modify uint permsMask = ~ ((uint)PermissionMask.Copy | (uint)PermissionMask.Transfer | - (uint)PermissionMask.Modify); + (uint)PermissionMask.Modify | + (uint)PermissionMask.Export); // Now, reduce the next perms to the mask bits // relevant to the operation @@ -677,13 +679,29 @@ namespace OpenSim.Region.Framework.Scenes (uint)PermissionMask.Move; uint ownerPerms = item.CurrentPermissions; + // These will be applied to the root prim at next rez. + // The legacy slam bit (bit 3) and folded permission (bits 0-2) + // are preserved due to the above mangling +// ownerPerms &= nextPerms; + + // Mask the base permissions. This is a conservative + // approach altering only the three main perms +// basePerms &= nextPerms; + + // Mask out the folded portion of the base mask. + // While the owner mask carries the actual folded + // permissions, the base mask carries the original + // base mask, before masking with the folded perms. + // We need this later for rezzing. +// basePerms &= ~(uint)PermissionMask.FoldedMask; +// basePerms |= ((basePerms >> 13) & 7) | (((basePerms & (uint)PermissionMask.Export) != 0) ? (uint)PermissionMask.FoldedExport : 0); + // If this is an object, root prim perms may be more // permissive than folded perms. Use folded perms as // a mask - if (item.InvType == (int)InventoryType.Object) + uint foldedPerms = (item.CurrentPermissions & (uint)PermissionMask.FoldedMask) << (int)PermissionMask.FoldingShift; + if (foldedPerms != 0 && item.InvType == (int)InventoryType.Object) { - // Create a safe mask for the current perms - uint foldedPerms = (item.CurrentPermissions & 7) << 13; foldedPerms |= permsMask; bool isRootMod = (item.CurrentPermissions & @@ -691,6 +709,8 @@ namespace OpenSim.Region.Framework.Scenes true : false; // Mask the owner perms to the folded perms + // Note that this is only to satisfy the viewer. + // The effect of this will be reversed on rez. ownerPerms &= foldedPerms; basePerms &= foldedPerms; @@ -705,15 +725,11 @@ namespace OpenSim.Region.Framework.Scenes } } - // These will be applied to the root prim at next rez. - // The slam bit (bit 3) and folded permission (bits 0-2) - // are preserved due to the above mangling + // move here so nextperms are mandatory ownerPerms &= nextPerms; - - // Mask the base permissions. This is a conservative - // approach altering only the three main perms basePerms &= nextPerms; - + basePerms &= ~(uint)PermissionMask.FoldedMask; + basePerms |= ((basePerms >> 13) & 7) | (((basePerms & (uint)PermissionMask.Export) != 0) ? (uint)PermissionMask.FoldedExport : 0); // Assign to the actual item. Make sure the slam bit is // set, if it wasn't set before. itemCopy.BasePermissions = basePerms; @@ -1200,6 +1216,7 @@ namespace OpenSim.Region.Framework.Scenes } group.RemoveInventoryItem(localID, itemID); + group.InvalidateEffectivePerms(); } part.SendPropertiesToClient(remoteClient); @@ -1244,22 +1261,32 @@ namespace OpenSim.Region.Framework.Scenes agentItem.InvType = taskItem.InvType; agentItem.Flags = taskItem.Flags; + // The code below isn't OK. It doesn't account for flags being changed + // in the object inventory, so it will break when you do it. That + // is the previous behaviour, so no matter at this moment. However, there is a lot + // TODO: Fix this after the inventory fixer exists and has beenr run if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions()) { - agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); + uint perms = taskItem.BasePermissions & taskItem.NextPermissions; if (taskItem.InvType == (int)InventoryType.Object) - agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); + { + PermissionsUtil.ApplyFoldedPermissions(taskItem.CurrentPermissions, ref perms ); + perms = PermissionsUtil.FixAndFoldPermissions(perms); + } else - agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; - - agentItem.CurrentPermissions = agentItem.BasePermissions; + perms &= taskItem.CurrentPermissions; + // always unlock + perms |= (uint)PermissionMask.Move; + + agentItem.BasePermissions = perms; + agentItem.CurrentPermissions = perms; + agentItem.NextPermissions = perms & taskItem.NextPermissions; + agentItem.EveryOnePermissions = perms & taskItem.EveryonePermissions; + agentItem.GroupPermissions = perms & taskItem.GroupPermissions; + agentItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; agentItem.Flags &= ~(uint)(InventoryItemFlags.ObjectOverwriteBase | InventoryItemFlags.ObjectOverwriteOwner | InventoryItemFlags.ObjectOverwriteGroup | InventoryItemFlags.ObjectOverwriteEveryone | InventoryItemFlags.ObjectOverwriteNextOwner); - agentItem.NextPermissions = taskItem.NextPermissions; - agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); - // Group permissions make no sense here - agentItem.GroupPermissions = 0; } else { @@ -1267,7 +1294,7 @@ namespace OpenSim.Region.Framework.Scenes agentItem.CurrentPermissions = taskItem.CurrentPermissions; agentItem.NextPermissions = taskItem.NextPermissions; agentItem.EveryOnePermissions = taskItem.EveryonePermissions; - agentItem.GroupPermissions = 0; + agentItem.GroupPermissions = taskItem.GroupPermissions; } message = null; @@ -1360,20 +1387,8 @@ namespace OpenSim.Region.Framework.Scenes return; } - if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - { - // If the item to be moved is no copy, we need to be able to - // edit the prim. - if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) - return; - } - else - { - // If the item is copiable, then we just need to have perms - // on it. The delete check is a pure rights check - if (!Permissions.CanDeleteObject(part.UUID, remoteClient.AgentId)) - return; - } + if (!Permissions.CanCopyObjectInventory(itemId, part.UUID, remoteClient.AgentId)) + return; string message; InventoryItemBase item = MoveTaskInventoryItem(remoteClient, folderId, part, itemId, out message); @@ -1449,29 +1464,9 @@ namespace OpenSim.Region.Framework.Scenes return; } - // Can't transfer this - // - if (part.OwnerID != destPart.OwnerID && (srcTaskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + if(!Permissions.CanDoObjectInvToObjectInv(srcTaskItem, part, destPart)) return; - bool overrideNoMod = false; - if ((part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0) - overrideNoMod = true; - - if (part.OwnerID != destPart.OwnerID && (destPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) == 0) - { - // object cannot copy items to an object owned by a different owner - // unless llAllowInventoryDrop has been called - - return; - } - - // must have both move and modify permission to put an item in an object - if (((part.OwnerMask & (uint)PermissionMask.Modify) == 0) && (!overrideNoMod)) - { - return; - } - TaskInventoryItem destTaskItem = new TaskInventoryItem(); destTaskItem.ItemID = UUID.Random(); @@ -1512,9 +1507,10 @@ namespace OpenSim.Region.Framework.Scenes destTaskItem.Type = srcTaskItem.Type; destPart.Inventory.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID); - if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + { part.Inventory.RemoveInventoryItem(itemId); + } ScenePresence avatar; @@ -1652,76 +1648,79 @@ namespace OpenSim.Region.Framework.Scenes uint primLocalID) { UUID itemID = itemInfo.ItemID; + if (itemID == UUID.Zero) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: UpdateTaskInventory called with item ID Zero on update for {1}!", + remoteClient.Name); + return; + } // Find the prim we're dealing with SceneObjectPart part = GetSceneObjectPart(primLocalID); - - if (part != null) + if(part == null) { - TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID); - bool allowInventoryDrop = (part.GetEffectiveObjectFlags() - & (uint)PrimFlags.AllowInventoryDrop) != 0; + m_log.WarnFormat( + "[PRIM INVENTORY]: " + + "Update with item {0} requested of prim {1} for {2} but this prim does not exist", + itemID, primLocalID, remoteClient.Name); + return; + } - // Explicity allow anyone to add to the inventory if the - // AllowInventoryDrop flag has been set. Don't however let - // them update an item unless they pass the external checks - // - if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId) - && (currentItem != null || !allowInventoryDrop)) + TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID); + + if (currentItem == null) + { + InventoryItemBase item = InventoryService.GetItem(remoteClient.AgentId, itemID); + + // if not found Try library + if (item == null && LibraryService != null && LibraryService.LibraryRootFolder != null) + item = LibraryService.LibraryRootFolder.FindItem(itemID); + + if(item == null) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: Could not find inventory item {0} to update for {1}!", + itemID, remoteClient.Name); + return; + } + + if (!Permissions.CanDropInObjectInv(item, remoteClient, part)) return; - if (currentItem == null) + UUID copyID = UUID.Random(); + bool modrights = Permissions.CanEditObject(part.ParentGroup, remoteClient); + part.ParentGroup.AddInventoryItem(remoteClient.AgentId, primLocalID, item, copyID, modrights); + m_log.InfoFormat( + "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", + item.Name, primLocalID, remoteClient.Name); + part.SendPropertiesToClient(remoteClient); + if (!Permissions.BypassPermissions()) { - UUID copyID = UUID.Random(); - if (itemID != UUID.Zero) + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { - InventoryItemBase item = InventoryService.GetItem(remoteClient.AgentId, itemID); - - // Try library - if (null == item && LibraryService != null && LibraryService.LibraryRootFolder != null) - { - item = LibraryService.LibraryRootFolder.FindItem(itemID); - } - - // If we've found the item in the user's inventory or in the library - if (item != null) - { - part.ParentGroup.AddInventoryItem(remoteClient.AgentId, primLocalID, item, copyID); - m_log.InfoFormat( - "[PRIM INVENTORY]: Update with item {0} requested of prim {1} for {2}", - item.Name, primLocalID, remoteClient.Name); - part.SendPropertiesToClient(remoteClient); - if (!Permissions.BypassPermissions()) - { - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - { - List uuids = new List(); - uuids.Add(itemID); - RemoveInventoryItem(remoteClient, uuids); - } - } - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: Could not find inventory item {0} to update for {1}!", - itemID, remoteClient.Name); - } + List uuids = new List(); + uuids.Add(itemID); + RemoveInventoryItem(remoteClient, uuids); } } - else // Updating existing item with new perms etc - { + } + else // Updating existing item with new perms etc + { // m_log.DebugFormat( // "[PRIM INVENTORY]: Updating item {0} in {1} for UpdateTaskInventory()", // currentItem.Name, part.Name); - // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the - // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update) - // will not pass in a transaction ID in the update message. - if (transactionID != UUID.Zero && AgentTransactionsModule != null) - { - AgentTransactionsModule.HandleTaskItemUpdateFromTransaction( - remoteClient, part, transactionID, currentItem); + if (!Permissions.CanEditObjectInventory(part.UUID, remoteClient.AgentId)) + return; + + // Only look for an uploaded updated asset if we are passed a transaction ID. This is only the + // case for updates uploded through UDP. Updates uploaded via a capability (e.g. a script update) + // will not pass in a transaction ID in the update message. + if (transactionID != UUID.Zero && AgentTransactionsModule != null) + { + AgentTransactionsModule.HandleTaskItemUpdateFromTransaction( + remoteClient, part, transactionID, currentItem); // if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) // remoteClient.SendAgentAlertMessage("Notecard saved", false); @@ -1729,49 +1728,47 @@ namespace OpenSim.Region.Framework.Scenes // remoteClient.SendAgentAlertMessage("Script saved", false); // else // remoteClient.SendAgentAlertMessage("Item saved", false); - } + } - // Base ALWAYS has move - currentItem.BasePermissions |= (uint)PermissionMask.Move; + // Base ALWAYS has move + currentItem.BasePermissions |= (uint)PermissionMask.Move; - itemInfo.Flags = currentItem.Flags; + itemInfo.Flags = currentItem.Flags; - // Check if we're allowed to mess with permissions - if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god + // Check if we're allowed to mess with permissions + if (!Permissions.IsGod(remoteClient.AgentId)) // Not a god + { + bool noChange; + if (remoteClient.AgentId != part.OwnerID) // Not owner { - if (remoteClient.AgentId != part.OwnerID) // Not owner + noChange = true; + if(itemInfo.OwnerID == UUID.Zero && itemInfo.GroupID != UUID.Zero) { - // Friends and group members can't change any perms - itemInfo.BasePermissions = currentItem.BasePermissions; - itemInfo.EveryonePermissions = currentItem.EveryonePermissions; - itemInfo.GroupPermissions = currentItem.GroupPermissions; - itemInfo.NextPermissions = currentItem.NextPermissions; - itemInfo.CurrentPermissions = currentItem.CurrentPermissions; - } - else - { - // Owner can't change base, and can change other - // only up to base - itemInfo.BasePermissions = currentItem.BasePermissions; - if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions) - itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone; - if (itemInfo.GroupPermissions != currentItem.GroupPermissions) - itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup; - if (itemInfo.CurrentPermissions != currentItem.CurrentPermissions) - itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner; - if (itemInfo.NextPermissions != currentItem.NextPermissions) - itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner; - itemInfo.EveryonePermissions &= currentItem.BasePermissions; - itemInfo.GroupPermissions &= currentItem.BasePermissions; - itemInfo.CurrentPermissions &= currentItem.BasePermissions; - itemInfo.NextPermissions &= currentItem.BasePermissions; + if(remoteClient.IsGroupMember(itemInfo.GroupID)) + { + ulong powers = remoteClient.GetGroupPowers(itemInfo.GroupID); + if((powers & (ulong)GroupPowers.ObjectManipulate) != 0) + noChange = false; + } } + } + else + noChange = false; + if(noChange) + { + // Friends and group members can't change any perms + itemInfo.BasePermissions = currentItem.BasePermissions; + itemInfo.EveryonePermissions = currentItem.EveryonePermissions; + itemInfo.GroupPermissions = currentItem.GroupPermissions; + itemInfo.NextPermissions = currentItem.NextPermissions; + itemInfo.CurrentPermissions = currentItem.CurrentPermissions; } else { - if (itemInfo.BasePermissions != currentItem.BasePermissions) - itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteBase; + // Owner can't change base, and can change other + // only up to base + itemInfo.BasePermissions = currentItem.BasePermissions; if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions) itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone; if (itemInfo.GroupPermissions != currentItem.GroupPermissions) @@ -1780,23 +1777,33 @@ namespace OpenSim.Region.Framework.Scenes itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner; if (itemInfo.NextPermissions != currentItem.NextPermissions) itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner; - } - - // Next ALWAYS has move - itemInfo.NextPermissions |= (uint)PermissionMask.Move; - - if (part.Inventory.UpdateInventoryItem(itemInfo)) - { - part.SendPropertiesToClient(remoteClient); + itemInfo.EveryonePermissions &= currentItem.BasePermissions; + itemInfo.GroupPermissions &= currentItem.BasePermissions; + itemInfo.CurrentPermissions &= currentItem.BasePermissions; + itemInfo.NextPermissions &= currentItem.BasePermissions; } } - } - else - { - m_log.WarnFormat( - "[PRIM INVENTORY]: " + - "Update with item {0} requested of prim {1} for {2} but this prim does not exist", - itemID, primLocalID, remoteClient.Name); + else + { + if (itemInfo.BasePermissions != currentItem.BasePermissions) + itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteBase; + if (itemInfo.EveryonePermissions != currentItem.EveryonePermissions) + itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteEveryone; + if (itemInfo.GroupPermissions != currentItem.GroupPermissions) + itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteGroup; + if (itemInfo.CurrentPermissions != currentItem.CurrentPermissions) + itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteOwner; + if (itemInfo.NextPermissions != currentItem.NextPermissions) + itemInfo.Flags |= (uint)InventoryItemFlags.ObjectOverwriteNextOwner; + } + + // Next ALWAYS has move + itemInfo.NextPermissions |= (uint)PermissionMask.Move; + + if (part.Inventory.UpdateInventoryItem(itemInfo)) + { + part.SendPropertiesToClient(remoteClient); + } } } @@ -1960,6 +1967,8 @@ namespace OpenSim.Region.Framework.Scenes part.Inventory.AddInventoryItem(taskItem, false); part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); + part.ParentGroup.InvalidateEffectivePerms(); + // tell anyone managing scripts that a new script exists EventManager.TriggerNewScript(agentID, part, taskItem.ItemID); @@ -2095,13 +2104,20 @@ namespace OpenSim.Region.Framework.Scenes /// DeRezAction /// User folder ID to place derezzed object public virtual void DeRezObjects( - IClientAPI remoteClient, List localIDs, UUID groupID, DeRezAction action, UUID destinationID) + IClientAPI remoteClient, List localIDs, UUID groupID, DeRezAction action, UUID destinationID, bool AddToReturns = true) { // First, see of we can perform the requested action and // build a list of eligible objects List deleteIDs = new List(); List deleteGroups = new List(); List takeGroups = new List(); + List takeDeleteGroups = new List(); + + ScenePresence sp = null; + if(remoteClient != null) + sp = remoteClient.SceneAgent as ScenePresence; + else if(action != DeRezAction.Return) + return; // only Return can be called without a client // Start with true for both, then remove the flags if objects // that we can't derez are part of the selection @@ -2157,17 +2173,17 @@ namespace OpenSim.Region.Framework.Scenes { if (action == DeRezAction.TakeCopy) { - if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) + if (!Permissions.CanTakeCopyObject(grp, sp)) permissionToTakeCopy = false; } else { permissionToTakeCopy = false; } - if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) + if (!Permissions.CanTakeObject(grp, sp)) permissionToTake = false; - if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) + if (!Permissions.CanDeleteObject(grp, remoteClient)) permissionToDelete = false; } @@ -2208,13 +2224,14 @@ namespace OpenSim.Region.Framework.Scenes { if (Permissions.CanReturnObjects( null, - remoteClient.AgentId, + remoteClient, new List() {grp})) { permissionToTake = true; permissionToDelete = true; - - AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); + if(AddToReturns) + AddReturn(grp.OwnerID == grp.GroupID ? grp.LastOwnerID : grp.OwnerID, grp.Name, grp.AbsolutePosition, + "parcel owner return"); } } else // Auto return passes through here with null agent @@ -2224,26 +2241,24 @@ namespace OpenSim.Region.Framework.Scenes } } - if (permissionToTake && (!permissionToDelete)) - takeGroups.Add(grp); - if (permissionToDelete) { if (permissionToTake) + takeDeleteGroups.Add(grp); + else deleteGroups.Add(grp); deleteIDs.Add(grp.LocalId); } + else if(permissionToTake) + takeGroups.Add(grp); } SendKillObject(deleteIDs); - if (deleteGroups.Count > 0) + if (takeDeleteGroups.Count > 0) { - foreach (SceneObjectGroup g in deleteGroups) - deleteIDs.Remove(g.LocalId); - m_asyncSceneObjectDeleter.DeleteToInventory( - action, destinationID, deleteGroups, remoteClient, + action, destinationID, takeDeleteGroups, remoteClient, true); } if (takeGroups.Count > 0) @@ -2252,7 +2267,7 @@ namespace OpenSim.Region.Framework.Scenes action, destinationID, takeGroups, remoteClient, false); } - if (deleteIDs.Count > 0) + if (deleteGroups.Count > 0) { foreach (SceneObjectGroup g in deleteGroups) DeleteSceneObject(g, true); @@ -2640,6 +2655,7 @@ namespace OpenSim.Region.Framework.Scenes // We can only call this after adding the scene object, since the scene object references the scene // to find out if scripts should be activated at all. + group.InvalidateEffectivePerms(); group.CreateScriptInstances(param, true, DefaultScriptEngine, 3); group.ScheduleGroupForFullUpdate(); @@ -2649,7 +2665,7 @@ namespace OpenSim.Region.Framework.Scenes } public virtual bool returnObjects(SceneObjectGroup[] returnobjects, - UUID AgentId) + IClientAPI client) { List localIDs = new List(); @@ -2659,8 +2675,8 @@ namespace OpenSim.Region.Framework.Scenes "parcel owner return"); localIDs.Add(grp.RootPart.LocalId); } - DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, - UUID.Zero); + DeRezObjects(client, localIDs, UUID.Zero, DeRezAction.Return, + UUID.Zero, false); return true; } @@ -2691,9 +2707,6 @@ namespace OpenSim.Region.Framework.Scenes { if (ownerID != UUID.Zero) return; - - if (!Permissions.CanDeedObject(remoteClient.AgentId, groupID)) - return; } List groups = new List(); @@ -2724,21 +2737,22 @@ namespace OpenSim.Region.Framework.Scenes child.TriggerScriptChangedEvent(Changed.OWNER); } } - else // The object was deeded to the group + else // The object deeded to the group { - if (!Permissions.IsGod(remoteClient.AgentId) && sog.OwnerID != remoteClient.AgentId) - continue; - - if (!Permissions.CanTransferObject(sog.UUID, groupID)) - continue; - - if (sog.GroupID != groupID) + if (!Permissions.CanDeedObject(remoteClient, sog, groupID)) continue; sog.SetOwnerId(groupID); - // Make the group mask be the previous owner mask - sog.RootPart.GroupMask = sog.RootPart.OwnerMask; + + // this is wrong, GroupMask is used for group sharing, still possible to set + // this whould give owner rights to users that are member of group but don't have role powers to edit +// sog.RootPart.GroupMask = sog.RootPart.OwnerMask; + + // we should keep all permissions on deed to group + // and with this comented code, if user does not set next permissions on the object + // and on ALL contents of ALL prims, he may loose rights, making the object useless sog.ApplyNextOwnerPermissions(); + sog.InvalidateEffectivePerms(); sog.ScheduleGroupForFullUpdate(); @@ -2748,8 +2762,6 @@ namespace OpenSim.Region.Framework.Scenes child.Inventory.ChangeInventoryOwner(groupID); child.TriggerScriptChangedEvent(Changed.OWNER); } - - } } @@ -2853,7 +2865,7 @@ namespace OpenSim.Region.Framework.Scenes root.SendPropertiesToClient(sp.ControllingClient); if (oldUsePhysics && (root.Flags & PrimFlags.Physics) == 0) { - sp.ControllingClient.SendAlertMessage("Object physics canceled"); + sp.ControllingClient.SendAlertMessage("Object physics cancelled"); } } } diff --git a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs index 2d62b50af4..4fef9c3012 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.PacketHandlers.cs @@ -183,11 +183,12 @@ namespace OpenSim.Region.Framework.Scenes part.SendFullUpdate(remoteClient); // A prim is only tainted if it's allowed to be edited by the person clicking it. - if (Permissions.CanEditObject(sog.UUID, remoteClient.AgentId) - || Permissions.CanMoveObject(sog.UUID, remoteClient.AgentId)) + if (Permissions.CanChangeSelectedState(part, (ScenePresence)remoteClient.SceneAgent)) { + bool oldsel = part.IsSelected; part.IsSelected = true; - EventManager.TriggerParcelPrimCountTainted(); + if(!oldsel) + EventManager.TriggerParcelPrimCountTainted(); } part.SendPropertiesToClient(remoteClient); @@ -229,6 +230,7 @@ namespace OpenSim.Region.Framework.Scenes if (so.OwnerID == remoteClient.AgentId) { so.SetGroup(groupID, remoteClient); + EventManager.TriggerParcelPrimCountTainted(); } } } @@ -250,8 +252,7 @@ namespace OpenSim.Region.Framework.Scenes // handled by group, but by prim. Legacy cruft. // TODO: Make selection flagging per prim! // - if (Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId) - || Permissions.CanMoveObject(part.ParentGroup.UUID, remoteClient.AgentId)) + if (Permissions.CanChangeSelectedState(part, (ScenePresence)remoteClient.SceneAgent)) { part.IsSelected = false; if (!part.ParentGroup.IsAttachment && oldgprSelect != part.ParentGroup.IsSelected) @@ -327,7 +328,7 @@ namespace OpenSim.Region.Framework.Scenes if(group == null || group.IsDeleted) return; - if (Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) + if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.) { group.GrabMovement(objectID, offset, pos, remoteClient); } @@ -388,7 +389,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(objectID); if (group != null) { - if (Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) + if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.) { group.SpinStart(remoteClient); } @@ -406,7 +407,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(objectID); if (group != null) { - if (Permissions.CanMoveObject(group.UUID, remoteClient.AgentId))// && PermissionsMngr.) + if (Permissions.CanMoveObject(group, remoteClient))// && PermissionsMngr.) { group.SpinMovement(rotation, remoteClient); } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs index 893b38c152..a75671e6fd 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Permissions.cs @@ -37,52 +37,61 @@ using OpenSim.Region.Framework.Interfaces; namespace OpenSim.Region.Framework.Scenes { #region Delegates - public delegate uint GenerateClientFlagsHandler(UUID userID, UUID objectID); + public delegate uint GenerateClientFlagsHandler(SceneObjectPart part, ScenePresence sp, uint curEffectivePerms); public delegate void SetBypassPermissionsHandler(bool value); public delegate bool BypassPermissionsHandler(); public delegate bool PropagatePermissionsHandler(); - public delegate bool RezObjectHandler(int objectCount, UUID owner, Vector3 objectPosition, Scene scene); - public delegate bool DeleteObjectHandler(UUID objectID, UUID deleter, Scene scene); - public delegate bool TransferObjectHandler(UUID objectID, UUID recipient, Scene scene); - public delegate bool TakeObjectHandler(UUID objectID, UUID stealer, Scene scene); - public delegate bool SellGroupObjectHandler(UUID userID, UUID groupID, Scene scene); - public delegate bool TakeCopyObjectHandler(UUID objectID, UUID userID, Scene inScene); - public delegate bool DuplicateObjectHandler(int objectCount, UUID objectID, UUID owner, Scene scene, Vector3 objectPosition); - public delegate bool EditObjectHandler(UUID objectID, UUID editorID, Scene scene); - public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID, Scene scene); - public delegate bool MoveObjectHandler(UUID objectID, UUID moverID, Scene scene); - public delegate bool ObjectEntryHandler(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene); - public delegate bool ReturnObjectsHandler(ILandObject land, UUID user, List objects, Scene scene); - public delegate bool InstantMessageHandler(UUID user, UUID target, Scene startScene); - public delegate bool InventoryTransferHandler(UUID user, UUID target, Scene startScene); - public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); - public delegate bool ViewNotecardHandler(UUID script, UUID objectID, UUID user, Scene scene); - public delegate bool EditScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); - public delegate bool EditNotecardHandler(UUID notecard, UUID objectID, UUID user, Scene scene); - public delegate bool RunScriptHandler(UUID script, UUID objectID, UUID user, Scene scene); - public delegate bool CompileScriptHandler(UUID ownerUUID, int scriptType, Scene scene); - public delegate bool StartScriptHandler(UUID script, UUID user, Scene scene); - public delegate bool StopScriptHandler(UUID script, UUID user, Scene scene); - public delegate bool ResetScriptHandler(UUID prim, UUID script, UUID user, Scene scene); - public delegate bool TerraformLandHandler(UUID user, Vector3 position, Scene requestFromScene); - public delegate bool RunConsoleCommandHandler(UUID user, Scene requestFromScene); - public delegate bool IssueEstateCommandHandler(UUID user, Scene requestFromScene, bool ownerCommand); - public delegate bool IsGodHandler(UUID user, Scene requestFromScene); - public delegate bool IsGridGodHandler(UUID user, Scene requestFromScene); + public delegate bool RezObjectHandler(int objectCount, UUID owner, Vector3 objectPosition); + public delegate bool DeleteObjectHandlerByIDs(UUID objectID, UUID deleter); + public delegate bool DeleteObjectHandler(SceneObjectGroup sog, ScenePresence sp); + public delegate bool TransferObjectHandler(UUID objectID, UUID recipient); + public delegate bool TakeObjectHandler(SceneObjectGroup sog, ScenePresence sp); + public delegate bool SellGroupObjectHandler(UUID userID, UUID groupID); + public delegate bool SellObjectHandlerByUserID(SceneObjectGroup sog, UUID userID, byte saleType); + public delegate bool SellObjectHandler(SceneObjectGroup sog, ScenePresence sp, byte saleType); + public delegate bool TakeCopyObjectHandler(SceneObjectGroup sog, ScenePresence sp); + public delegate bool DuplicateObjectHandler(SceneObjectGroup sog, ScenePresence sp); + public delegate bool EditObjectByIDsHandler(UUID objectID, UUID editorID); + public delegate bool EditObjectHandler(SceneObjectGroup sog, ScenePresence sp); + public delegate bool EditObjectPermsHandler(SceneObjectGroup sog, UUID editorID); + public delegate bool EditObjectInventoryHandler(UUID objectID, UUID editorID); + public delegate bool MoveObjectHandler(SceneObjectGroup sog, ScenePresence sp); + public delegate bool ObjectEntryHandler(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint); + public delegate bool ObjectEnterWithScriptsHandler(SceneObjectGroup sog, ILandObject land); + public delegate bool ReturnObjectsHandler(ILandObject land, ScenePresence sp, List objects); + public delegate bool InstantMessageHandler(UUID user, UUID target); + public delegate bool InventoryTransferHandler(UUID user, UUID target); + public delegate bool ViewScriptHandler(UUID script, UUID objectID, UUID user); + public delegate bool ViewNotecardHandler(UUID script, UUID objectID, UUID user); + public delegate bool EditScriptHandler(UUID script, UUID objectID, UUID user); + public delegate bool EditNotecardHandler(UUID notecard, UUID objectID, UUID user); + public delegate bool RunScriptHandlerByIDs(UUID script, UUID objectID, UUID user); + public delegate bool RunScriptHandler(TaskInventoryItem item, SceneObjectPart part); + public delegate bool CompileScriptHandler(UUID ownerUUID, int scriptType); + public delegate bool StartScriptHandler(UUID script, UUID user); + public delegate bool StopScriptHandler(UUID script, UUID user); + public delegate bool ResetScriptHandler(UUID prim, UUID script, UUID user); + public delegate bool TerraformLandHandler(UUID user, Vector3 position); + public delegate bool RunConsoleCommandHandler(UUID user); + public delegate bool IssueEstateCommandHandler(UUID user, bool ownerCommand); + public delegate bool IsGodHandler(UUID user); + public delegate bool IsGridGodHandler(UUID user); public delegate bool IsAdministratorHandler(UUID user); public delegate bool IsEstateManagerHandler(UUID user); - public delegate bool EditParcelHandler(UUID user, ILandObject parcel, Scene scene); - public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, Scene scene, bool allowManager); - public delegate bool SellParcelHandler(UUID user, ILandObject parcel, Scene scene); - public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel, Scene scene); - public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel, Scene scene); - public delegate bool DeedParcelHandler(UUID user, ILandObject parcel, Scene scene); - public delegate bool DeedObjectHandler(UUID user, UUID group, Scene scene); - public delegate bool BuyLandHandler(UUID user, ILandObject parcel, Scene scene); + public delegate bool EditParcelHandler(UUID user, ILandObject parcel); + public delegate bool EditParcelPropertiesHandler(UUID user, ILandObject parcel, GroupPowers p, bool allowManager); + public delegate bool SellParcelHandler(UUID user, ILandObject parcel); + public delegate bool AbandonParcelHandler(UUID user, ILandObject parcel); + public delegate bool ReclaimParcelHandler(UUID user, ILandObject parcel); + public delegate bool DeedParcelHandler(UUID user, ILandObject parcel); + public delegate bool DeedObjectHandler(ScenePresence sp, SceneObjectGroup sog, UUID targetGroupID); + public delegate bool BuyLandHandler(UUID user, ILandObject parcel); public delegate bool LinkObjectHandler(UUID user, UUID objectID); public delegate bool DelinkObjectHandler(UUID user, UUID objectID); public delegate bool CreateObjectInventoryHandler(int invType, UUID objectID, UUID userID); public delegate bool CopyObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID); + public delegate bool DoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart); + public delegate bool DoDropInObjectInv(InventoryItemBase item, ScenePresence sp, SceneObjectPart destPart); public delegate bool DeleteObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID); public delegate bool TransferObjectInventoryHandler(UUID itemID, UUID objectID, UUID userID); public delegate bool CreateUserInventoryHandler(int invType, UUID userID); @@ -112,16 +121,24 @@ namespace OpenSim.Region.Framework.Scenes public event BypassPermissionsHandler OnBypassPermissions; public event PropagatePermissionsHandler OnPropagatePermissions; public event RezObjectHandler OnRezObject; + public event DeleteObjectHandlerByIDs OnDeleteObjectByIDs; public event DeleteObjectHandler OnDeleteObject; public event TransferObjectHandler OnTransferObject; public event TakeObjectHandler OnTakeObject; + public event SellGroupObjectHandler OnSellGroupObject; + public event SellObjectHandlerByUserID OnSellObjectByUserID; + public event SellObjectHandler OnSellObject; + public event TakeCopyObjectHandler OnTakeCopyObject; public event DuplicateObjectHandler OnDuplicateObject; + public event EditObjectByIDsHandler OnEditObjectByIDs; public event EditObjectHandler OnEditObject; + public event EditObjectPermsHandler OnEditObjectPerms; public event EditObjectInventoryHandler OnEditObjectInventory; public event MoveObjectHandler OnMoveObject; public event ObjectEntryHandler OnObjectEntry; + public event ObjectEnterWithScriptsHandler OnObjectEnterWithScripts; public event ReturnObjectsHandler OnReturnObjects; public event InstantMessageHandler OnInstantMessage; public event InventoryTransferHandler OnInventoryTransfer; @@ -129,6 +146,7 @@ namespace OpenSim.Region.Framework.Scenes public event ViewNotecardHandler OnViewNotecard; public event EditScriptHandler OnEditScript; public event EditNotecardHandler OnEditNotecard; + public event RunScriptHandlerByIDs OnRunScriptByIDs; public event RunScriptHandler OnRunScript; public event CompileScriptHandler OnCompileScript; public event StartScriptHandler OnStartScript; @@ -137,7 +155,6 @@ namespace OpenSim.Region.Framework.Scenes public event TerraformLandHandler OnTerraformLand; public event RunConsoleCommandHandler OnRunConsoleCommand; public event IssueEstateCommandHandler OnIssueEstateCommand; - public event IsGodHandler OnIsGod; public event IsGridGodHandler OnIsGridGod; public event IsAdministratorHandler OnIsAdministrator; public event IsEstateManagerHandler OnIsEstateManager; @@ -153,6 +170,8 @@ namespace OpenSim.Region.Framework.Scenes public event DelinkObjectHandler OnDelinkObject; public event CreateObjectInventoryHandler OnCreateObjectInventory; public event CopyObjectInventoryHandler OnCopyObjectInventory; + public event DoObjectInvToObjectInv OnDoObjectInvToObjectInv; + public event DoDropInObjectInv OnDropInObjectInv; public event DeleteObjectInventoryHandler OnDeleteObjectInventory; public event TransferObjectInventoryHandler OnTransferObjectInventory; public event CreateUserInventoryHandler OnCreateUserInventory; @@ -167,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes #region Object Permission Checks - public uint GenerateClientFlags(UUID userID, UUID objectID) + public uint GenerateClientFlags( SceneObjectPart part, ScenePresence sp) { // libomv will moan about PrimFlags.ObjectYouOfficer being // obsolete... @@ -179,12 +198,9 @@ namespace OpenSim.Region.Framework.Scenes PrimFlags.ObjectTransfer | PrimFlags.ObjectYouOwner | PrimFlags.ObjectAnyOwner | - PrimFlags.ObjectOwnerModify | - PrimFlags.ObjectYouOfficer; + PrimFlags.ObjectOwnerModify; #pragma warning restore 0612 - SceneObjectPart part = m_scene.GetSceneObjectPart(objectID); - if (part == null) return 0; @@ -196,7 +212,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handlerGenerateClientFlags.GetInvocationList(); foreach (GenerateClientFlagsHandler check in list) { - perms &= check(userID, objectID); + perms &= check(part, sp, perms); } } return perms; @@ -248,7 +264,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (RezObjectHandler h in list) { - if (h(objectCount, owner,objectPosition, m_scene) == false) + if (h(objectCount, owner,objectPosition) == false) return false; } } @@ -262,141 +278,183 @@ namespace OpenSim.Region.Framework.Scenes { bool result = true; - DeleteObjectHandler handler = OnDeleteObject; + DeleteObjectHandlerByIDs handler = OnDeleteObjectByIDs; if (handler != null) { Delegate[] list = handler.GetInvocationList(); - foreach (DeleteObjectHandler h in list) + foreach (DeleteObjectHandlerByIDs h in list) { - if (h(objectID, deleter, m_scene) == false) + if (h(objectID, deleter) == false) { result = false; break; } } } - return result; } + public bool CanDeleteObject(SceneObjectGroup sog, IClientAPI client) + { + DeleteObjectHandler handler = OnDeleteObject; + if (handler != null) + { + if(sog == null || client == null || client.SceneAgent == null) + return false; + + ScenePresence sp = client.SceneAgent as ScenePresence; + + Delegate[] list = handler.GetInvocationList(); + foreach (DeleteObjectHandler h in list) + { + if (h(sog, sp) == false) + return false; + } + } + + return true; + } + public bool CanTransferObject(UUID objectID, UUID recipient) { - bool result = true; - TransferObjectHandler handler = OnTransferObject; if (handler != null) { Delegate[] list = handler.GetInvocationList(); foreach (TransferObjectHandler h in list) { - if (h(objectID, recipient, m_scene) == false) - { - result = false; - break; - } + if (h(objectID, recipient) == false) + return false; } } - - return result; + return true; } #endregion #region TAKE OBJECT - public bool CanTakeObject(UUID objectID, UUID AvatarTakingUUID) + public bool CanTakeObject(SceneObjectGroup sog, ScenePresence sp) { - bool result = true; - TakeObjectHandler handler = OnTakeObject; if (handler != null) { + if(sog == null || sp == null) + return false; + Delegate[] list = handler.GetInvocationList(); foreach (TakeObjectHandler h in list) { - if (h(objectID, AvatarTakingUUID, m_scene) == false) - { - result = false; - break; - } + if (h(sog, sp) == false) + return false; } } - // m_log.DebugFormat( // "[SCENE PERMISSIONS]: CanTakeObject() fired for object {0}, taker {1}, result {2}", // objectID, AvatarTakingUUID, result); - - return result; + return true; } #endregion #region SELL GROUP OBJECT - public bool CanSellGroupObject(UUID userID, UUID groupID, Scene scene) + public bool CanSellGroupObject(UUID userID, UUID groupID) { - bool result = true; - SellGroupObjectHandler handler = OnSellGroupObject; if (handler != null) { Delegate[] list = handler.GetInvocationList(); foreach (SellGroupObjectHandler h in list) { - if (h(userID, groupID, scene) == false) - { - result = false; - break; - } + if (h(userID, groupID) == false) + return false; } } - //m_log.DebugFormat( // "[SCENE PERMISSIONS]: CanSellGroupObject() fired for user {0}, group {1}, result {2}", // userID, groupID, result); + return true; + } - return result; + #endregion + + #region SELL OBJECT + public bool CanSellObject(IClientAPI client, SceneObjectGroup sog, byte saleType) + { + SellObjectHandler handler = OnSellObject; + if (handler != null) + { + if(sog == null || client == null || client.SceneAgent == null) + return false; + + ScenePresence sp = client.SceneAgent as ScenePresence; + Delegate[] list = handler.GetInvocationList(); + foreach (SellObjectHandler h in list) + { + if (h(sog, sp, saleType) == false) + return false; + } + } + return true; + } + + public bool CanSellObject(UUID userID, SceneObjectGroup sog, byte saleType) + { + SellObjectHandlerByUserID handler = OnSellObjectByUserID; + if (handler != null) + { + if(sog == null) + return false; + Delegate[] list = handler.GetInvocationList(); + foreach (SellObjectHandlerByUserID h in list) + { + if (h(sog, userID, saleType) == false) + return false; + } + } + return true; } #endregion #region TAKE COPY OBJECT - public bool CanTakeCopyObject(UUID objectID, UUID userID) + public bool CanTakeCopyObject(SceneObjectGroup sog, ScenePresence sp) { - bool result = true; - TakeCopyObjectHandler handler = OnTakeCopyObject; if (handler != null) { + if(sog == null || sp == null) + return false; Delegate[] list = handler.GetInvocationList(); foreach (TakeCopyObjectHandler h in list) { - if (h(objectID, userID, m_scene) == false) - { - result = false; - break; - } + if (h(sog, sp) == false) + return false; } } - // m_log.DebugFormat( // "[SCENE PERMISSIONS]: CanTakeCopyObject() fired for object {0}, user {1}, result {2}", // objectID, userID, result); - - return result; + return true; } #endregion #region DUPLICATE OBJECT - public bool CanDuplicateObject(int objectCount, UUID objectID, UUID owner, Vector3 objectPosition) + public bool CanDuplicateObject(SceneObjectGroup sog, UUID agentID) { DuplicateObjectHandler handler = OnDuplicateObject; if (handler != null) { + if(sog == null || sog.IsDeleted) + return false; + ScenePresence sp = m_scene.GetScenePresence(agentID); + if(sp == null || sp.IsDeleted) + return false; Delegate[] list = handler.GetInvocationList(); foreach (DuplicateObjectHandler h in list) { - if (h(objectCount, objectID, owner, m_scene, objectPosition) == false) + if (h(sog, sp) == false) return false; } } @@ -405,22 +463,74 @@ namespace OpenSim.Region.Framework.Scenes #endregion + #region persence EDIT or MOVE OBJECT + private const uint CANSELECTMASK = (uint)( + PrimFlags.ObjectMove | + PrimFlags.ObjectModify | + PrimFlags.ObjectOwnerModify + ); + + public bool CanChangeSelectedState(SceneObjectPart part, ScenePresence sp) + { + uint perms = GenerateClientFlags(part, sp); + return (perms & CANSELECTMASK) != 0; + } + + #endregion #region EDIT OBJECT public bool CanEditObject(UUID objectID, UUID editorID) { - EditObjectHandler handler = OnEditObject; + EditObjectByIDsHandler handler = OnEditObjectByIDs; if (handler != null) { Delegate[] list = handler.GetInvocationList(); - foreach (EditObjectHandler h in list) + foreach (EditObjectByIDsHandler h in list) { - if (h(objectID, editorID, m_scene) == false) + if (h(objectID, editorID) == false) return false; } } return true; } + public bool CanEditObject(SceneObjectGroup sog, IClientAPI client) + { + EditObjectHandler handler = OnEditObject; + if (handler != null) + { + if(sog == null || client == null || client.SceneAgent == null) + return false; + + ScenePresence sp = client.SceneAgent as ScenePresence; + + Delegate[] list = handler.GetInvocationList(); + foreach (EditObjectHandler h in list) + { + if (h(sog, sp) == false) + return false; + } + } + return true; + } + + public bool CanEditObjectPermissions(SceneObjectGroup sog, UUID editorID) + { + EditObjectPermsHandler handler = OnEditObjectPerms; + if (handler != null) + { + if(sog == null) + return false; + Delegate[] list = handler.GetInvocationList(); + foreach (EditObjectPermsHandler h in list) + { + if (h(sog, editorID) == false) + return false; + } + } + return true; + } + + public bool CanEditObjectInventory(UUID objectID, UUID editorID) { EditObjectInventoryHandler handler = OnEditObjectInventory; @@ -429,7 +539,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (EditObjectInventoryHandler h in list) { - if (h(objectID, editorID, m_scene) == false) + if (h(objectID, editorID) == false) return false; } } @@ -439,15 +549,20 @@ namespace OpenSim.Region.Framework.Scenes #endregion #region MOVE OBJECT - public bool CanMoveObject(UUID objectID, UUID moverID) + public bool CanMoveObject(SceneObjectGroup sog, IClientAPI client) { MoveObjectHandler handler = OnMoveObject; if (handler != null) { + if(sog == null || client == null || client.SceneAgent == null) + return false; + + ScenePresence sp = client.SceneAgent as ScenePresence; + Delegate[] list = handler.GetInvocationList(); foreach (MoveObjectHandler h in list) { - if (h(objectID, moverID, m_scene) == false) + if (h(sog, sp) == false) return false; } } @@ -457,7 +572,7 @@ namespace OpenSim.Region.Framework.Scenes #endregion #region OBJECT ENTRY - public bool CanObjectEntry(UUID objectID, bool enteringRegion, Vector3 newPoint) + public bool CanObjectEntry(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint) { ObjectEntryHandler handler = OnObjectEntry; if (handler != null) @@ -465,7 +580,22 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (ObjectEntryHandler h in list) { - if (h(objectID, enteringRegion, newPoint, m_scene) == false) + if (h(sog, enteringRegion, newPoint) == false) + return false; + } + } + return true; + } + + public bool CanObjectEnterWithScripts(SceneObjectGroup sog, ILandObject land) + { + ObjectEnterWithScriptsHandler handler = OnObjectEnterWithScripts; + if (handler != null) + { + Delegate[] list = handler.GetInvocationList(); + foreach (ObjectEnterWithScriptsHandler h in list) + { + if (h(sog, land) == false) return false; } } @@ -475,29 +605,30 @@ namespace OpenSim.Region.Framework.Scenes #endregion #region RETURN OBJECT - public bool CanReturnObjects(ILandObject land, UUID user, List objects) + public bool CanReturnObjects(ILandObject land, IClientAPI client, List objects) { - bool result = true; - ReturnObjectsHandler handler = OnReturnObjects; if (handler != null) { + if(objects == null) + return false; + + ScenePresence sp = null; + if(client != null && client.SceneAgent != null) + sp = client.SceneAgent as ScenePresence; + Delegate[] list = handler.GetInvocationList(); foreach (ReturnObjectsHandler h in list) { - if (h(land, user, objects, m_scene) == false) - { - result = false; - break; - } + if (h(land, sp, objects) == false) + return false; } } - // m_log.DebugFormat( // "[SCENE PERMISSIONS]: CanReturnObjects() fired for user {0} for {1} objects on {2}, result {3}", // user, objects.Count, land.LandData.Name, result); - return result; + return true; } #endregion @@ -511,7 +642,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (InstantMessageHandler h in list) { - if (h(user, target, m_scene) == false) + if (h(user, target) == false) return false; } } @@ -529,7 +660,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (InventoryTransferHandler h in list) { - if (h(user, target, m_scene) == false) + if (h(user, target) == false) return false; } } @@ -547,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (ViewScriptHandler h in list) { - if (h(script, objectID, user, m_scene) == false) + if (h(script, objectID, user) == false) return false; } } @@ -562,7 +693,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (ViewNotecardHandler h in list) { - if (h(script, objectID, user, m_scene) == false) + if (h(script, objectID, user) == false) return false; } } @@ -580,7 +711,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (EditScriptHandler h in list) { - if (h(script, objectID, user, m_scene) == false) + if (h(script, objectID, user) == false) return false; } } @@ -595,7 +726,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (EditNotecardHandler h in list) { - if (h(script, objectID, user, m_scene) == false) + if (h(script, objectID, user) == false) return false; } } @@ -607,19 +738,37 @@ namespace OpenSim.Region.Framework.Scenes #region RUN SCRIPT (When Script Placed in Object) public bool CanRunScript(UUID script, UUID objectID, UUID user) { - RunScriptHandler handler = OnRunScript; + RunScriptHandlerByIDs handler = OnRunScriptByIDs; if (handler != null) { Delegate[] list = handler.GetInvocationList(); - foreach (RunScriptHandler h in list) + foreach (RunScriptHandlerByIDs h in list) { - if (h(script, objectID, user, m_scene) == false) + if (h(script, objectID, user) == false) return false; } } return true; } + public bool CanRunScript(TaskInventoryItem item, SceneObjectPart part) + { + RunScriptHandler handler = OnRunScript; + if (handler != null) + { + if(item == null || part == null) + return false; + Delegate[] list = handler.GetInvocationList(); + foreach (RunScriptHandler h in list) + { + if (h(item, part) == false) + return false; + } + } + return true; + } + + #endregion #region COMPILE SCRIPT (When Script needs to get (re)compiled) @@ -631,7 +780,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (CompileScriptHandler h in list) { - if (h(ownerUUID, scriptType, m_scene) == false) + if (h(ownerUUID, scriptType) == false) return false; } } @@ -649,7 +798,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (StartScriptHandler h in list) { - if (h(script, user, m_scene) == false) + if (h(script, user) == false) return false; } } @@ -667,7 +816,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (StopScriptHandler h in list) { - if (h(script, user, m_scene) == false) + if (h(script, user) == false) return false; } } @@ -685,7 +834,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (ResetScriptHandler h in list) { - if (h(prim, script, user, m_scene) == false) + if (h(prim, script, user) == false) return false; } } @@ -703,7 +852,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (TerraformLandHandler h in list) { - if (h(user, pos, m_scene) == false) + if (h(user, pos) == false) return false; } } @@ -721,7 +870,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (RunConsoleCommandHandler h in list) { - if (h(user, m_scene) == false) + if (h(user) == false) return false; } } @@ -739,7 +888,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (IssueEstateCommandHandler h in list) { - if (h(user, m_scene, ownerCommand) == false) + if (h(user, ownerCommand) == false) return false; } } @@ -750,13 +899,13 @@ namespace OpenSim.Region.Framework.Scenes #region CAN BE GODLIKE public bool IsGod(UUID user) { - IsGodHandler handler = OnIsGod; + IsAdministratorHandler handler = OnIsAdministrator; if (handler != null) { Delegate[] list = handler.GetInvocationList(); - foreach (IsGodHandler h in list) + foreach (IsAdministratorHandler h in list) { - if (h(user, m_scene) == false) + if (h(user) == false) return false; } } @@ -771,7 +920,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (IsGridGodHandler h in list) { - if (h(user, m_scene) == false) + if (h(user) == false) return false; } } @@ -819,7 +968,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (EditParcelPropertiesHandler h in list) { - if (h(user, parcel, p, m_scene, allowManager) == false) + if (h(user, parcel, p, allowManager) == false) return false; } } @@ -836,7 +985,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (SellParcelHandler h in list) { - if (h(user, parcel, m_scene) == false) + if (h(user, parcel) == false) return false; } } @@ -853,7 +1002,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (AbandonParcelHandler h in list) { - if (h(user, parcel, m_scene) == false) + if (h(user, parcel) == false) return false; } } @@ -869,7 +1018,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (ReclaimParcelHandler h in list) { - if (h(user, parcel, m_scene) == false) + if (h(user, parcel) == false) return false; } } @@ -884,22 +1033,27 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (DeedParcelHandler h in list) { - if (h(user, parcel, m_scene) == false) + if (h(user, parcel) == false) return false; } } return true; } - public bool CanDeedObject(UUID user, UUID group) + public bool CanDeedObject(IClientAPI client, SceneObjectGroup sog, UUID targetGroupID) { DeedObjectHandler handler = OnDeedObject; if (handler != null) { + if(sog == null || client == null || client.SceneAgent == null || targetGroupID == UUID.Zero) + return false; + + ScenePresence sp = client.SceneAgent as ScenePresence; + Delegate[] list = handler.GetInvocationList(); foreach (DeedObjectHandler h in list) { - if (h(user, group, m_scene) == false) + if (h(sp, sog, targetGroupID) == false) return false; } } @@ -914,7 +1068,7 @@ namespace OpenSim.Region.Framework.Scenes Delegate[] list = handler.GetInvocationList(); foreach (BuyLandHandler h in list) { - if (h(user, parcel, m_scene) == false) + if (h(user, parcel) == false) return false; } } @@ -990,6 +1144,45 @@ namespace OpenSim.Region.Framework.Scenes return true; } + public bool CanDoObjectInvToObjectInv(TaskInventoryItem item, SceneObjectPart sourcePart, SceneObjectPart destPart) + { + DoObjectInvToObjectInv handler = OnDoObjectInvToObjectInv; + if (handler != null) + { + if (sourcePart == null || destPart == null || item == null) + return false; + Delegate[] list = handler.GetInvocationList(); + foreach (DoObjectInvToObjectInv h in list) + { + if (h(item, sourcePart, destPart) == false) + return false; + } + } + return true; + } + + public bool CanDropInObjectInv(InventoryItemBase item, IClientAPI client, SceneObjectPart destPart) + { + DoDropInObjectInv handler = OnDropInObjectInv; + if (handler != null) + { + if (client == null || client.SceneAgent == null|| destPart == null || item == null) + return false; + + ScenePresence sp = client.SceneAgent as ScenePresence; + if(sp == null || sp.IsDeleted) + return false; + + Delegate[] list = handler.GetInvocationList(); + foreach (DoDropInObjectInv h in list) + { + if (h(item, sp, destPart) == false) + return false; + } + } + return true; + } + public bool CanDeleteObjectInventory(UUID itemID, UUID objectID, UUID userID) { DeleteObjectInventoryHandler handler = OnDeleteObjectInventory; diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 2137b42417..c06b3dd401 100755 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -257,37 +257,7 @@ namespace OpenSim.Region.Framework.Scenes public bool m_useFlySlow; public bool m_useTrashOnDelete = true; - /// - /// Temporarily setting to trigger appearance resends at 60 second intervals. - /// - public bool SendPeriodicAppearanceUpdates { get; set; } - - /// - /// How much a root agent has to change position before updates are sent to viewers. - /// - public float RootPositionUpdateTolerance { get; set; } - - /// - /// How much a root agent has to rotate before updates are sent to viewers. - /// - public float RootRotationUpdateTolerance { get; set; } - - /// - /// How much a root agent has to change velocity before updates are sent to viewers. - /// - public float RootVelocityUpdateTolerance { get; set; } - - /// - /// If greater than 1, we only send terse updates to other root agents on every n updates. - /// - public int RootTerseUpdatePeriod { get; set; } - - /// - /// If greater than 1, we only send terse updates to child agents on every n updates. - /// - public int ChildTerseUpdatePeriod { get; set; } - - protected float m_defaultDrawDistance = 255f; + protected float m_defaultDrawDistance = 255f; protected float m_defaultCullingDrawDistance = 16f; public float DefaultDrawDistance { @@ -375,11 +345,6 @@ namespace OpenSim.Region.Framework.Scenes protected set; } - /// - /// Current maintenance run number - /// - public uint MaintenanceRun { get; private set; } - /// /// Frame time /// @@ -391,14 +356,6 @@ namespace OpenSim.Region.Framework.Scenes // see SimStatsReporter.cs public bool Normalized55FPS { get; private set; } - /// - /// The minimum length of time in seconds that will be taken for a scene frame. - /// - /// - /// Always derived from MinFrameTicks. - /// - public float MinMaintenanceTime { get; private set; } - private int m_update_physics = 1; private int m_update_entitymovement = 1; private int m_update_objects = 1; @@ -407,9 +364,8 @@ namespace OpenSim.Region.Framework.Scenes private int m_update_backup = 200; private int m_update_terrain = 1000; - private int m_update_land = 10; - private int m_update_coarse_locations = 50; + private int m_update_coarse_locations = 5; private int m_update_temp_cleaning = 180; private float agentMS; @@ -428,11 +384,6 @@ namespace OpenSim.Region.Framework.Scenes /// private int m_lastFrameTick; - /// - /// Tick at which the last maintenance run occurred. - /// - private int m_lastMaintenanceTick; - /// /// Total script execution time (in Stopwatch Ticks) since the last frame /// @@ -443,17 +394,13 @@ namespace OpenSim.Region.Framework.Scenes /// asynchronously from the update loop. /// private bool m_cleaningTemps = false; + private bool m_sendingCoarseLocations = false; // same for async course locations sending /// /// Used to control main scene thread looping time when not updating via timer. /// private ManualResetEvent m_updateWaitEvent = new ManualResetEvent(false); - /// - /// Used to control maintenance thread runs. - /// - private ManualResetEvent m_maintenanceWaitEvent = new ManualResetEvent(false); - // TODO: Possibly stop other classes being able to manipulate this directly. private SceneGraph m_sceneGraph; private readonly Timer m_restartTimer = new Timer(15000); // Wait before firing @@ -497,7 +444,7 @@ namespace OpenSim.Region.Framework.Scenes /// Is the scene active? /// /// - /// If false, maintenance and update loops are not being run, though after setting to false update may still + /// If false, update loop is not being run, though after setting to false update may still /// be active for a period (and IsRunning will still be true). Updates can still be triggered manually if /// the scene is not active. /// @@ -527,7 +474,6 @@ namespace OpenSim.Region.Framework.Scenes public bool IsRunning { get { return m_isRunning; } } private volatile bool m_isRunning; -// private int m_lastUpdate; private bool m_firstHeartbeat = true; // private UpdatePrioritizationSchemes m_priorityScheme = UpdatePrioritizationSchemes.Time; @@ -540,6 +486,9 @@ namespace OpenSim.Region.Framework.Scenes private Timer m_mapGenerationTimer = new Timer(); private bool m_generateMaptiles; + protected int m_lastHealth = -1; + protected int m_lastUsers = -1; + #endregion Fields #region Properties @@ -805,6 +754,8 @@ namespace OpenSim.Region.Framework.Scenes private float m_minReprioritizationDistance = 32f; public bool ObjectsCullingByDistance = false; + private ExpiringCache TeleportTargetsCoolDown = new ExpiringCache(); + public AgentCircuitManager AuthenticateHandler { get { return m_authenticateHandler; } @@ -878,7 +829,6 @@ namespace OpenSim.Region.Framework.Scenes FrameTimeWarnPercent = 60; FrameTimeCritPercent = 40; Normalized55FPS = true; - MinMaintenanceTime = 1; SeeIntoRegion = true; Random random = new Random(); @@ -973,6 +923,7 @@ namespace OpenSim.Region.Framework.Scenes m_maxDrawDistance = startupConfig.GetFloat("MaxDrawDistance", m_maxDrawDistance); m_maxRegionViewDistance = startupConfig.GetFloat("MaxRegionsViewDistance", m_maxRegionViewDistance); + // old versions compatibility LegacySitOffsets = startupConfig.GetBoolean("LegacySitOffsets", LegacySitOffsets); if (m_defaultDrawDistance > m_maxDrawDistance) @@ -1141,17 +1092,6 @@ namespace OpenSim.Region.Framework.Scenes } - - // FIXME: Ultimately this should be in a module. - SendPeriodicAppearanceUpdates = false; - - IConfig appearanceConfig = m_config.Configs["Appearance"]; - if (appearanceConfig != null) - { - SendPeriodicAppearanceUpdates - = appearanceConfig.GetBoolean("ResendAppearanceUpdates", SendPeriodicAppearanceUpdates); - } - #endregion Region Config IConfig entityTransferConfig = m_config.Configs["EntityTransfer"]; @@ -1191,16 +1131,6 @@ namespace OpenSim.Region.Framework.Scenes ObjectsCullingByDistance = interestConfig.GetBoolean("ObjectsCullingByDistance", ObjectsCullingByDistance); - - RootTerseUpdatePeriod = interestConfig.GetInt("RootTerseUpdatePeriod", RootTerseUpdatePeriod); - ChildTerseUpdatePeriod = interestConfig.GetInt("ChildTerseUpdatePeriod", ChildTerseUpdatePeriod); - - RootPositionUpdateTolerance - = interestConfig.GetFloat("RootPositionUpdateTolerance", RootPositionUpdateTolerance); - RootRotationUpdateTolerance - = interestConfig.GetFloat("RootRotationUpdateTolerance", RootRotationUpdateTolerance); - RootVelocityUpdateTolerance - = interestConfig.GetFloat("RootVelocityUpdateTolerance", RootVelocityUpdateTolerance); } m_log.DebugFormat("[SCENE]: Using the {0} prioritization scheme", UpdatePrioritizationScheme); @@ -1212,6 +1142,30 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; + IConfig restartConfig = config.Configs["RestartModule"]; + if (restartConfig != null) + { + string markerPath = restartConfig.GetString("MarkerPath", String.Empty); + + if (markerPath != String.Empty) + { + string path = Path.Combine(markerPath, RegionInfo.RegionID.ToString() + ".started"); + try + { + string pidstring = System.Diagnostics.Process.GetCurrentProcess().Id.ToString(); + FileStream fs = File.Create(path); + System.Text.ASCIIEncoding enc = new System.Text.ASCIIEncoding(); + Byte[] buf = enc.GetBytes(pidstring); + fs.Write(buf, 0, buf.Length); + fs.Close(); + } + catch (Exception) + { + } + } + } + + StartTimerWatchdog(); } public Scene(RegionInfo regInfo) @@ -1245,9 +1199,6 @@ namespace OpenSim.Region.Framework.Scenes UpdatePrioritizationScheme = UpdatePrioritizationSchemes.Time; ReprioritizationInterval = 5000; - RootRotationUpdateTolerance = 0.1f; - RootVelocityUpdateTolerance = 0.001f; - RootPositionUpdateTolerance = 0.05f; ReprioritizationDistance = m_minReprioritizationDistance; m_eventManager = new EventManager(); @@ -1482,6 +1433,14 @@ namespace OpenSim.Region.Framework.Scenes return; } + IEtcdModule etcd = RequestModuleInterface(); + if (etcd != null) + { + etcd.Delete("Health"); + etcd.Delete("HealthFlags"); + etcd.Delete("RootAgents"); + } + m_log.InfoFormat("[SCENE]: Closing down the single simulator: {0}", RegionInfo.RegionName); @@ -1520,6 +1479,8 @@ namespace OpenSim.Region.Framework.Scenes m_log.Debug("[SCENE]: Persisting changed objects"); Backup(true); + m_log.Debug("[SCENE]: Closing scene"); + m_sceneGraph.Close(); base.Close(); @@ -1628,100 +1589,12 @@ namespace OpenSim.Region.Framework.Scenes // alarms for scenes with many objects. Update(1); - WorkManager.StartThread( - Maintenance, string.Format("Maintenance ({0})", RegionInfo.RegionName), ThreadPriority.Normal, false, true); - Watchdog.GetCurrentThreadInfo().AlarmIfTimeout = true; m_lastFrameTick = Util.EnvironmentTickCount(); Update(-1); - Watchdog.RemoveThread(); } - private void Maintenance() - { - DoMaintenance(-1); - - Watchdog.RemoveThread(); - } - - public void DoMaintenance(int runs) - { - long? endRun = null; - int runtc, tmpMS; - int previousMaintenanceTick; - - if (runs >= 0) - endRun = MaintenanceRun + runs; - - List coarseLocations; - List avatarUUIDs; - - while (!m_shuttingDown && ((endRun == null && Active) || MaintenanceRun < endRun)) - { - runtc = Util.EnvironmentTickCount(); - ++MaintenanceRun; - - // m_log.DebugFormat("[SCENE]: Maintenance run {0} in {1}", MaintenanceRun, Name); - - // Coarse locations relate to positions of green dots on the mini-map (on a SecondLife client) - if (MaintenanceRun % (m_update_coarse_locations / 10) == 0) - { - SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); - // Send coarse locations to clients - ForEachScenePresence(delegate(ScenePresence presence) - { - presence.SendCoarseLocations(coarseLocations, avatarUUIDs); - }); - } - - if (SendPeriodicAppearanceUpdates && MaintenanceRun % 60 == 0) - { - // m_log.DebugFormat("[SCENE]: Sending periodic appearance updates"); - - if (AvatarFactory != null) - { - ForEachRootScenePresence(sp => AvatarFactory.SendAppearance(sp.UUID)); - } - } - - // Delete temp-on-rez stuff - if (MaintenanceRun % m_update_temp_cleaning == 0 && !m_cleaningTemps) - { - // m_log.DebugFormat("[SCENE]: Running temp-on-rez cleaning in {0}", Name); - tmpMS = Util.EnvironmentTickCount(); - m_cleaningTemps = true; - - WorkManager.RunInThread( - delegate { CleanTempObjects(); m_cleaningTemps = false; }, - null, - string.Format("CleanTempObjects ({0})", Name)); - - tempOnRezMS = Util.EnvironmentTickCountSubtract(tmpMS); - } - - Watchdog.UpdateThread(); - - previousMaintenanceTick = m_lastMaintenanceTick; - m_lastMaintenanceTick = Util.EnvironmentTickCount(); - runtc = Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, runtc); - runtc = (int)(MinMaintenanceTime * 1000) - runtc; - - if (runtc > 0) - m_maintenanceWaitEvent.WaitOne(runtc); - - // Optionally warn if a frame takes double the amount of time that it should. - if (DebugUpdates - && Util.EnvironmentTickCountSubtract( - m_lastMaintenanceTick, previousMaintenanceTick) > (int)(MinMaintenanceTime * 1000 * 2)) - m_log.WarnFormat( - "[SCENE]: Maintenance took {0} ms (desired max {1} ms) in {2}", - Util.EnvironmentTickCountSubtract(m_lastMaintenanceTick, previousMaintenanceTick), - MinMaintenanceTime * 1000, - RegionInfo.RegionName); - } - } - public override void Update(int frames) { long? endFrame = null; @@ -1778,9 +1651,28 @@ namespace OpenSim.Region.Framework.Scenes physicsMS2 = (float)(tmpMS2 - tmpMS); tmpMS = tmpMS2; +/* // Apply any pending avatar force input to the avatar's velocity if (Frame % m_update_entitymovement == 0) m_sceneGraph.UpdateScenePresenceMovement(); +*/ + if (Frame % (m_update_coarse_locations) == 0 && !m_sendingCoarseLocations) + { + m_sendingCoarseLocations = true; + WorkManager.RunInThreadPool( + delegate + { + List coarseLocations; + List avatarUUIDs; + SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); + // Send coarse locations to clients + ForEachScenePresence(delegate(ScenePresence presence) + { + presence.SendCoarseLocations(coarseLocations, avatarUUIDs); + }); + m_sendingCoarseLocations = false; + }, null, string.Format("SendCoarseLocations ({0})", Name)); + } // Get the simulation frame time that the avatar force input // took @@ -1824,7 +1716,8 @@ namespace OpenSim.Region.Framework.Scenes if (Frame % m_update_temp_cleaning == 0 && !m_cleaningTemps) { m_cleaningTemps = true; - Util.FireAndForget(delegate { CleanTempObjects(); m_cleaningTemps = false; }); + WorkManager.RunInThreadPool( + delegate { CleanTempObjects(); m_cleaningTemps = false; }, null, string.Format("CleanTempObjects ({0})", Name)); tmpMS2 = Util.GetTimeStampMS(); tempOnRezMS = (float)(tmpMS2 - tmpMS); // bad.. counts the FireAndForget, not CleanTempObjects tmpMS = tmpMS2; @@ -2050,8 +1943,7 @@ namespace OpenSim.Region.Framework.Scenes { if (!m_backingup) { - m_backingup = true; - WorkManager.RunInThread(o => Backup(false), null, string.Format("BackupWaitCallback ({0})", Name)); + WorkManager.RunInThreadPool(o => Backup(false), null, string.Format("BackupWorker ({0})", Name)); } } @@ -2079,38 +1971,58 @@ namespace OpenSim.Region.Framework.Scenes { lock (m_returns) { - EventManager.TriggerOnBackup(SimulationDataService, forced); - m_backingup = false; - - foreach (KeyValuePair ret in m_returns) + if(m_backingup) { - UUID transaction = UUID.Random(); + m_log.WarnFormat("[Scene] Backup of {0} already running. New call skipped", RegionInfo.RegionName); + return; + } - GridInstantMessage msg = new GridInstantMessage(); - msg.fromAgentID = new Guid(UUID.Zero.ToString()); // From server - msg.toAgentID = new Guid(ret.Key.ToString()); - msg.imSessionID = new Guid(transaction.ToString()); - msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); - msg.fromAgentName = "Server"; - msg.dialog = (byte)19; // Object msg - msg.fromGroup = false; - msg.offline = (byte)1; - msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; - msg.Position = Vector3.Zero; - msg.RegionID = RegionInfo.RegionID.Guid; + m_backingup = true; + try + { + EventManager.TriggerOnBackup(SimulationDataService, forced); - // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. - msg.binaryBucket = Util.StringToBytes256("\0"); - if (ret.Value.count > 1) - msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); - else - msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); + if(m_returns.Count == 0) + return; IMessageTransferModule tr = RequestModuleInterface(); - if (tr != null) + if (tr == null) + return; + + uint unixtime = (uint)Util.UnixTimeSinceEpoch(); + uint estateid = RegionInfo.EstateSettings.ParentEstateID; + Guid regionguid = RegionInfo.RegionID.Guid; + + foreach (KeyValuePair ret in m_returns) + { + GridInstantMessage msg = new GridInstantMessage(); + msg.fromAgentID = Guid.Empty; // From server + msg.toAgentID = ret.Key.Guid; + msg.imSessionID = Guid.NewGuid(); + msg.timestamp = unixtime; + msg.fromAgentName = "Server"; + msg.dialog = 19; // Object msg + msg.fromGroup = false; + msg.offline = 1; + msg.ParentEstateID = estateid; + msg.Position = Vector3.Zero; + msg.RegionID = regionguid; + + // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3. + msg.binaryBucket = new Byte[1] {0}; + if (ret.Value.count > 1) + msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); + else + msg.message = string.Format("Your object {0} was returned from {1} in region {2} due to {3}", ret.Value.objectName, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); + tr.SendInstantMessage(msg, delegate(bool success) { }); + } + m_returns.Clear(); + } + finally + { + m_backingup = false; } - m_returns.Clear(); } } @@ -2351,7 +2263,9 @@ namespace OpenSim.Region.Framework.Scenes EventManager.TriggerOnSceneObjectLoaded(group); SceneObjectPart rootPart = group.GetPart(group.UUID); rootPart.Flags &= ~PrimFlags.Scripted; + rootPart.TrimPermissions(); + group.InvalidateDeepEffectivePerms(); // Don't do this here - it will get done later on when sculpt data is loaded. // group.CheckSculptAndLoad(); @@ -2603,8 +2517,8 @@ namespace OpenSim.Region.Framework.Scenes { // Otherwise, use this default creation code; sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - AddNewSceneObject(sceneObject, true); sceneObject.SetGroup(groupID, null); + AddNewSceneObject(sceneObject, true); if (AgentPreferencesService != null) // This will override the brave new full perm world! { @@ -2622,6 +2536,7 @@ namespace OpenSim.Region.Framework.Scenes if (UserManagementModule != null) sceneObject.RootPart.CreatorIdentification = UserManagementModule.GetUserUUI(ownerID); + sceneObject.InvalidateDeepEffectivePerms();; sceneObject.ScheduleGroupForFullUpdate(); return sceneObject; @@ -2768,7 +2683,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup sog = (SceneObjectGroup)e; if (sog != null && !sog.IsAttachment) { - if (!exceptNoCopy || ((sog.GetEffectivePermissions() & (uint)PermissionMask.Copy) != 0)) + if (!exceptNoCopy || ((sog.EffectiveOwnerPerms & (uint)PermissionMask.Copy) != 0)) { DeleteSceneObject((SceneObjectGroup)e, false); } @@ -2782,7 +2697,7 @@ namespace OpenSim.Region.Framework.Scenes } if (toReturn.Count > 0) { - returnObjects(toReturn.ToArray(), UUID.Zero); + returnObjects(toReturn.ToArray(), null); } } @@ -2944,15 +2859,15 @@ namespace OpenSim.Region.Framework.Scenes // Return 'true' if position inside region. public bool PositionIsInCurrentRegion(Vector3 pos) { - bool ret = false; - int xx = (int)Math.Floor(pos.X); - int yy = (int)Math.Floor(pos.Y); - if (xx < 0 || yy < 0) + float t = pos.X; + if (t < 0 || t >= RegionInfo.RegionSizeX) return false; - if (xx < RegionInfo.RegionSizeX && yy < RegionInfo.RegionSizeY ) - ret = true; - return ret; + t = pos.Y; + if (t < 0 || t >= RegionInfo.RegionSizeY) + return false; + + return true; } /// @@ -3603,7 +3518,9 @@ namespace OpenSim.Region.Framework.Scenes /// Group of new object public void DuplicateObject(uint originalPrim, Vector3 offset, uint flags, UUID AgentID, UUID GroupID) { - SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, flags, AgentID, GroupID, Quaternion.Identity); + bool createSelected = (flags & (uint)PrimFlags.CreateSelected) != 0; + SceneObjectGroup copy = SceneGraph.DuplicateObject(originalPrim, offset, AgentID, + GroupID, Quaternion.Identity, createSelected); if (copy != null) EventManager.TriggerObjectAddedToScene(copy); } @@ -3633,6 +3550,8 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart target = GetSceneObjectPart(localID); SceneObjectPart target2 = GetSceneObjectPart(RayTargetObj); + bool createSelected = (dupeFlags & (uint)PrimFlags.CreateSelected) != 0; + if (target != null && target2 != null) { Vector3 direction = Vector3.Normalize(RayEnd - RayStart); @@ -3674,13 +3593,13 @@ namespace OpenSim.Region.Framework.Scenes Quaternion worldRot = target2.GetWorldRotation(); // SceneObjectGroup obj = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); - copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, worldRot); + copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, worldRot, createSelected); //obj.Rotation = worldRot; //obj.UpdateGroupRotationR(worldRot); } else { - copy = m_sceneGraph.DuplicateObject(localID, pos, target.GetEffectiveObjectFlags(), AgentID, GroupID, Quaternion.Identity); + copy = m_sceneGraph.DuplicateObject(localID, pos, AgentID, GroupID, Quaternion.Identity, createSelected); } if (copy != null) @@ -3983,7 +3902,7 @@ namespace OpenSim.Region.Framework.Scenes if (!LoginsEnabled) { - reason = "Logins Disabled"; + reason = "Logins to this region are disabled"; return false; } @@ -4906,16 +4825,34 @@ Label_GroupsDone: public void RequestTeleportLocation(IClientAPI remoteClient, string regionName, Vector3 position, Vector3 lookat, uint teleportFlags) { - GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); + if (EntityTransferModule == null) + { + m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); + return; + } - if (region == null) + ScenePresence sp = GetScenePresence(remoteClient.AgentId); + if (sp == null || sp.IsDeleted || sp.IsInTransit) + return; + + ulong regionHandle = 0; + if(regionName == RegionInfo.RegionName) + regionHandle = RegionInfo.RegionHandle; + else + { + GridRegion region = GridService.GetRegionByName(RegionInfo.ScopeID, regionName); + if (region != null) + regionHandle = region.RegionHandle; + } + + if(regionHandle == 0) { // can't find the region: Tell viewer and abort remoteClient.SendTeleportFailed("The region '" + regionName + "' could not be found."); return; } - RequestTeleportLocation(remoteClient, region.RegionHandle, position, lookat, teleportFlags); + EntityTransferModule.Teleport(sp, regionHandle, position, lookat, teleportFlags); } /// @@ -4929,19 +4866,17 @@ Label_GroupsDone: public void RequestTeleportLocation(IClientAPI remoteClient, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags) { - ScenePresence sp = GetScenePresence(remoteClient.AgentId); - if (sp != null) + if (EntityTransferModule == null) { - if (EntityTransferModule != null) - { - EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); - } - else - { - m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); - sp.ControllingClient.SendTeleportFailed("Unable to perform teleports on this simulator."); - } + m_log.DebugFormat("[SCENE]: Unable to perform teleports: no AgentTransferModule is active"); + return; } + + ScenePresence sp = GetScenePresence(remoteClient.AgentId); + if (sp == null || sp.IsDeleted || sp.IsInTransit) + return; + + EntityTransferModule.Teleport(sp, regionHandle, position, lookAt, teleportFlags); } public bool CrossAgentToNewRegion(ScenePresence agent, bool isFlying) @@ -5077,65 +5012,59 @@ Label_GroupsDone: #endregion #region Script Engine + public bool LSLScriptDanger(SceneObjectPart part, Vector3 pos) + { + + ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); + if (parcel == null) + return true; + + LandData ldata = parcel.LandData; + if (ldata == null) + return true; + + uint landflags = ldata.Flags; + + uint mask = (uint)(ParcelFlags.CreateObjects | ParcelFlags.AllowAPrimitiveEntry); + if((landflags & mask) != mask) + return true; + + if((landflags & (uint)ParcelFlags.AllowOtherScripts) != 0) + return false; + + if(part == null) + return true; + if(part.GroupID == ldata.GroupID && (landflags & (uint)ParcelFlags.AllowGroupScripts) != 0) + return false; + + return true; + } private bool ScriptDanger(SceneObjectPart part, Vector3 pos) { + if (part == null) + return false; + ILandObject parcel = LandChannel.GetLandObject(pos.X, pos.Y); - if (part != null) + if (parcel != null) { - if (parcel != null) - { - if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) - { - return true; - } - else if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) - { - return true; - } - else if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) - && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) - { - return true; - } - else - { - return false; - } - } - else - { + if ((parcel.LandData.Flags & (uint)ParcelFlags.AllowOtherScripts) != 0) + return true; - if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) - { - // The only time parcel != null when an object is inside a region is when - // there is nothing behind the landchannel. IE, no land plugin loaded. - return true; - } - else - { - // The object is outside of this region. Stop piping events to it. - return false; - } - } + if ((part.OwnerID == parcel.LandData.OwnerID) || Permissions.IsGod(part.OwnerID)) + return true; + + if (((parcel.LandData.Flags & (uint)ParcelFlags.AllowGroupScripts) != 0) + && (parcel.LandData.GroupID != UUID.Zero) && (parcel.LandData.GroupID == part.GroupID)) + return true; } else { - return false; + if (pos.X > 0f && pos.X < RegionInfo.RegionSizeX && pos.Y > 0f && pos.Y < RegionInfo.RegionSizeY) + return true; } - } - public bool ScriptDanger(uint localID, Vector3 pos) - { - SceneObjectPart part = GetSceneObjectPart(localID); - if (part != null) - { - return ScriptDanger(part, pos); - } - else - { - return false; - } + return false; } public bool PipeEventsForScript(uint localID) @@ -5405,7 +5334,7 @@ Label_GroupsDone: /// public void ForEachClient(Action action) { - m_clientManager.ForEachSync(action); + m_clientManager.ForEach(action); } public int GetNumberOfClients() @@ -5512,23 +5441,24 @@ Label_GroupsDone: return 0; } - if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 1000) + if ((Util.EnvironmentTickCountSubtract(m_lastFrameTick)) < 2000) { health+=1; flags |= 1; } - if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 1000) + if (Util.EnvironmentTickCountSubtract(m_lastIncoming) < 2000) { health+=1; flags |= 2; } - if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 1000) + if (Util.EnvironmentTickCountSubtract(m_lastOutgoing) < 2000) { health+=1; flags |= 4; } + /* else { int pid = System.Diagnostics.Process.GetCurrentProcess().Id; @@ -5541,6 +5471,7 @@ proc.WaitForExit(); Thread.Sleep(1000); Environment.Exit(1); } + */ if (flags != 7) return health; @@ -6305,6 +6236,32 @@ Environment.Exit(1); public void TimerWatchdog(object sender, ElapsedEventArgs e) { CheckHeartbeat(); + + IEtcdModule etcd = RequestModuleInterface(); + int flags; + string message; + if (etcd != null) + { + int health = GetHealth(out flags, out message); + if (health != m_lastHealth) + { + m_lastHealth = health; + + etcd.Store("Health", health.ToString(), 300000); + etcd.Store("HealthFlags", flags.ToString(), 300000); + } + + int roots = 0; + foreach (ScenePresence sp in GetScenePresences()) + if (!sp.IsChildAgent && !sp.IsNPC) + roots++; + + if (m_lastUsers != roots) + { + m_lastUsers = roots; + etcd.Store("RootAgents", roots.ToString(), 300000); + } + } } /// This method deals with movement when an avatar is automatically moving (but this is distinct from the @@ -6461,5 +6418,21 @@ Environment.Exit(1); m_eventManager.TriggerExtraSettingChanged(this, name, String.Empty); } + + public bool InTeleportTargetsCoolDown(UUID sourceID, UUID targetID, double timeout) + { + lock(TeleportTargetsCoolDown) + { + UUID lastSource = UUID.Zero; + TeleportTargetsCoolDown.TryGetValue(targetID, out lastSource); + if(lastSource == UUID.Zero) + { + TeleportTargetsCoolDown.Add(targetID, sourceID, timeout); + return false; + } + TeleportTargetsCoolDown.AddOrUpdate(targetID, sourceID, timeout); + return lastSource == sourceID; + } + } } } diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index 2f65ce2ae9..61a243dd20 100755 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -343,7 +343,7 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.ForceInventoryPersistence(); sceneObject.HasGroupChanged = true; } - + sceneObject.InvalidateDeepEffectivePerms(); return ret; } @@ -388,19 +388,19 @@ namespace OpenSim.Region.Framework.Scenes public bool AddNewSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, Vector3? pos, Quaternion? rot, Vector3 vel) { - AddNewSceneObject(sceneObject, attachToBackup, false); - if (pos != null) sceneObject.AbsolutePosition = (Vector3)pos; + if (rot != null) + sceneObject.UpdateGroupRotationR((Quaternion)rot); + + AddNewSceneObject(sceneObject, attachToBackup, false); + if (sceneObject.RootPart.Shape.PCode == (byte)PCode.Prim) { sceneObject.ClearPartAttachmentData(); } - if (rot != null) - sceneObject.UpdateGroupRotationR((Quaternion)rot); - PhysicsActor pa = sceneObject.RootPart.PhysActor; if (pa != null && pa.IsPhysical && vel != Vector3.Zero) { @@ -549,6 +549,8 @@ namespace OpenSim.Region.Framework.Scenes // that are part of the Scene Object being removed m_numTotalPrim -= grp.PrimCount; + bool isPh = (grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics; + int nphysparts = 0; // Go through all parts (primitives and meshes) of this Scene Object foreach (SceneObjectPart part in grp.Parts) { @@ -559,10 +561,13 @@ namespace OpenSim.Region.Framework.Scenes m_numMesh--; else m_numPrim--; + + if(isPh && part.PhysicsShapeType != (byte)PhysShapeType.none) + nphysparts++; } - if ((grp.RootPart.Flags & PrimFlags.Physics) == PrimFlags.Physics) - RemovePhysicalPrim(grp.PrimCount); + if (nphysparts > 0 ) + RemovePhysicalPrim(nphysparts); } bool ret = Entities.Remove(uuid); @@ -1358,7 +1363,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup grp = part.ParentGroup; if (grp != null) { - if (m_parentScene.Permissions.CanEditObject(grp.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(grp, remoteClient)) { // These two are exceptions SL makes in the interpretation // of the change flags. Must check them here because otherwise @@ -1379,7 +1384,7 @@ namespace OpenSim.Region.Framework.Scenes if ((data.change & (ObjectChangeType.Position | ObjectChangeType.Rotation)) != 0) { // Are we allowed to move it? - if (m_parentScene.Permissions.CanMoveObject(grp.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(grp, remoteClient)) { // Strip all but move and rotation from request data.change &= (ObjectChangeType.Group | ObjectChangeType.Position | ObjectChangeType.Rotation); @@ -1406,7 +1411,7 @@ namespace OpenSim.Region.Framework.Scenes if (part != null) { - if (m_parentScene.Permissions.CanEditObject(part.ParentGroup.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(part.ParentGroup, remoteClient)) { bool physbuild = false; if (part.ParentGroup.RootPart.PhysActor != null) @@ -1428,7 +1433,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { bool physbuild = false; if (group.RootPart.PhysActor != null) @@ -1474,7 +1479,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateSingleRotation(rot, localID); } @@ -1492,7 +1497,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateSingleRotation(rot, pos, localID); } @@ -1510,7 +1515,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateGroupRotationR(rot); } @@ -1529,7 +1534,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient)) { group.UpdateGroupRotationPR(pos, rot); } @@ -1547,7 +1552,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, remoteClient.AgentId) || group.IsAttachment) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) || group.IsAttachment) { group.UpdateSinglePosition(pos, localID); } @@ -1561,17 +1566,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// public void UpdatePrimGroupPosition(uint localId, Vector3 pos, IClientAPI remoteClient) - { - UpdatePrimGroupPosition(localId, pos, remoteClient.AgentId); - } - - /// - /// Update the position of the given group. - /// - /// - /// - /// - public void UpdatePrimGroupPosition(uint localId, Vector3 pos, UUID updatingAgentId) { SceneObjectGroup group = GetGroupByPrim(localId); @@ -1580,7 +1574,7 @@ namespace OpenSim.Region.Framework.Scenes if (group.IsAttachment || (group.RootPart.Shape.PCode == 9 && group.RootPart.Shape.State != 0)) { // Set the new attachment point data in the object - byte attachmentPoint = group.GetAttachmentPoint(); + byte attachmentPoint = (byte)group.AttachmentPoint; group.UpdateGroupPosition(pos); group.IsAttachment = false; group.AbsolutePosition = group.RootPart.AttachedPos; @@ -1589,8 +1583,8 @@ namespace OpenSim.Region.Framework.Scenes } else { - if (m_parentScene.Permissions.CanMoveObject(group.UUID, updatingAgentId) - && m_parentScene.Permissions.CanObjectEntry(group.UUID, false, pos)) + if (m_parentScene.Permissions.CanMoveObject(group, remoteClient) + && m_parentScene.Permissions.CanObjectEntry(group, false, pos)) { group.UpdateGroupPosition(pos); } @@ -1610,13 +1604,16 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal void UpdatePrimTexture(uint localID, byte[] texture, IClientAPI remoteClient) { - SceneObjectGroup group = GetGroupByPrim(localID); + SceneObjectPart part = GetSceneObjectPart(localID); + if(part == null) + return; - if (group != null) + SceneObjectGroup group = part.ParentGroup; + if (group != null && !group.IsDeleted) { - if (m_parentScene.Permissions.CanEditObject(group.UUID,remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { - group.UpdateTextureEntry(localID, texture); + part.UpdateTextureEntry(texture); } } } @@ -1638,7 +1635,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { // VolumeDetect can't be set via UI and will always be off when a change is made there // now only change volume dtc if phantom off @@ -1652,7 +1649,7 @@ namespace OpenSim.Region.Framework.Scenes else // else turn it off vdtc = false; - group.UpdatePrimFlags(localID, UsePhysics, SetTemporary, SetPhantom, vdtc); + group.UpdateFlags(UsePhysics, SetTemporary, SetPhantom, vdtc); } else { @@ -1667,8 +1664,11 @@ namespace OpenSim.Region.Framework.Scenes if (wantedPhys != group.UsesPhysics && remoteClient != null) { - remoteClient.SendAlertMessage("Object physics canceled because exceeds the limit of " + - m_parentScene.m_linksetPhysCapacity + " physical prims with shape type not set to None"); + if(m_parentScene.m_linksetPhysCapacity != 0) + remoteClient.SendAlertMessage("Object physics cancelled because it exceeds limits for physical prims, either size or number of primswith shape type not set to None"); + else + remoteClient.SendAlertMessage("Object physics cancelled because it exceeds size limits for physical prims"); + group.RootPart.ScheduleFullUpdate(); } } @@ -1685,7 +1685,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { group.SetPartName(Util.CleanString(name), primLocalID); group.HasGroupChanged = true; @@ -1703,7 +1703,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { group.SetPartDescription(Util.CleanString(description), primLocalID); group.HasGroupChanged = true; @@ -1725,7 +1725,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); if (part != null) @@ -1742,7 +1742,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(primLocalID); if (group != null) { - if (m_parentScene.Permissions.CanEditObject(group.UUID, remoteClient.AgentId)) + if (m_parentScene.Permissions.CanEditObject(group, remoteClient)) { SceneObjectPart part = m_parentScene.GetSceneObjectPart(primLocalID); if (part != null) @@ -1996,6 +1996,7 @@ namespace OpenSim.Region.Framework.Scenes { newRoot.TriggerScriptChangedEvent(Changed.LINK); newRoot.ParentGroup.HasGroupChanged = true; + newRoot.ParentGroup.InvalidatePartsLinkMaps(); newRoot.ParentGroup.ScheduleGroupForFullUpdate(); } } @@ -2012,6 +2013,7 @@ namespace OpenSim.Region.Framework.Scenes // from the database. They will be rewritten immediately, // minus the rows for the unlinked child prims. m_parentScene.SimulationDataService.RemoveObject(g.UUID, m_parentScene.RegionInfo.RegionID); + g.InvalidatePartsLinkMaps(); g.TriggerScriptChangedEvent(Changed.LINK); g.HasGroupChanged = true; // Persist g.ScheduleGroupForFullUpdate(); @@ -2025,27 +2027,9 @@ namespace OpenSim.Region.Framework.Scenes protected internal void MakeObjectSearchable(IClientAPI remoteClient, bool IncludeInSearch, uint localID) { - UUID user = remoteClient.AgentId; - UUID objid = UUID.Zero; - SceneObjectPart obj = null; - - EntityBase[] entityList = GetEntities(); - foreach (EntityBase ent in entityList) - { - if (ent is SceneObjectGroup) - { - SceneObjectGroup sog = ent as SceneObjectGroup; - - foreach (SceneObjectPart part in sog.Parts) - { - if (part.LocalId == localID) - { - objid = part.UUID; - obj = part; - } - } - } - } + SceneObjectGroup sog = GetGroupByPrim(localID); + if(sog == null) + return; //Protip: In my day, we didn't call them searchable objects, we called them limited point-to-point joints //aka ObjectFlags.JointWheel = IncludeInSearch @@ -2062,15 +2046,15 @@ namespace OpenSim.Region.Framework.Scenes // libomv will complain about PrimFlags.JointWheel being // deprecated, so we #pragma warning disable 0612 - if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(objid, user)) + if (IncludeInSearch && m_parentScene.Permissions.CanEditObject(sog, remoteClient)) { - obj.ParentGroup.RootPart.AddFlag(PrimFlags.JointWheel); - obj.ParentGroup.HasGroupChanged = true; + sog.RootPart.AddFlag(PrimFlags.JointWheel); + sog.HasGroupChanged = true; } - else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(objid,user)) + else if (!IncludeInSearch && m_parentScene.Permissions.CanMoveObject(sog, remoteClient)) { - obj.ParentGroup.RootPart.RemFlag(PrimFlags.JointWheel); - obj.ParentGroup.HasGroupChanged = true; + sog.RootPart.RemFlag(PrimFlags.JointWheel); + sog.HasGroupChanged = true; } #pragma warning restore 0612 } @@ -2086,7 +2070,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// null if duplication fails, otherwise the duplicated object /// - public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) + public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, UUID AgentID, UUID GroupID, Quaternion rot, bool createSelected) { // m_log.DebugFormat( // "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", @@ -2095,27 +2079,28 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup original = GetGroupByPrim(originalPrimID); if (original != null) { - if (m_parentScene.Permissions.CanDuplicateObject( - original.PrimCount, original.UUID, AgentID, original.AbsolutePosition)) + if (m_parentScene.Permissions.CanDuplicateObject(original, AgentID)) { SceneObjectGroup copy = original.Copy(true); copy.AbsolutePosition = copy.AbsolutePosition + offset; + SceneObjectPart[] parts = copy.Parts; + + m_numTotalPrim += parts.Length; + if (original.OwnerID != AgentID) { - copy.SetOwnerId(AgentID); - copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); - - SceneObjectPart[] partList = copy.Parts; + copy.SetOwner(AgentID, GroupID); if (m_parentScene.Permissions.PropagatePermissions()) { - foreach (SceneObjectPart child in partList) + foreach (SceneObjectPart child in parts) { child.Inventory.ChangeInventoryOwner(AgentID); child.TriggerScriptChangedEvent(Changed.OWNER); child.ApplyNextOwnerPermissions(); } + copy.InvalidateEffectivePerms(); } } @@ -2125,10 +2110,6 @@ namespace OpenSim.Region.Framework.Scenes lock (SceneObjectGroupsByFullID) SceneObjectGroupsByFullID[copy.UUID] = copy; - SceneObjectPart[] parts = copy.Parts; - - m_numTotalPrim += parts.Length; - foreach (SceneObjectPart part in parts) { if (part.GetPrimType() == PrimType.SCULPT) @@ -2144,28 +2125,19 @@ namespace OpenSim.Region.Framework.Scenes // PROBABLE END OF FIXME - // Since we copy from a source group that is in selected - // state, but the copy is shown deselected in the viewer, - // We need to clear the selection flag here, else that - // prim never gets persisted at all. The client doesn't - // think it's selected, so it will never send a deselect... - copy.IsSelected = false; - - m_numPrim += copy.Parts.Length; + copy.IsSelected = createSelected; if (rot != Quaternion.Identity) - { copy.UpdateGroupRotationR(rot); - } - - copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); - copy.HasGroupChanged = true; - copy.ScheduleGroupForFullUpdate(); - copy.ResumeScripts(); // required for physics to update it's position - copy.AbsolutePosition = copy.AbsolutePosition; + copy.ResetChildPrimPhysicsPositions(); + copy.CreateScriptInstances(0, false, m_parentScene.DefaultScriptEngine, 1); + copy.ResumeScripts(); + + copy.HasGroupChanged = true; + copy.ScheduleGroupForFullUpdate(); return copy; } } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index 9f98554ac0..f778367ce6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -111,7 +111,7 @@ namespace OpenSim.Region.Framework.Scenes /// The user inventory item being added. /// The item UUID that should be used by the new item. /// - public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID) + public bool AddInventoryItem(UUID agentID, uint localID, InventoryItemBase item, UUID copyItemID, bool withModRights = true) { // m_log.DebugFormat( // "[PRIM INVENTORY]: Adding inventory item {0} from {1} to part with local ID {2}", @@ -120,69 +120,72 @@ namespace OpenSim.Region.Framework.Scenes UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; SceneObjectPart part = GetPart(localID); - if (part != null) - { - TaskInventoryItem taskItem = new TaskInventoryItem(); - - taskItem.ItemID = newItemId; - taskItem.AssetID = item.AssetID; - taskItem.Name = item.Name; - taskItem.Description = item.Description; - taskItem.OwnerID = part.OwnerID; // Transfer ownership - taskItem.CreatorID = item.CreatorIdAsUuid; - taskItem.Type = item.AssetType; - taskItem.InvType = item.InvType; - - if (agentID != part.OwnerID && m_scene.Permissions.PropagatePermissions()) - { - taskItem.BasePermissions = item.BasePermissions & - item.NextPermissions; - taskItem.CurrentPermissions = item.CurrentPermissions & - item.NextPermissions; - taskItem.EveryonePermissions = item.EveryOnePermissions & - item.NextPermissions; - taskItem.GroupPermissions = item.GroupPermissions & - item.NextPermissions; - taskItem.NextPermissions = item.NextPermissions; - // We're adding this to a prim we don't own. Force - // owner change - taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; - } - else - { - taskItem.BasePermissions = item.BasePermissions; - taskItem.CurrentPermissions = item.CurrentPermissions; - taskItem.EveryonePermissions = item.EveryOnePermissions; - taskItem.GroupPermissions = item.GroupPermissions; - taskItem.NextPermissions = item.NextPermissions; - } - - taskItem.Flags = item.Flags; - -// m_log.DebugFormat( -// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}", -// taskItem.Flags, taskItem.Name, localID, remoteClient.Name); - - // TODO: These are pending addition of those fields to TaskInventoryItem -// taskItem.SalePrice = item.SalePrice; -// taskItem.SaleType = item.SaleType; - taskItem.CreationDate = (uint)item.CreationDate; - - bool addFromAllowedDrop = agentID != part.OwnerID; - - part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop); - - return true; - } - else + if (part == null) { m_log.ErrorFormat( "[PRIM INVENTORY]: " + "Couldn't find prim local ID {0} in group {1}, {2} to add inventory item ID {3}", localID, Name, UUID, newItemId); + return false; } - return false; + TaskInventoryItem taskItem = new TaskInventoryItem(); + + taskItem.ItemID = newItemId; + taskItem.AssetID = item.AssetID; + taskItem.Name = item.Name; + taskItem.Description = item.Description; + taskItem.OwnerID = part.OwnerID; // Transfer ownership + taskItem.CreatorID = item.CreatorIdAsUuid; + taskItem.Type = item.AssetType; + taskItem.InvType = item.InvType; + + if (agentID != part.OwnerID && m_scene.Permissions.PropagatePermissions()) + { + taskItem.BasePermissions = item.BasePermissions & + item.NextPermissions; + taskItem.CurrentPermissions = item.CurrentPermissions & + item.NextPermissions; + taskItem.EveryonePermissions = item.EveryOnePermissions & + item.NextPermissions; + taskItem.GroupPermissions = item.GroupPermissions & + item.NextPermissions; + taskItem.NextPermissions = item.NextPermissions; + // We're adding this to a prim we don't own. Force + // owner change + taskItem.Flags |= (uint)InventoryItemFlags.ObjectSlamPerm; + + } + else + { + taskItem.BasePermissions = item.BasePermissions; + taskItem.CurrentPermissions = item.CurrentPermissions; + taskItem.EveryonePermissions = item.EveryOnePermissions; + taskItem.GroupPermissions = item.GroupPermissions; + taskItem.NextPermissions = item.NextPermissions; + } + + taskItem.Flags = item.Flags; + +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Flags are 0x{0:X} for item {1} added to part {2} by {3}", +// taskItem.Flags, taskItem.Name, localID, remoteClient.Name); + + // TODO: These are pending addition of those fields to TaskInventoryItem +// taskItem.SalePrice = item.SalePrice; +// taskItem.SaleType = item.SaleType; + taskItem.CreationDate = (uint)item.CreationDate; + + bool addFromAllowedDrop; + if(withModRights) + addFromAllowedDrop = false; + else + addFromAllowedDrop = (part.ParentGroup.RootPart.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0; + + part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop); + part.ParentGroup.InvalidateEffectivePerms(); + return true; + } /// @@ -248,30 +251,201 @@ namespace OpenSim.Region.Framework.Scenes return -1; } - public uint GetEffectivePermissions() + // new test code, to place in better place later + private object m_PermissionsLock = new object(); + private bool m_EffectivePermsInvalid = true; + private bool m_DeepEffectivePermsInvalid = true; + + // should called when parts chanced by their contents did not, so we know their cacche is valid + // in case of doubt call InvalidateDeepEffectivePerms(), it only costs a bit more cpu time + public void InvalidateEffectivePerms() { - return GetEffectivePermissions(false); + lock(m_PermissionsLock) + m_EffectivePermsInvalid = true; } - public uint GetEffectivePermissions(bool useBase) + // should called when parts chanced and their contents where accounted for + public void InvalidateDeepEffectivePerms() + { + lock(m_PermissionsLock) + { + m_DeepEffectivePermsInvalid = true; + m_EffectivePermsInvalid = true; + } + } + + private uint m_EffectiveEveryOnePerms; + public uint EffectiveEveryOnePerms + { + get + { + lock(m_PermissionsLock) + { + if(m_EffectivePermsInvalid) + AggregatePerms(); + return m_EffectiveEveryOnePerms; + } + } + } + + private uint m_EffectiveGroupPerms; + public uint EffectiveGroupPerms + { + get + { + lock(m_PermissionsLock) + { + if(m_EffectivePermsInvalid) + AggregatePerms(); + return m_EffectiveGroupPerms; + } + } + } + + private uint m_EffectiveGroupOrEveryOnePerms; + public uint EffectiveGroupOrEveryOnePerms + { + get + { + lock(m_PermissionsLock) + { + if(m_EffectivePermsInvalid) + AggregatePerms(); + return m_EffectiveGroupOrEveryOnePerms; + } + } + } + + private uint m_EffectiveOwnerPerms; + public uint EffectiveOwnerPerms + { + get + { + lock(m_PermissionsLock) + { + if(m_EffectivePermsInvalid) + AggregatePerms(); + return m_EffectiveOwnerPerms; + } + } + } + + public void AggregatePerms() + { + lock(m_PermissionsLock) + { + // aux + const uint allmask = (uint)PermissionMask.AllEffective; + const uint movemodmask = (uint)(PermissionMask.Move | PermissionMask.Modify); + const uint copytransfermast = (uint)(PermissionMask.Copy | PermissionMask.Transfer); + + uint basePerms = (RootPart.BaseMask & allmask) | (uint)PermissionMask.Move; + bool noBaseTransfer = (basePerms & (uint)PermissionMask.Transfer) == 0; + + uint rootOwnerPerms = RootPart.OwnerMask; + uint owner = rootOwnerPerms; + uint rootGroupPerms = RootPart.GroupMask; + uint group = rootGroupPerms; + uint rootEveryonePerms = RootPart.EveryoneMask; + uint everyone = rootEveryonePerms; + + bool needUpdate = false; + // date is time of writing april 30th 2017 + bool newobj = (RootPart.CreationDate == 0 || RootPart.CreationDate > 1493574994); + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + SceneObjectPart part = parts[i]; + + if(m_DeepEffectivePermsInvalid) + part.AggregateInnerPerms(); + + owner &= part.AggregatedInnerOwnerPerms; + group &= part.AggregatedInnerGroupPerms; + if(newobj) + group &= part.AggregatedInnerGroupPerms; + if(newobj) + everyone &= part.AggregatedInnerEveryonePerms; + } + // recover modify and move + rootOwnerPerms &= movemodmask; + owner |= rootOwnerPerms; + if((owner & copytransfermast) == 0) + owner |= (uint)PermissionMask.Transfer; + + owner &= basePerms; + if(owner != m_EffectiveOwnerPerms) + { + needUpdate = true; + m_EffectiveOwnerPerms = owner; + } + + uint ownertransfermask = owner & (uint)PermissionMask.Transfer; + + // recover modify and move + rootGroupPerms &= movemodmask; + group |= rootGroupPerms; + if(noBaseTransfer) + group &=~(uint)PermissionMask.Copy; + else + group |= ownertransfermask; + + uint groupOrEveryone = group; + uint tmpPerms = group & owner; + if(tmpPerms != m_EffectiveGroupPerms) + { + needUpdate = true; + m_EffectiveGroupPerms = tmpPerms; + } + + // recover move + rootEveryonePerms &= (uint)PermissionMask.Move; + everyone |= rootEveryonePerms; + everyone &= ~(uint)PermissionMask.Modify; + if(noBaseTransfer) + everyone &=~(uint)PermissionMask.Copy; + else + everyone |= ownertransfermask; + + groupOrEveryone |= everyone; + + tmpPerms = everyone & owner; + if(tmpPerms != m_EffectiveEveryOnePerms) + { + needUpdate = true; + m_EffectiveEveryOnePerms = tmpPerms; + } + + tmpPerms = groupOrEveryone & owner; + if(tmpPerms != m_EffectiveGroupOrEveryOnePerms) + { + needUpdate = true; + m_EffectiveGroupOrEveryOnePerms = tmpPerms; + } + + m_DeepEffectivePermsInvalid = false; + m_EffectivePermsInvalid = false; + + if(needUpdate) + RootPart.ScheduleFullUpdate(); + } + } + + public uint CurrentAndFoldedNextPermissions() { uint perms=(uint)(PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Move | - PermissionMask.Transfer) | 7; + PermissionMask.Transfer | + PermissionMask.FoldedMask); - uint ownerMask = 0x7fffffff; + uint ownerMask = RootPart.OwnerMask; SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) { SceneObjectPart part = parts[i]; - - if (useBase) - ownerMask &= part.BaseMask; - else - ownerMask &= part.OwnerMask; - + ownerMask &= part.BaseMask; perms &= part.Inventory.MaskEffectivePermissions(); } @@ -281,17 +455,8 @@ namespace OpenSim.Region.Framework.Scenes perms &= ~(uint)PermissionMask.Copy; if ((ownerMask & (uint)PermissionMask.Transfer) == 0) perms &= ~(uint)PermissionMask.Transfer; - - // If root prim permissions are applied here, this would screw - // with in-inventory manipulation of the next owner perms - // in a major way. So, let's move this to the give itself. - // Yes. I know. Evil. -// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0) -// perms &= ~((uint)PermissionMask.Modify >> 13); -// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0) -// perms &= ~((uint)PermissionMask.Copy >> 13); -// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0) -// perms &= ~((uint)PermissionMask.Transfer >> 13); + if ((ownerMask & (uint)PermissionMask.Export) == 0) + perms &= ~(uint)PermissionMask.Export; return perms; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 5928764a24..53b7ced25b 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -117,9 +117,6 @@ namespace OpenSim.Region.Framework.Scenes NOT_STATUS_ROTATE_Z = 0xF7 } - // This flag has the same purpose as InventoryItemFlags.ObjectSlamPerm - public static readonly uint SLAM = 16; - // private PrimCountTaintedDelegate handlerPrimCountTainted = null; /// @@ -156,7 +153,7 @@ namespace OpenSim.Region.Framework.Scenes timeLastChanged = DateTime.UtcNow.Ticks; if (!m_hasGroupChanged) timeFirstChanged = DateTime.UtcNow.Ticks; - if (m_rootPart != null && m_rootPart.UUID != null && m_scene != null) + if (m_rootPart != null && m_scene != null) { /* if (m_rand == null) @@ -379,6 +376,8 @@ namespace OpenSim.Region.Framework.Scenes public bool m_dupeInProgress = false; internal Dictionary m_savedScriptState; + public UUID MonitoringObject { get; set; } + #region Properties /// @@ -539,7 +538,7 @@ namespace OpenSim.Region.Framework.Scenes public bool inTransit = false; - public delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos); + private delegate SceneObjectGroup SOGCrossDelegate(SceneObjectGroup sog,Vector3 pos, TeleportObjectData tpData); /// /// The absolute position of this scene object in the scene @@ -561,7 +560,7 @@ namespace OpenSim.Region.Framework.Scenes { inTransit = true; SOGCrossDelegate d = CrossAsync; - d.BeginInvoke(this, val, CrossAsyncCompleted, d); + d.BeginInvoke(this, val, null, CrossAsyncCompleted, d); } return; } @@ -602,7 +601,6 @@ namespace OpenSim.Region.Framework.Scenes av.sitSOGmoved(); } - // now that position is changed tell it to scripts if (triggerScriptEvent) { @@ -618,64 +616,78 @@ namespace OpenSim.Region.Framework.Scenes } } - public SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val) + private SceneObjectGroup CrossAsync(SceneObjectGroup sog, Vector3 val, TeleportObjectData tpdata) { Scene sogScene = sog.m_scene; + SceneObjectPart root = sog.RootPart; + + bool isTeleport = tpdata != null; + + if(!isTeleport) + { + if (root.DIE_AT_EDGE) + { + try + { + sogScene.DeleteSceneObject(sog, false); + } + catch (Exception) + { + m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); + } + return sog; + } + + if (root.RETURN_AT_EDGE) + { + // We remove the object here + try + { + List localIDs = new List(); + localIDs.Add(root.LocalId); + sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition, + "Returned at region cross"); + sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero, false); + } + catch (Exception) + { + m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); + } + return sog; + } + } + +// if(!m_scene.IsRunning) +// return sog; + + if (root.KeyframeMotion != null) + root.KeyframeMotion.StartCrossingCheck(); + + if(root.PhysActor != null) + root.PhysActor.CrossingStart(); + IEntityTransferModule entityTransfer = sogScene.RequestModuleInterface(); - Vector3 newpos = Vector3.Zero; - OpenSim.Services.Interfaces.GridRegion destination = null; - - if (sog.RootPart.DIE_AT_EDGE) - { - try - { - sogScene.DeleteSceneObject(sog, false); - } - catch (Exception) - { - m_log.Warn("[SCENE]: exception when trying to remove the prim that crossed the border."); - } - return sog; - } - - if (sog.RootPart.RETURN_AT_EDGE) - { - // We remove the object here - try - { - List localIDs = new List(); - localIDs.Add(sog.RootPart.LocalId); - sogScene.AddReturn(sog.OwnerID, sog.Name, sog.AbsolutePosition, - "Returned at region cross"); - sogScene.DeRezObjects(null, localIDs, UUID.Zero, DeRezAction.Return, UUID.Zero); - } - catch (Exception) - { - m_log.Warn("[SCENE]: exception when trying to return the prim that crossed the border."); - } - return sog; - } - - if (sog.m_rootPart.KeyframeMotion != null) - sog.m_rootPart.KeyframeMotion.StartCrossingCheck(); - if (entityTransfer == null) return sog; + Vector3 newpos = Vector3.Zero; + OpenSim.Services.Interfaces.GridRegion destination = null; + destination = entityTransfer.GetObjectDestination(sog, val, out newpos); if (destination == null) return sog; if (sog.m_sittingAvatars.Count == 0) { - entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true, true); + entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, !isTeleport, true); return sog; } string reason = String.Empty; EntityTransferContext ctx = new EntityTransferContext(); + Vector3 curPos = root.GroupPosition; foreach (ScenePresence av in sog.m_sittingAvatars) { // We need to cross these agents. First, let's find @@ -686,10 +698,15 @@ namespace OpenSim.Region.Framework.Scenes // We set the avatar position as being the object // position to get the region to send to - if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, ctx, out reason)) - { + if(av.IsNPC) + continue; + + if(av.IsInTransit) return sog; - } + + if(!entityTransfer.checkAgentAccessToRegion(av, destination, newpos, ctx, out reason)) + return sog; + m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); } @@ -697,8 +714,10 @@ namespace OpenSim.Region.Framework.Scenes // be made to stand up List avsToCross = new List(); - - foreach (ScenePresence av in sog.m_sittingAvatars) + List avsToCrossFar = new List(); + ulong destHandle = destination.RegionHandle; + List sittingAvatars = GetSittingAvatars(); + foreach (ScenePresence av in sittingAvatars) { byte cflags = 1; @@ -712,68 +731,176 @@ namespace OpenSim.Region.Framework.Scenes else cflags = 3; } + if(!av.knowsNeighbourRegion(destHandle)) + cflags |= 8; // 1 is crossing // 2 is sitting // 4 is sitting at sittarget - av.crossingFlags = cflags; + // 8 far crossing avinfo.av = av; avinfo.ParentID = av.ParentID; avsToCross.Add(avinfo); + if(!av.knowsNeighbourRegion(destHandle)) + { + cflags |= 8; + avsToCrossFar.Add(av); + } + + if(av.IsNPC) + av.crossingFlags = 0; + else + av.crossingFlags = cflags; + av.PrevSitOffset = av.OffsetPosition; av.ParentID = 0; } + Vector3 vel = root.Velocity; + Vector3 avel = root.AngularVelocity; + Vector3 acc = root.Acceleration; + Quaternion ori = root.RotationOffset; + + if(isTeleport) + { + root.Stop(); + sogScene.ForEachScenePresence(delegate(ScenePresence av) + { + av.ControllingClient.SendEntityUpdate(root,PrimUpdateFlags.SendInTransit); + av.ControllingClient.SendEntityTerseUpdateImmediate(root); + }); + + root.Velocity = tpdata.vel; + root.AngularVelocity = tpdata.avel; + root.Acceleration = tpdata.acc; + root.RotationOffset = tpdata.ori; + } + if (entityTransfer.CrossPrimGroupIntoNewRegion(destination, newpos, sog, true, false)) { + if(isTeleport) + { + sogScene.ForEachScenePresence(delegate(ScenePresence oav) + { + if(sittingAvatars.Contains(oav)) + return; + if(oav.knowsNeighbourRegion(destHandle)) + return; + oav.ControllingClient.SendEntityUpdate(root, PrimUpdateFlags.Kill); + foreach (ScenePresence sav in sittingAvatars) + { + sav.SendKillTo(oav); + } + }); + } + bool crossedfar = false; + foreach (ScenePresence av in avsToCrossFar) + { + if(entityTransfer.CrossAgentCreateFarChild(av,destination, newpos, ctx)) + crossedfar = true; + else + av.crossingFlags = 0; + } + + if(crossedfar) + Thread.Sleep(1000); + foreach (avtocrossInfo avinfo in avsToCross) { ScenePresence av = avinfo.av; - if (!av.IsInTransit) // just in case... + av.IsInLocalTransit = true; + av.IsInTransit = true; + m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); + + if(av.crossingFlags > 0) + entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, false, ctx); + + if (av.IsChildAgent) { - m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar {0} to {1}", av.Name, val); - - av.IsInTransit = true; - -// CrossAgentToNewRegionDelegate d = entityTransfer.CrossAgentToNewRegionAsync; -// d.BeginInvoke(av, val, destination, av.Flying, version, CrossAgentToNewRegionCompleted, d); - entityTransfer.CrossAgentToNewRegionAsync(av, newpos, destination, av.Flying, ctx); - if (av.IsChildAgent) + // avatar crossed do some extra cleanup + if (av.ParentUUID != UUID.Zero) { - // avatar crossed do some extra cleanup - if (av.ParentUUID != UUID.Zero) - { - av.ClearControls(); - av.ParentPart = null; - } + av.ClearControls(); + av.ParentPart = null; } - else - { - // avatar cross failed we need do dedicated standUp - // part of it was done at CrossAgentToNewRegionAsync - // so for now just remove the sog controls - // this may need extra care - av.UnRegisterSeatControls(sog.UUID); - } - av.ParentUUID = UUID.Zero; + av.ParentPart = null; // In any case av.IsInTransit = false; av.crossingFlags = 0; m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", av.Firstname, av.Lastname); } else - m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar already in transit {0} to {1}", av.Name, val); + { + // avatar cross failed we need do dedicated standUp + // part of it was done at CrossAgentToNewRegionAsync + // so for now just remove the sog controls + // this may need extra care + av.UnRegisterSeatControls(sog.UUID); + av.ParentUUID = UUID.Zero; + av.ParentPart = null; + Vector3 oldp = curPos; + oldp.X = Util.Clamp(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); + oldp.Y = Util.Clamp(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); + av.AbsolutePosition = oldp; + av.crossingFlags = 0; + av.sitAnimation = "SIT"; + av.IsInTransit = false; + if(av.Animator!= null) + av.Animator.SetMovementAnimations("STAND"); + av.AddToPhysicalScene(false); + sogScene.ForEachScenePresence(delegate(ScenePresence oav) + { + if(sittingAvatars.Contains(oav)) + return; + if(oav.knowsNeighbourRegion(destHandle)) + av.SendAvatarDataToAgent(oav); + else + { + av.SendAvatarDataToAgent(oav); + av.SendAppearanceToAgent(oav); + if (av.Animator != null) + av.Animator.SendAnimPackToClient(oav.ControllingClient); + av.SendAttachmentsToAgentNF(oav); // not ok + } + }); + m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} failed.", av.Firstname, av.Lastname); + } } + + if(crossedfar) + { + Thread.Sleep(10000); + foreach (ScenePresence av in avsToCrossFar) + { + if(av.IsChildAgent) + { + av.Scene.CloseAgent(av.UUID, false); + } + else + av.RemoveNeighbourRegion(destHandle); + } + } + avsToCrossFar.Clear(); avsToCross.Clear(); sog.RemoveScriptInstances(true); sog.Clear(); return sog; } - else // cross failed, put avas back ?? + else { + if(isTeleport) + { + if((tpdata.flags & OSTPOBJ_STOPONFAIL) == 0) + { + root.Velocity = vel; + root.AngularVelocity = avel; + root.Acceleration = acc; + } + root.RotationOffset = ori; + } foreach (avtocrossInfo avinfo in avsToCross) { ScenePresence av = avinfo.av; @@ -783,7 +910,6 @@ namespace OpenSim.Region.Framework.Scenes } } avsToCross.Clear(); - return sog; } @@ -795,11 +921,14 @@ namespace OpenSim.Region.Framework.Scenes if (!sog.IsDeleted) { SceneObjectPart rootp = sog.m_rootPart; + Vector3 oldp = rootp.GroupPosition; oldp.X = Util.Clamp(oldp.X, 0.5f, sog.m_scene.RegionInfo.RegionSizeX - 0.5f); oldp.Y = Util.Clamp(oldp.Y, 0.5f, sog.m_scene.RegionInfo.RegionSizeY - 0.5f); rootp.GroupPosition = oldp; + rootp.Stop(); + SceneObjectPart[] parts = sog.m_parts.GetArray(); foreach (SceneObjectPart part in parts) @@ -813,47 +942,150 @@ namespace OpenSim.Region.Framework.Scenes av.sitSOGmoved(); } - sog.Velocity = Vector3.Zero; - if (sog.m_rootPart.KeyframeMotion != null) sog.m_rootPart.KeyframeMotion.CrossingFailure(); if (sog.RootPart.PhysActor != null) - { sog.RootPart.PhysActor.CrossingFailure(); - } sog.inTransit = false; + AttachToBackup(); sog.ScheduleGroupForFullUpdate(); } } -/* outdated - private void CrossAgentToNewRegionCompleted(ScenePresence agent) + private class TeleportObjectData { - //// If the cross was successful, this agent is a child agent - if (agent.IsChildAgent) + public int flags; + public Vector3 vel; + public Vector3 avel; + public Vector3 acc; + public Quaternion ori; + public UUID sourceID; + } + + // copy from LSL_constants.cs + const int OSTPOBJ_STOPATTARGET = 0x1; // stops at destination + const int OSTPOBJ_STOPONFAIL = 0x2; // stops at start if tp fails + const int OSTPOBJ_SETROT = 0x4; // the rotation is the final rotation, otherwise is a added rotation + + public int TeleportObject(UUID sourceID, Vector3 targetPosition, Quaternion rotation, int flags) + { + if(inTransit || IsDeleted || IsAttachmentCheckFull() || IsSelected || Scene == null) + return -1; + + inTransit = true; + + PhysicsActor pa = RootPart.PhysActor; + if(pa == null || RootPart.KeyframeMotion != null /*|| m_sittingAvatars.Count == 0*/) { - if (agent.ParentUUID != UUID.Zero) - { - agent.HandleForceReleaseControls(agent.ControllingClient,agent.UUID); - agent.ParentPart = null; -// agent.ParentPosition = Vector3.Zero; -// agent.ParentUUID = UUID.Zero; - } + inTransit = false; + return -1; } - agent.ParentUUID = UUID.Zero; -// agent.Reset(); -// else // Not successful -// agent.RestoreInCurrentScene(); + bool stop = (flags & OSTPOBJ_STOPATTARGET) != 0; + bool setrot = (flags & OSTPOBJ_SETROT) != 0; - // In any case - agent.IsInTransit = false; + rotation.Normalize(); + + Quaternion currentRot = RootPart.RotationOffset; + if(setrot) + rotation = Quaternion.Conjugate(currentRot) * rotation; - m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); + bool dorot = setrot | (Math.Abs(rotation.W) < 0.99999); + + Vector3 vel = Vector3.Zero; + Vector3 avel = Vector3.Zero; + Vector3 acc = Vector3.Zero; + + if(!stop) + { + vel = RootPart.Velocity; + avel = RootPart.AngularVelocity; + acc = RootPart.Acceleration; + } + Quaternion ori = RootPart.RotationOffset; + + if(dorot) + { + if(!stop) + { + vel *= rotation; + avel *= rotation; + acc *= rotation; + } + ori *= rotation; + } + + if(Scene.PositionIsInCurrentRegion(targetPosition)) + { + if(Scene.InTeleportTargetsCoolDown(UUID, sourceID, 1.0)) + { + inTransit = false; + return -2; + } + + Vector3 curPos = AbsolutePosition; + ILandObject curLand = Scene.LandChannel.GetLandObject(curPos.X, curPos.Y); + float posX = targetPosition.X; + float posY = targetPosition.Y; + ILandObject land = Scene.LandChannel.GetLandObject(posX, posY); + if(land != null && land != curLand) + { + if(!Scene.Permissions.CanObjectEnterWithScripts(this, land)) + { + inTransit = false; + return -3; + } + + UUID agentID; + foreach (ScenePresence av in m_sittingAvatars) + { + agentID = av.UUID; + if(land.IsRestrictedFromLand(agentID) || land.IsBannedFromLand(agentID)) + { + inTransit = false; + return -4; + } + } + } + + RootPart.Velocity = vel; + RootPart.AngularVelocity = avel; + RootPart.Acceleration = acc; + RootPart.RotationOffset = ori; + + Vector3 s = RootPart.Scale * RootPart.RotationOffset; + float h = Scene.GetGroundHeight(posX, posY) + 0.5f * (float)Math.Abs(s.Z) + 0.01f; + if(targetPosition.Z < h) + targetPosition.Z = h; + + inTransit = false; + AbsolutePosition = targetPosition; + RootPart.ScheduleTerseUpdate(); + return 1; + } + + if(Scene.InTeleportTargetsCoolDown(UUID, sourceID, 20.0)) + { + inTransit = false; + return -1; + } + + TeleportObjectData tdata = new TeleportObjectData(); + tdata.flags = flags; + tdata.vel = vel; + tdata.avel = avel; + tdata.acc = acc; + tdata.ori = ori; + tdata.sourceID = sourceID; + + + SOGCrossDelegate d = CrossAsync; + d.BeginInvoke(this, targetPosition, tdata, CrossAsyncCompleted, d); + return 0; } -*/ + public override Vector3 Velocity { get { return RootPart.Velocity; } @@ -1030,6 +1262,8 @@ namespace OpenSim.Region.Framework.Scenes set { m_LoopSoundSlavePrims = value; } } + private double m_lastCollisionSoundMS; + /// /// The UUID for the region this object is in. /// @@ -1107,7 +1341,7 @@ namespace OpenSim.Region.Framework.Scenes /// public SceneObjectGroup() { - + m_lastCollisionSoundMS = Util.GetTimeStampMS() + 1000.0; } /// @@ -1786,63 +2020,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Attach this scene object to the given avatar. - /// - /// - /// - /// - private void AttachToAgent( - ScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) - { - if (avatar != null) - { - // don't attach attachments to child agents - if (avatar.IsChildAgent) return; - - // Remove from database and parcel prim count - m_scene.DeleteFromStorage(so.UUID); - m_scene.EventManager.TriggerParcelPrimCountTainted(); - - so.AttachedAvatar = avatar.UUID; - - if (so.RootPart.PhysActor != null) - { - m_scene.PhysicsScene.RemovePrim(so.RootPart.PhysActor); - so.RootPart.PhysActor = null; - } - - so.AbsolutePosition = attachOffset; - so.RootPart.AttachedPos = attachOffset; - so.IsAttachment = true; - so.RootPart.SetParentLocalId(avatar.LocalId); - so.AttachmentPoint = attachmentpoint; - - avatar.AddAttachment(this); - - if (!silent) - { - // Killing it here will cause the client to deselect it - // It then reappears on the avatar, deselected - // through the full update below - // - if (IsSelected) - { - m_scene.SendKillObject(new List { m_rootPart.LocalId }); - } - - IsSelected = false; // fudge.... - ScheduleGroupForFullUpdate(); - } - } - else - { - m_log.WarnFormat( - "[SOG]: Tried to add attachment {0} to avatar with UUID {1} in region {2} but the avatar is not present", - UUID, avatar.ControllingClient.AgentId, Scene.RegionInfo.RegionName); - } - } - public byte GetAttachmentPoint() { return m_rootPart.Shape.State; @@ -1957,6 +2134,7 @@ namespace OpenSim.Region.Framework.Scenes if (part.LinkNum == 2) RootPart.LinkNum = 1; + InvalidatePartsLinkMaps(); } /// @@ -2233,7 +2411,8 @@ namespace OpenSim.Region.Framework.Scenes { if (part.OwnerID != userId) { - part.LastOwnerID = part.OwnerID; + if(part.GroupID != part.OwnerID) + part.LastOwnerID = part.OwnerID; part.OwnerID = userId; } }); @@ -2313,7 +2492,7 @@ namespace OpenSim.Region.Framework.Scenes RootPart.UUID); m_scene.AddReturn(OwnerID == GroupID ? LastOwnerID : OwnerID, Name, AbsolutePosition, "parcel autoreturn"); m_scene.DeRezObjects(null, new List() { RootPart.LocalId }, UUID.Zero, - DeRezAction.Return, UUID.Zero); + DeRezAction.Return, UUID.Zero, false); return; } @@ -2443,17 +2622,16 @@ namespace OpenSim.Region.Framework.Scenes dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; - if (userExposed) dupe.m_rootPart.TrimPermissions(); List partList = new List(m_parts.GetArray()); partList.Sort(delegate(SceneObjectPart p1, SceneObjectPart p2) - { - return p1.LinkNum.CompareTo(p2.LinkNum); - } - ); + { + return p1.LinkNum.CompareTo(p2.LinkNum); + } + ); foreach (SceneObjectPart part in partList) { @@ -2505,12 +2683,15 @@ namespace OpenSim.Region.Framework.Scenes if (dupe.m_rootPart.PhysActor != null) dupe.m_rootPart.PhysActor.Building = false; // tell physics to finish building + dupe.InvalidateDeepEffectivePerms(); + dupe.HasGroupChanged = true; dupe.AttachToBackup(); - ScheduleGroupForFullUpdate(); + dupe.ScheduleGroupForFullUpdate(); } + dupe.InvalidatePartsLinkMaps(); m_dupeInProgress = false; return dupe; } @@ -2540,35 +2721,22 @@ namespace OpenSim.Region.Framework.Scenes RootPart.KeyframeMotion.Stop(); RootPart.KeyframeMotion = null; } - UpdatePrimFlags(RootPart.LocalId, usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); + UpdateFlags(usePhysics, IsTemporary, IsPhantom, IsVolumeDetect); } public void ScriptSetTemporaryStatus(bool makeTemporary) { - UpdatePrimFlags(RootPart.LocalId, UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect); + UpdateFlags(UsesPhysics, makeTemporary, IsPhantom, IsVolumeDetect); } public void ScriptSetPhantomStatus(bool makePhantom) { - UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect); + UpdateFlags(UsesPhysics, IsTemporary, makePhantom, IsVolumeDetect); } public void ScriptSetVolumeDetect(bool makeVolumeDetect) { - UpdatePrimFlags(RootPart.LocalId, UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect); - - /* - ScriptSetPhantomStatus(false); // What ever it was before, now it's not phantom anymore - - if (PhysActor != null) // Should always be the case now - { - PhysActor.SetVolumeDetect(param); - } - if (param != 0) - AddFlag(PrimFlags.Phantom); - - ScheduleFullUpdate(); - */ + UpdateFlags(UsesPhysics, IsTemporary, IsPhantom, makeVolumeDetect); } public void applyImpulse(Vector3 impulse) @@ -2746,25 +2914,33 @@ namespace OpenSim.Region.Framework.Scenes } /// - /// Set the owner of the root part. + /// Set the owner of all linkset. /// - /// /// /// - public void SetRootPartOwner(SceneObjectPart part, UUID cAgentID, UUID cGroupID) + public void SetOwner(UUID cAgentID, UUID cGroupID) { - part.LastOwnerID = part.OwnerID; - part.OwnerID = cAgentID; - part.GroupID = cGroupID; + SceneObjectPart rpart = RootPart; + UUID oldowner = rpart.OwnerID; + ForEachPart(delegate(SceneObjectPart part) + { + if(part.GroupID != part.OwnerID) + part.LastOwnerID = part.OwnerID; + part.OwnerID = cAgentID; + part.GroupID = cGroupID; + }); - if (part.OwnerID != cAgentID) + if (oldowner != cAgentID) { // Apply Next Owner Permissions if we're not bypassing permissions if (!m_scene.Permissions.BypassPermissions()) + { ApplyNextOwnerPermissions(); + InvalidateEffectivePerms(); + } } - part.ScheduleFullUpdate(); + rpart.ScheduleFullUpdate(); } /// @@ -2845,12 +3021,13 @@ namespace OpenSim.Region.Framework.Scenes // If we somehow got here to updating the SOG and its root part is not scheduled for update, // check to see if the physical position or rotation warrant an update. +/* if (m_rootPart.UpdateFlag == UpdateRequired.NONE) { // rootpart SendScheduledUpdates will check if a update is needed m_rootPart.UpdateFlag = UpdateRequired.TERSE; } - +*/ if (IsAttachment) { ScenePresence sp = m_scene.GetScenePresence(AttachedAvatar); @@ -3264,6 +3441,7 @@ namespace OpenSim.Region.Framework.Scenes ResetChildPrimPhysicsPositions(); InvalidBoundsRadius(); + InvalidatePartsLinkMaps(); if (m_rootPart.PhysActor != null) m_rootPart.PhysActor.Building = false; @@ -3420,6 +3598,8 @@ namespace OpenSim.Region.Framework.Scenes objectGroup.HasGroupChangedDueToDelink = true; InvalidBoundsRadius(); + InvalidatePartsLinkMaps(); + objectGroup.InvalidateEffectivePerms(); if (sendEvents) linkPart.TriggerScriptChangedEvent(Changed.LINK); @@ -3842,84 +4022,80 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) + public void UpdateFlags(bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) { + if (m_scene == null || IsDeleted) + return; + HasGroupChanged = true; - SceneObjectPart selectionPart = GetPart(localID); - - if (Scene != null) + if (SetTemporary) { - if (SetTemporary) - { - DetachFromBackup(); - // Remove from database and parcel prim count - // - m_scene.DeleteFromStorage(UUID); - } - else if (!Backup) - { - // Previously been temporary now switching back so make it - // available for persisting again - AttachToBackup(); - } - - m_scene.EventManager.TriggerParcelPrimCountTainted(); + DetachFromBackup(); + // Remove from database and parcel prim count + // + m_scene.DeleteFromStorage(UUID); + } + else if (!Backup) + { + // Previously been temporary now switching back so make it + // available for persisting again + AttachToBackup(); } - if (selectionPart != null) + + SceneObjectPart[] parts = m_parts.GetArray(); + + if (UsePhysics) { - SceneObjectPart[] parts = m_parts.GetArray(); + int maxprims = m_scene.m_linksetPhysCapacity; + bool checkShape = (maxprims > 0 && + parts.Length > maxprims); - if (Scene != null && UsePhysics) + for (int i = 0; i < parts.Length; i++) { - int maxprims = m_scene.m_linksetPhysCapacity; - bool checkShape = (maxprims > 0 && - parts.Length > maxprims); + SceneObjectPart part = parts[i]; - for (int i = 0; i < parts.Length; i++) + if(part.PhysicsShapeType == (byte)PhysicsShapeType.None) + continue; // assuming root type was checked elsewhere + + if (checkShape) { - SceneObjectPart part = parts[i]; - - if(part.PhysicsShapeType == (byte)PhysicsShapeType.None) - continue; // assuming root type was checked elsewhere - - if (checkShape) + if (--maxprims < 0) { - if (--maxprims < 0) - { - UsePhysics = false; - break; - } - } - - if (part.Scale.X > m_scene.m_maxPhys || - part.Scale.Y > m_scene.m_maxPhys || - part.Scale.Z > m_scene.m_maxPhys ) - { - UsePhysics = false; // Reset physics + UsePhysics = false; break; } } - } - if (parts.Length > 1) - { - m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true); - - for (int i = 0; i < parts.Length; i++) + if (part.Scale.X > m_scene.m_maxPhys || + part.Scale.Y > m_scene.m_maxPhys || + part.Scale.Z > m_scene.m_maxPhys ) { - - if (parts[i].UUID != m_rootPart.UUID) - parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true); + UsePhysics = false; // Reset physics + break; } - - if (m_rootPart.PhysActor != null) - m_rootPart.PhysActor.Building = false; } - else - m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false); } + + if (parts.Length > 1) + { + m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true); + + for (int i = 0; i < parts.Length; i++) + { + + if (parts[i].UUID != m_rootPart.UUID) + parts[i].UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, true); + } + + if (m_rootPart.PhysActor != null) + m_rootPart.PhysActor.Building = false; + } + else + m_rootPart.UpdatePrimFlags(UsePhysics, SetTemporary, SetPhantom, SetVolumeDetect, false); + + m_scene.EventManager.TriggerParcelPrimCountTainted(); } public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data) @@ -3942,24 +4118,10 @@ namespace OpenSim.Region.Framework.Scenes return Parts.Count(); } - /// - /// Update the texture entry for this part - /// - /// - /// - public void UpdateTextureEntry(uint localID, byte[] textureEntry) - { - SceneObjectPart part = GetPart(localID); - if (part != null) - { - part.UpdateTextureEntry(textureEntry); - } - } - public void AdjustChildPrimPermissions(bool forceTaskInventoryPermissive) { - uint newOwnerMask = (uint)(PermissionMask.All | PermissionMask.Export) & 0xfffffff8; // Mask folded bits - uint foldedPerms = RootPart.OwnerMask & 3; + uint newOwnerMask = (uint)(PermissionMask.All | PermissionMask.Export) & 0xfffffff0; // Mask folded bits + uint foldedPerms = RootPart.OwnerMask & (uint)PermissionMask.FoldedMask; ForEachPart(part => { @@ -3970,14 +4132,14 @@ namespace OpenSim.Region.Framework.Scenes part.Inventory.ApplyGodPermissions(part.BaseMask); }); - uint lockMask = ~(uint)(PermissionMask.Move | PermissionMask.Modify); - uint lockBit = RootPart.OwnerMask & (uint)(PermissionMask.Move | PermissionMask.Modify); + uint lockMask = ~(uint)(PermissionMask.Move); + uint lockBit = RootPart.OwnerMask & (uint)(PermissionMask.Move); RootPart.OwnerMask = (RootPart.OwnerMask & lockBit) | ((newOwnerMask | foldedPerms) & lockMask); // m_log.DebugFormat( // "[SCENE OBJECT GROUP]: RootPart.OwnerMask now {0} for {1} in {2}", // (OpenMetaverse.PermissionMask)RootPart.OwnerMask, Name, Scene.Name); - + InvalidateEffectivePerms(); RootPart.ScheduleFullUpdate(); } @@ -4002,6 +4164,7 @@ namespace OpenSim.Region.Framework.Scenes { foreach (SceneObjectPart part in Parts) part.Inventory.ApplyGodPermissions(RootPart.BaseMask); + InvalidateEffectivePerms(); } HasGroupChanged = true; @@ -4647,7 +4810,7 @@ namespace OpenSim.Region.Framework.Scenes } if ((change & ObjectChangeType.Position) != 0) { - if (IsAttachment || m_scene.Permissions.CanObjectEntry(group.UUID, false, data.position)) + if (IsAttachment || m_scene.Permissions.CanObjectEntry(group, false, data.position)) UpdateGroupPosition(data.position); updateType = updatetype.groupterse; } @@ -5056,6 +5219,49 @@ namespace OpenSim.Region.Framework.Scenes return Ptot; } + public void GetInertiaData(out float TotalMass, out Vector3 CenterOfMass, out Vector3 Inertia, out Vector4 aux ) + { + PhysicsActor pa = RootPart.PhysActor; + + if(((RootPart.Flags & PrimFlags.Physics) !=0) && pa !=null) + { + PhysicsInertiaData inertia; + + inertia = pa.GetInertiaData(); + + TotalMass = inertia.TotalMass; + CenterOfMass = inertia.CenterOfMass; + Inertia = inertia.Inertia; + aux = inertia.InertiaRotation; + + return; + } + + TotalMass = GetMass(); + CenterOfMass = GetCenterOfMass() - AbsolutePosition; + CenterOfMass *= Quaternion.Conjugate(RootPart.RotationOffset); + Inertia = Vector3.Zero; + aux = Vector4.Zero; + } + + public void SetInertiaData(float TotalMass, Vector3 CenterOfMass, Vector3 Inertia, Vector4 aux ) + { + PhysicsInertiaData inertia = new PhysicsInertiaData(); + inertia.TotalMass = TotalMass; + inertia.CenterOfMass = CenterOfMass; + inertia.Inertia = Inertia; + inertia.InertiaRotation = aux; + + if(TotalMass < 0) + RootPart.PhysicsInertia = null; + else + RootPart.PhysicsInertia = new PhysicsInertiaData(inertia); + + PhysicsActor pa = RootPart.PhysActor; + if(pa !=null) + pa.SetInertiaData(inertia); + } + /// /// Set the user group to which this scene object belongs. /// @@ -5217,6 +5423,7 @@ namespace OpenSim.Region.Framework.Scenes { part.ResetOwnerChangeFlag(); }); + InvalidateEffectivePerms(); } // clear some references to easy cg @@ -5230,9 +5437,113 @@ namespace OpenSim.Region.Framework.Scenes m_PlaySoundSlavePrims.Clear(); m_LoopSoundMasterPrim = null; m_targets.Clear(); + m_partsNameToLinkMap.Clear(); + } + + private Dictionary m_partsNameToLinkMap = new Dictionary(); + private string GetLinkNumber_lastname; + private int GetLinkNumber_lastnumber; + + // this scales bad but so does GetLinkNumPart + public int GetLinkNumber(string name) + { + if(String.IsNullOrEmpty(name) || name == "Object") + return -1; + + lock(m_partsNameToLinkMap) + { + if(m_partsNameToLinkMap.Count == 0) + { + GetLinkNumber_lastname = String.Empty; + GetLinkNumber_lastnumber = -1; + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + string s = parts[i].Name; + if(String.IsNullOrEmpty(s) || s == "Object" || s == "Primitive") + continue; + + if(m_partsNameToLinkMap.ContainsKey(s)) + { + int ol = parts[i].LinkNum; + if(ol < m_partsNameToLinkMap[s]) + m_partsNameToLinkMap[s] = ol; + } + else + m_partsNameToLinkMap[s] = parts[i].LinkNum; + } + } + + if(name == GetLinkNumber_lastname) + return GetLinkNumber_lastnumber; + + if(m_partsNameToLinkMap.ContainsKey(name)) + { + lock(m_partsNameToLinkMap) + { + GetLinkNumber_lastname = name; + GetLinkNumber_lastnumber = m_partsNameToLinkMap[name]; + return GetLinkNumber_lastnumber; + } + } + } + + if(m_sittingAvatars.Count > 0) + { + int j = m_parts.Count + 1; + + ScenePresence[] avs = m_sittingAvatars.ToArray(); + for (int i = 0; i < avs.Length; i++, j++) + { + if (avs[i].Name == name) + { + GetLinkNumber_lastname = name; + GetLinkNumber_lastnumber = j; + return j; + } + } + } + + return -1; + } + + public void InvalidatePartsLinkMaps() + { + lock(m_partsNameToLinkMap) + { + m_partsNameToLinkMap.Clear(); + GetLinkNumber_lastname = String.Empty; + GetLinkNumber_lastnumber = -1; + } + } + + public bool CollisionSoundThrottled(int collisionSoundType) + { + double time = m_lastCollisionSoundMS; +// m_lastCollisionSoundMS = Util.GetTimeStampMS(); +// time = m_lastCollisionSoundMS - time; + double now = Util.GetTimeStampMS(); + time = now - time; + switch (collisionSoundType) + { + case 0: // default sounds + case 2: // default sounds with volume set by script + if(time < 300.0) + return true; + break; + case 1: // selected sound + if(time < 200.0) + return true; + break; + default: + break; + } + m_lastCollisionSoundMS = now; + return false; } #endregion } + } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index b8ac089826..0370c41723 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -238,17 +238,6 @@ namespace OpenSim.Region.Framework.Scenes /// public bool SoundQueueing { get; set; } - public uint TimeStampFull; - - public uint TimeStampLastActivity; // Will be used for AutoReturn - - public uint TimeStampTerse; - - // The following two are to hold the attachment data - // while an object is inworld - [XmlIgnore] - public byte AttachPoint = 0; - [XmlIgnore] public Quaternion AttachRotation = Quaternion.Identity; @@ -277,7 +266,11 @@ namespace OpenSim.Region.Framework.Scenes public scriptEvents AggregateScriptEvents; - public Vector3 AttachedPos; + public Vector3 AttachedPos + { + get; + set; + } // rotation locks on local X,Y and or Z axis bit flags // bits are as in llSetStatus defined in SceneObjectGroup.axisSelect enum @@ -330,7 +323,8 @@ namespace OpenSim.Region.Framework.Scenes private byte[] m_TextureAnimation; private byte m_clickAction; private Color m_color = Color.Black; - private readonly List m_lastColliders = new List(); + private List m_lastColliders = new List(); + private bool m_lastLandCollide; private int m_linkNum; private int m_scriptAccessPin; @@ -370,9 +364,9 @@ namespace OpenSim.Region.Framework.Scenes protected Vector3 m_lastPosition; protected Quaternion m_lastRotation; protected Vector3 m_lastVelocity; - protected Vector3 m_lastAcceleration; + protected Vector3 m_lastAcceleration; // acceleration is a derived var with high noise protected Vector3 m_lastAngularVelocity; - protected int m_lastUpdateSentTime; + protected double m_lastUpdateSentTime; protected float m_buoyancy = 0.0f; protected Vector3 m_force; protected Vector3 m_torque; @@ -407,6 +401,8 @@ namespace OpenSim.Region.Framework.Scenes private SOPVehicle m_vehicleParams = null; + private PhysicsInertiaData m_physicsInertia; + public KeyframeMotion KeyframeMotion { get; set; @@ -476,8 +472,8 @@ namespace OpenSim.Region.Framework.Scenes APIDActive = false; Flags = 0; CreateSelected = true; - TrimPermissions(); + AggregateInnerPerms(); } #endregion Constructors @@ -637,6 +633,8 @@ namespace OpenSim.Region.Framework.Scenes set { m_name = value; + if(ParentGroup != null) + ParentGroup.InvalidatePartsLinkMaps(); PhysicsActor pa = PhysActor; @@ -806,7 +804,7 @@ namespace OpenSim.Region.Framework.Scenes { // If this is a linkset, we don't want the physics engine mucking up our group position here. PhysicsActor actor = PhysActor; - if (ParentID == 0) + if (_parentID == 0) { if (actor != null) m_groupPosition = actor.Position; @@ -835,7 +833,7 @@ namespace OpenSim.Region.Framework.Scenes try { // Root prim actually goes at Position - if (ParentID == 0) + if (_parentID == 0) { actor.Position = value; } @@ -877,7 +875,7 @@ namespace OpenSim.Region.Framework.Scenes ParentGroup.InvalidBoundsRadius(); PhysicsActor actor = PhysActor; - if (ParentID != 0 && actor != null) + if (_parentID != 0 && actor != null) { actor.Position = GetWorldPosition(); actor.Orientation = GetWorldRotation(); @@ -937,21 +935,8 @@ namespace OpenSim.Region.Framework.Scenes PhysicsActor actor = PhysActor; // If this is a root of a linkset, the real rotation is what the physics engine thinks. // If not a root prim, the offset rotation is computed by SOG and is relative to the root. - if (ParentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) - { - if (actor.Orientation.X != 0f || actor.Orientation.Y != 0f - || actor.Orientation.Z != 0f || actor.Orientation.W != 0f) - { - m_rotationOffset = actor.Orientation; - } - } - -// float roll, pitch, yaw = 0; -// m_rotationOffset.GetEulerAngles(out roll, out pitch, out yaw); -// -// m_log.DebugFormat( -// "[SCENE OBJECT PART]: Got euler {0} for RotationOffset on {1} {2}", -// new Vector3(roll, pitch, yaw), Name, LocalId); + if (_parentID == 0 && (Shape.PCode != 9 || Shape.State == 0) && actor != null) + m_rotationOffset = actor.Orientation; return m_rotationOffset; } @@ -967,7 +952,7 @@ namespace OpenSim.Region.Framework.Scenes try { // Root prim gets value directly - if (ParentID == 0) + if (_parentID == 0) { actor.Orientation = value; //m_log.Info("[PART]: RO1:" + actor.Orientation.ToString()); @@ -1063,7 +1048,7 @@ namespace OpenSim.Region.Framework.Scenes m_angularVelocity = value; PhysicsActor actor = PhysActor; - if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this && VehicleType == (int)Vehicle.TYPE_NONE) + if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this) { actor.RotationalVelocity = m_angularVelocity; } @@ -1089,6 +1074,12 @@ namespace OpenSim.Region.Framework.Scenes m_acceleration = Vector3.Zero; else m_acceleration = value; + + PhysicsActor actor = PhysActor; + if ((actor != null) && actor.IsPhysical && ParentGroup.RootPart == this) + { + actor.Acceleration = m_acceleration; + } } } @@ -1107,8 +1098,8 @@ namespace OpenSim.Region.Framework.Scenes { get { - if (m_text.Length > 255) - return m_text.Substring(0, 254); + if (m_text.Length > 256) // yes > 254 + return m_text.Substring(0, 256); return m_text; } set { m_text = value; } @@ -1222,6 +1213,7 @@ namespace OpenSim.Region.Framework.Scenes } public UpdateRequired UpdateFlag { get; set; } + private object UpdateFlagLock = new object(); /// /// Used for media on a prim. @@ -1262,6 +1254,9 @@ namespace OpenSim.Region.Framework.Scenes { get { + if (_parentID == 0) + return GroupPosition; + return GroupPosition + (m_offsetPosition * ParentGroup.RootPart.RotationOffset); } } @@ -1383,7 +1378,8 @@ namespace OpenSim.Region.Framework.Scenes public UUID LastOwnerID { get { return _lastOwnerID; } - set { _lastOwnerID = value; } + set { + _lastOwnerID = value; } } public UUID RezzerID @@ -1640,8 +1636,10 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.SetMaterial((int)value); } if(ParentGroup != null) + { ParentGroup.HasGroupChanged = true; - ScheduleFullUpdateIfNone(); + ScheduleFullUpdate(); + } } } } @@ -1674,7 +1672,7 @@ namespace OpenSim.Region.Framework.Scenes get { byte pst = PhysicsShapeType; - if(pst == (byte) PhysShapeType.none || pst == (byte) PhysShapeType.convex || HasMesh()) + if(pst == (byte) PhysShapeType.none || HasMesh()) return true; return false; } @@ -1729,7 +1727,12 @@ namespace OpenSim.Region.Framework.Scenes public byte PhysicsShapeType { - get { return m_physicsShapeType; } + get + { +// if (PhysActor != null) +// m_physicsShapeType = PhysActor.PhysicsShapeType; + return m_physicsShapeType; + } set { byte oldv = m_physicsShapeType; @@ -1780,10 +1783,12 @@ namespace OpenSim.Region.Framework.Scenes { m_density = value; - ScheduleFullUpdateIfNone(); if (ParentGroup != null) + { ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); + } PhysicsActor pa = PhysActor; if (pa != null) @@ -1801,10 +1806,11 @@ namespace OpenSim.Region.Framework.Scenes { m_gravitymod = value; - ScheduleFullUpdateIfNone(); - if (ParentGroup != null) + { ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); + } PhysicsActor pa = PhysActor; if (pa != null) @@ -1822,10 +1828,11 @@ namespace OpenSim.Region.Framework.Scenes { m_friction = value; - ScheduleFullUpdateIfNone(); - if (ParentGroup != null) + { ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); + } PhysicsActor pa = PhysActor; if (pa != null) @@ -1843,10 +1850,11 @@ namespace OpenSim.Region.Framework.Scenes { m_bounce = value; - ScheduleFullUpdateIfNone(); - if (ParentGroup != null) + { ParentGroup.HasGroupChanged = true; + ScheduleFullUpdate(); + } PhysicsActor pa = PhysActor; if (pa != null) @@ -1875,7 +1883,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ClearUpdateSchedule() { - UpdateFlag = UpdateRequired.NONE; + lock(UpdateFlagLock) + UpdateFlag = UpdateRequired.NONE; } /// @@ -2013,7 +2022,7 @@ namespace OpenSim.Region.Framework.Scenes // SetVelocity for LSL llSetVelocity.. may need revision if having other uses in future public void SetVelocity(Vector3 pVel, bool localGlobalTF) { - if (ParentGroup == null || ParentGroup.IsDeleted) + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) return; if (ParentGroup.IsAttachment) @@ -2040,7 +2049,7 @@ namespace OpenSim.Region.Framework.Scenes // SetAngularVelocity for LSL llSetAngularVelocity.. may need revision if having other uses in future public void SetAngularVelocity(Vector3 pAngVel, bool localGlobalTF) { - if (ParentGroup == null || ParentGroup.IsDeleted) + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) return; if (ParentGroup.IsAttachment) @@ -2074,6 +2083,9 @@ namespace OpenSim.Region.Framework.Scenes /// true for the local frame, false for the global frame public void ApplyAngularImpulse(Vector3 impulsei, bool localGlobalTF) { + if (ParentGroup == null || ParentGroup.IsDeleted || ParentGroup.inTransit) + return; + Vector3 impulse = impulsei; if (localGlobalTF) @@ -2228,7 +2240,11 @@ namespace OpenSim.Region.Framework.Scenes dupe.LocalId = plocalID; // This may be wrong... it might have to be applied in SceneObjectGroup to the object that's being duplicated. - dupe.LastOwnerID = OwnerID; + if(OwnerID != GroupID) + dupe.LastOwnerID = OwnerID; + else + dupe.LastOwnerID = LastOwnerID; // redundant ? + dupe.RezzerID = RezzerID; byte[] extraP = new byte[Shape.ExtraParams.Length]; @@ -2419,7 +2435,7 @@ namespace OpenSim.Region.Framework.Scenes PhysActor.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; PhysActor.OnOutOfBounds += PhysicsOutOfBounds; - if (ParentID != 0 && ParentID != LocalId) + if (_parentID != 0 && _parentID != LocalId) { PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; @@ -2537,6 +2553,37 @@ namespace OpenSim.Region.Framework.Scenes return (uint)Flags | (uint)LocalFlags; } + // some of this lines need be moved to other place later + + // effective permitions considering only this part inventory contents perms + public uint AggregatedInnerOwnerPerms {get; private set; } + public uint AggregatedInnerGroupPerms {get; private set; } + public uint AggregatedInnerEveryonePerms {get; private set; } + private object InnerPermsLock = new object(); + + public void AggregateInnerPerms() + { + // assuming child prims permissions masks are irrelevant on a linkset + // root part is handle at SOG since its masks are the sog masks + const uint mask = (uint)PermissionMask.AllEffective; + + uint owner = mask; + uint group = mask; + uint everyone = mask; + + lock(InnerPermsLock) // do we really need this? + { + if(Inventory != null) + Inventory.AggregateInnerPerms(ref owner, ref group, ref everyone); + + AggregatedInnerOwnerPerms = owner & mask; + AggregatedInnerGroupPerms = group & mask; + AggregatedInnerEveryonePerms = everyone & mask; + if(ParentGroup != null) + ParentGroup.InvalidateEffectivePerms(); + } + } + public Vector3 GetGeometricCenter() { // this is not real geometric center but a average of positions relative to root prim acording to @@ -2754,12 +2801,13 @@ namespace OpenSim.Region.Framework.Scenes { ColliderArgs colliderArgs = new ColliderArgs(); List colliding = new List(); + Scene parentScene = ParentGroup.Scene; foreach (uint localId in colliders) { if (localId == 0) continue; - SceneObjectPart obj = ParentGroup.Scene.GetSceneObjectPart(localId); + SceneObjectPart obj = parentScene.GetSceneObjectPart(localId); if (obj != null) { if (!dest.CollisionFilteredOut(obj.UUID, obj.Name)) @@ -2767,7 +2815,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - ScenePresence av = ParentGroup.Scene.GetScenePresence(localId); + ScenePresence av = parentScene.GetScenePresence(localId); if (av != null && (!av.IsChildAgent)) { if (!dest.CollisionFilteredOut(av.UUID, av.Name)) @@ -2840,10 +2888,13 @@ namespace OpenSim.Region.Framework.Scenes public void PhysicsCollision(EventArgs e) { - if (ParentGroup.Scene == null || ParentGroup.IsDeleted) + if (ParentGroup.Scene == null || ParentGroup.IsDeleted || ParentGroup.inTransit) return; // this a thread from physics ( heartbeat ) + bool thisHitLand = false; + bool startLand = false; + bool endedLand = false; CollisionEventUpdate a = (CollisionEventUpdate)e; Dictionary collissionswith = a.m_objCollisionList; @@ -2853,13 +2904,17 @@ namespace OpenSim.Region.Framework.Scenes if (collissionswith.Count == 0) { - if (m_lastColliders.Count == 0) + if (m_lastColliders.Count == 0 && !m_lastLandCollide) return; // nothing to do + endedLand = m_lastLandCollide; + m_lastLandCollide = false; + foreach (uint localID in m_lastColliders) { endedColliders.Add(localID); } + m_lastColliders.Clear(); } else @@ -2875,19 +2930,39 @@ namespace OpenSim.Region.Framework.Scenes foreach (uint id in collissionswith.Keys) { - thisHitColliders.Add(id); - if (!m_lastColliders.Contains(id)) + if(id == 0) { - startedColliders.Add(id); - - curcontact = collissionswith[id]; - if (Math.Abs(curcontact.RelativeSpeed) > 0.2) + thisHitLand = true; + if (!m_lastLandCollide) { - soundinfo = new CollisionForSoundInfo(); - soundinfo.colliderID = id; - soundinfo.position = curcontact.Position; - soundinfo.relativeVel = curcontact.RelativeSpeed; - soundinfolist.Add(soundinfo); + startLand = true; + curcontact = collissionswith[id]; + if (Math.Abs(curcontact.RelativeSpeed) > 0.2) + { + soundinfo = new CollisionForSoundInfo(); + soundinfo.colliderID = id; + soundinfo.position = curcontact.Position; + soundinfo.relativeVel = curcontact.RelativeSpeed; + soundinfolist.Add(soundinfo); + } + } + } + else + { + thisHitColliders.Add(id); + if (!m_lastColliders.Contains(id)) + { + startedColliders.Add(id); + + curcontact = collissionswith[id]; + if (Math.Abs(curcontact.RelativeSpeed) > 0.2) + { + soundinfo = new CollisionForSoundInfo(); + soundinfo.colliderID = id; + soundinfo.position = curcontact.Position; + soundinfo.relativeVel = curcontact.RelativeSpeed; + soundinfolist.Add(soundinfo); + } } } } @@ -2896,9 +2971,18 @@ namespace OpenSim.Region.Framework.Scenes { foreach (uint id in collissionswith.Keys) { - thisHitColliders.Add(id); - if (!m_lastColliders.Contains(id)) - startedColliders.Add(id); + if(id == 0) + { + thisHitLand = true; + if (!m_lastLandCollide) + startLand = true; + } + else + { + thisHitColliders.Add(id); + if (!m_lastColliders.Contains(id)) + startedColliders.Add(id); + } } } @@ -2917,22 +3001,32 @@ namespace OpenSim.Region.Framework.Scenes foreach (uint localID in endedColliders) m_lastColliders.Remove(localID); + if(m_lastLandCollide && !thisHitLand) + endedLand = true; + + m_lastLandCollide = thisHitLand; + // play sounds. if (soundinfolist.Count > 0) CollisionSounds.PartCollisionSound(this, soundinfolist); } + + EventManager eventmanager = ParentGroup.Scene.EventManager; - SendCollisionEvent(scriptEvents.collision_start, startedColliders, ParentGroup.Scene.EventManager.TriggerScriptCollidingStart); + SendCollisionEvent(scriptEvents.collision_start, startedColliders, eventmanager.TriggerScriptCollidingStart); if (!VolumeDetectActive) - SendCollisionEvent(scriptEvents.collision , m_lastColliders , ParentGroup.Scene.EventManager.TriggerScriptColliding); - SendCollisionEvent(scriptEvents.collision_end , endedColliders , ParentGroup.Scene.EventManager.TriggerScriptCollidingEnd); + SendCollisionEvent(scriptEvents.collision , m_lastColliders , eventmanager.TriggerScriptColliding); + SendCollisionEvent(scriptEvents.collision_end , endedColliders , eventmanager.TriggerScriptCollidingEnd); - if (startedColliders.Contains(0)) - SendLandCollisionEvent(scriptEvents.land_collision_start, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingStart); - if (m_lastColliders.Contains(0)) - SendLandCollisionEvent(scriptEvents.land_collision, ParentGroup.Scene.EventManager.TriggerScriptLandColliding); - if (endedColliders.Contains(0)) - SendLandCollisionEvent(scriptEvents.land_collision_end, ParentGroup.Scene.EventManager.TriggerScriptLandCollidingEnd); + if (!VolumeDetectActive) + { + if (startLand) + SendLandCollisionEvent(scriptEvents.land_collision_start, eventmanager.TriggerScriptLandCollidingStart); + if (m_lastLandCollide) + SendLandCollisionEvent(scriptEvents.land_collision, eventmanager.TriggerScriptLandColliding); + if (endedLand) + SendLandCollisionEvent(scriptEvents.land_collision_end, eventmanager.TriggerScriptLandCollidingEnd); + } } // The Collision sounds code calls this @@ -2951,7 +3045,7 @@ namespace OpenSim.Region.Framework.Scenes volume = 0; int now = Util.EnvironmentTickCount(); - if(Util.EnvironmentTickCountSubtract(now,LastColSoundSentTime) <200) + if(Util.EnvironmentTickCountSubtract(now, LastColSoundSentTime) < 200) return; LastColSoundSentTime = now; @@ -2992,7 +3086,7 @@ namespace OpenSim.Region.Framework.Scenes //ParentGroup.RootPart.m_groupPosition = newpos; } /* - if (pa != null && ParentID != 0 && ParentGroup != null) + if (pa != null && _parentID != 0 && ParentGroup != null) { // Special case where a child object is requesting property updates. // This happens when linksets are modified to use flexible links rather than @@ -3153,17 +3247,6 @@ namespace OpenSim.Region.Framework.Scenes APIDActive = false; } - public void ScheduleFullUpdateIfNone() - { - if (ParentGroup == null) - return; - -// ??? ParentGroup.HasGroupChanged = true; - - if (UpdateFlag != UpdateRequired.FULL) - ScheduleFullUpdate(); - } - /// /// Schedules this prim for a full update /// @@ -3174,35 +3257,26 @@ namespace OpenSim.Region.Framework.Scenes if (ParentGroup == null) return; - ParentGroup.QueueForUpdateCheck(); - - int timeNow = Util.UnixTimeSinceEpoch(); - - // If multiple updates are scheduled on the same second, we still need to perform all of them - // So we'll force the issue by bumping up the timestamp so that later processing sees these need - // to be performed. - if (timeNow <= TimeStampFull) + lock(UpdateFlagLock) { - TimeStampFull += 1; + ParentGroup.QueueForUpdateCheck(); // just in case + if(UpdateFlag != UpdateRequired.FULL) + { + UpdateFlag = UpdateRequired.FULL; + + // m_log.DebugFormat( + // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", + // UUID, Name, TimeStampFull); + + if (ParentGroup.Scene != null) + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); + } } - else - { - TimeStampFull = (uint)timeNow; - } - - UpdateFlag = UpdateRequired.FULL; - - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Scheduling full update for {0}, {1} at {2}", - // UUID, Name, TimeStampFull); - - if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, true); } /// /// Schedule a terse update for this prim. Terse updates only send position, - /// rotation, velocity and rotational velocity information. + /// rotation, velocity and rotational velocity information. WRONG!!!! /// public void ScheduleTerseUpdate() { @@ -3218,21 +3292,23 @@ namespace OpenSim.Region.Framework.Scenes return; } - if (UpdateFlag == UpdateRequired.NONE) + lock(UpdateFlagLock) { - ParentGroup.HasGroupChanged = true; - ParentGroup.QueueForUpdateCheck(); + if (UpdateFlag == UpdateRequired.NONE) + { + ParentGroup.HasGroupChanged = true; + ParentGroup.QueueForUpdateCheck(); - TimeStampTerse = (uint) Util.UnixTimeSinceEpoch(); - UpdateFlag = UpdateRequired.TERSE; + UpdateFlag = UpdateRequired.TERSE; - // m_log.DebugFormat( - // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}", - // UUID, Name, TimeStampTerse); + // m_log.DebugFormat( + // "[SCENE OBJECT PART]: Scheduling terse update for {0}, {1} at {2}", + // UUID, Name, TimeStampTerse); + } + + if (ParentGroup.Scene != null) + ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); } - - if (ParentGroup.Scene != null) - ParentGroup.Scene.EventManager.TriggerSceneObjectPartUpdated(this, false); } public void ScriptSetPhysicsStatus(bool UsePhysics) @@ -3261,21 +3337,6 @@ namespace OpenSim.Region.Framework.Scenes sp.SendAttachmentUpdate(this, UpdateRequired.FULL); } } - -/* this does nothing -SendFullUpdateToClient(remoteClient, Position) ignores position parameter - if (IsRoot) - { - if (ParentGroup.IsAttachment) - { - SendFullUpdateToClient(remoteClient, AttachedPos); - } - else - { - SendFullUpdateToClient(remoteClient, AbsolutePosition); - } - } -*/ else { SendFullUpdateToClient(remoteClient); @@ -3291,12 +3352,15 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter return; // Update the "last" values - m_lastPosition = OffsetPosition; - m_lastRotation = RotationOffset; - m_lastVelocity = Velocity; - m_lastAcceleration = Acceleration; - m_lastAngularVelocity = AngularVelocity; - m_lastUpdateSentTime = Environment.TickCount; + lock(UpdateFlagLock) + { + m_lastPosition = AbsolutePosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = Util.GetTimeStampMS(); + } ParentGroup.Scene.ForEachScenePresence(delegate(ScenePresence avatar) { @@ -3310,12 +3374,15 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter return; // Update the "last" values - m_lastPosition = OffsetPosition; - m_lastRotation = RotationOffset; - m_lastVelocity = Velocity; - m_lastAcceleration = Acceleration; - m_lastAngularVelocity = AngularVelocity; - m_lastUpdateSentTime = Environment.TickCount; + lock(UpdateFlagLock) + { + m_lastPosition = AbsolutePosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = Util.GetTimeStampMS(); + } if (ParentGroup.IsAttachment) { @@ -3340,25 +3407,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter /// public void SendFullUpdateToClient(IClientAPI remoteClient) { - SendFullUpdateToClient(remoteClient, OffsetPosition); - } - - /// - /// Sends a full update to the client - /// - /// - /// - public void SendFullUpdateToClient(IClientAPI remoteClient, Vector3 lPos) - { - if (ParentGroup == null) - return; - - // Suppress full updates during attachment editing - // sl Does send them - // if (ParentGroup.IsSelected && ParentGroup.IsAttachment) - // return; - - if (ParentGroup.IsDeleted) + if (ParentGroup == null || ParentGroup.IsDeleted) return; if (ParentGroup.IsAttachment @@ -3379,40 +3428,138 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter ParentGroup.Scene.StatsReporter.AddObjectUpdates(1); } + + private const float ROTATION_TOLERANCE = 0.01f; + private const float VELOCITY_TOLERANCE = 0.1f; // terse update vel has low resolution + private const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary + private const double TIME_MS_TOLERANCE = 200f; //llSetPos has a 200ms delay. This should NOT be 3 seconds. + /// /// Tell all the prims which have had updates scheduled /// public void SendScheduledUpdates() - { - const float ROTATION_TOLERANCE = 0.01f; - const float VELOCITY_TOLERANCE = 0.001f; - const float POSITION_TOLERANCE = 0.05f; // I don't like this, but I suppose it's necessary - const int TIME_MS_TOLERANCE = 200; //llSetPos has a 200ms delay. This should NOT be 3 seconds. - - switch (UpdateFlag) + { + UpdateRequired currentUpdate; + lock(UpdateFlagLock) { + currentUpdate = UpdateFlag; + ClearUpdateSchedule(); + } + + switch (currentUpdate) + { + case UpdateRequired.NONE: + break; + case UpdateRequired.TERSE: - { - ClearUpdateSchedule(); - // Throw away duplicate or insignificant updates - if (!RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || - !Acceleration.Equals(m_lastAcceleration) || - !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || - Velocity.ApproxEquals(Vector3.Zero, VELOCITY_TOLERANCE) || - !AngularVelocity.ApproxEquals(m_lastAngularVelocity, VELOCITY_TOLERANCE) || - !OffsetPosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || - Environment.TickCount - m_lastUpdateSentTime > TIME_MS_TOLERANCE) + bool needupdate = true; + lock(UpdateFlagLock) { - SendTerseUpdateToAllClientsInternal(); + double now = Util.GetTimeStampMS(); + Vector3 curvel = Velocity; + Vector3 curacc = Acceleration; + Vector3 angvel = AngularVelocity; + + while(true) // just to avoid ugly goto + { + double elapsed = now - m_lastUpdateSentTime; + if (elapsed > TIME_MS_TOLERANCE) + break; + + if( Math.Abs(curacc.X - m_lastAcceleration.X) > VELOCITY_TOLERANCE || + Math.Abs(curacc.Y - m_lastAcceleration.Y) > VELOCITY_TOLERANCE || + Math.Abs(curacc.Z - m_lastAcceleration.Z) > VELOCITY_TOLERANCE) + break; + + // velocity change is also direction not only norm) + if( Math.Abs(curvel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || + Math.Abs(curvel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE || + Math.Abs(curvel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE) + break; + + float vx = Math.Abs(curvel.X); + if(vx > 128.0) + break; + float vy = Math.Abs(curvel.Y); + if(vy > 128.0) + break; + float vz = Math.Abs(curvel.Z); + if(vz > 128.0) + break; + + if ( + vx < VELOCITY_TOLERANCE && + vy < VELOCITY_TOLERANCE && + vz < VELOCITY_TOLERANCE + ) + { + if(!AbsolutePosition.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) + break; + + if (vx < 1e-4 && + vy < 1e-4 && + vz < 1e-4 && + ( + Math.Abs(m_lastVelocity.X) > 1e-4 || + Math.Abs(m_lastVelocity.Y) > 1e-4 || + Math.Abs(m_lastVelocity.Z) > 1e-4 + )) + break; + } + + if( Math.Abs(angvel.X - m_lastAngularVelocity.X) > VELOCITY_TOLERANCE || + Math.Abs(angvel.Y - m_lastAngularVelocity.Y) > VELOCITY_TOLERANCE || + Math.Abs(angvel.Z - m_lastAngularVelocity.Z) > VELOCITY_TOLERANCE) + break; + + // viewer interpolators have a limit of 128m/s + float ax = Math.Abs(angvel.X); + if(ax > 64.0) + break; + float ay = Math.Abs(angvel.Y); + if(ay > 64.0) + break; + float az = Math.Abs(angvel.Z); + if(az > 64.0) + break; + + if ( + ax < VELOCITY_TOLERANCE && + ay < VELOCITY_TOLERANCE && + az < VELOCITY_TOLERANCE && + !RotationOffset.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) + ) + break; + + needupdate = false; + break; + } + + if(needupdate) + { + + // Update the "last" values + m_lastPosition = AbsolutePosition; + m_lastRotation = RotationOffset; + m_lastVelocity = curvel; + m_lastAcceleration = curacc; + m_lastAngularVelocity = angvel; + m_lastUpdateSentTime = now; + } + } + + if(needupdate) + { + ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) + { + SendTerseUpdateToClient(client); + }); } break; - } + case UpdateRequired.FULL: - { - ClearUpdateSchedule(); SendFullUpdateToAllClientsInternal(); break; - } } } @@ -3425,13 +3572,19 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (ParentGroup == null || ParentGroup.Scene == null) return; - // Update the "last" values - m_lastPosition = OffsetPosition; - m_lastRotation = RotationOffset; - m_lastVelocity = Velocity; - m_lastAcceleration = Acceleration; - m_lastAngularVelocity = AngularVelocity; - m_lastUpdateSentTime = Environment.TickCount; + lock(UpdateFlagLock) + { + if(UpdateFlag != UpdateRequired.NONE) + return; + + // Update the "last" values + m_lastPosition = AbsolutePosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = Util.GetTimeStampMS(); + } ParentGroup.Scene.ForEachClient(delegate(IClientAPI client) { @@ -3444,13 +3597,19 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (ParentGroup == null || ParentGroup.Scene == null) return; - // Update the "last" values - m_lastPosition = OffsetPosition; - m_lastRotation = RotationOffset; - m_lastVelocity = Velocity; - m_lastAcceleration = Acceleration; - m_lastAngularVelocity = AngularVelocity; - m_lastUpdateSentTime = Environment.TickCount; + lock(UpdateFlagLock) + { + if(UpdateFlag != UpdateRequired.NONE) + return; + + // Update the "last" values + m_lastPosition = AbsolutePosition; + m_lastRotation = RotationOffset; + m_lastVelocity = Velocity; + m_lastAcceleration = Acceleration; + m_lastAngularVelocity = AngularVelocity; + m_lastUpdateSentTime = Util.GetTimeStampMS(); + } if (ParentGroup.IsAttachment) { @@ -3516,6 +3675,18 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter Force = force; } + public PhysicsInertiaData PhysicsInertia + { + get + { + return m_physicsInertia; + } + set + { + m_physicsInertia = value; + } + } + public SOPVehicle VehicleParams { get @@ -3689,7 +3860,18 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter bool hasDimple; bool hasProfileCut; - PrimType primType = GetPrimType(); + if(Shape.SculptEntry) + { + if (Shape.SculptType != (byte)SculptType.Mesh) + return 1; // sculp + + //hack to detect new upload with faces data enconded on pbs + if ((Shape.ProfileCurve & 0xf0) != (byte)HollowShape.Triangle) + // old broken upload TODO + return 8; + } + + PrimType primType = GetPrimType(true); HasCutHollowDimpleProfileCut(primType, Shape, out hasCut, out hasHollow, out hasDimple, out hasProfileCut); switch (primType) @@ -3733,13 +3915,6 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (hasProfileCut) ret += 2; if (hasHollow) ret += 1; break; - case PrimType.SCULPT: - // Special mesh handling - if (Shape.SculptType == (byte)SculptType.Mesh) - ret = 8; // if it's a mesh then max 8 faces - else - ret = 1; // if it's a sculpt then max 1 face - break; } return ret; @@ -3750,9 +3925,9 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter /// /// /// - public PrimType GetPrimType() + public PrimType GetPrimType(bool ignoreSculpt = false) { - if (Shape.SculptEntry) + if (Shape.SculptEntry && !ignoreSculpt) return PrimType.SCULPT; if ((Shape.ProfileCurve & 0x07) == (byte)ProfileShape.Square) @@ -4415,8 +4590,11 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (god) baseMask = 0x7ffffff0; - // Are we the owner? - if ((AgentID == OwnerID) || god) + bool canChange = (AgentID == OwnerID) || god; + if(!canChange) + canChange = ParentGroup.Scene.Permissions.CanEditObjectPermissions(ParentGroup, AgentID); + + if (canChange) { switch (field) { @@ -4464,7 +4642,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter break; } - + AggregateInnerPerms(); SendFullUpdateToAllClients(); } } @@ -4481,6 +4659,8 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter EveryoneMask = source.EveryoneMask & BaseMask; NextOwnerMask = source.NextOwnerMask & BaseMask; + AggregateInnerPerms(); + if (OwnerMask != prevOwnerMask || GroupMask != prevGroupMask || EveryoneMask != prevEveryoneMask || @@ -4714,8 +4894,13 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (VolumeDetectActive) // change if not the default only pa.SetVolumeDetect(1); + + bool isroot = (m_localId == ParentGroup.RootPart.LocalId); - if (m_vehicleParams != null && m_localId == ParentGroup.RootPart.LocalId) + if(isroot && m_physicsInertia != null) + pa.SetInertiaData(m_physicsInertia); + + if (isroot && m_vehicleParams != null ) { m_vehicleParams.SetVehicle(pa); if(isPhysical && !isPhantom && m_vehicleParams.CameraDecoupled) @@ -4741,7 +4926,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter pa.OnRequestTerseUpdate += PhysicsRequestingTerseUpdate; pa.OnOutOfBounds += PhysicsOutOfBounds; - if (ParentID != 0 && ParentID != LocalId) + if (_parentID != 0 && _parentID != LocalId) { PhysicsActor parentPa = ParentGroup.RootPart.PhysActor; @@ -4974,6 +5159,9 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (newTex.FaceTextures[i] != null) newFace = newTex.FaceTextures[i]; + if (oldFace.TextureID != newFace.TextureID) + changeFlags |= Changed.TEXTURE; + Color4 oldRGBA = oldFace.RGBA; Color4 newRGBA = newFace.RGBA; @@ -4983,9 +5171,6 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter oldRGBA.A != newRGBA.A) changeFlags |= Changed.COLOR; - if (oldFace.TextureID != newFace.TextureID) - changeFlags |= Changed.TEXTURE; - // Max change, skip the rest of testing if (changeFlags == (Changed.TEXTURE | Changed.COLOR)) break; @@ -5011,17 +5196,11 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter m_shape.TextureEntry = newTex.GetBytes(); if (changeFlags != 0) TriggerScriptChangedEvent(changeFlags); - UpdateFlag = UpdateRequired.FULL; ParentGroup.HasGroupChanged = true; - - //This is madness.. - //ParentGroup.ScheduleGroupForFullUpdate(); - //This is sparta ScheduleFullUpdate(); } } - internal void UpdatePhysicsSubscribedEvents() { PhysicsActor pa = PhysActor; @@ -5181,7 +5360,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter /// The scene the prim is being rezzed into public void ApplyPermissionsOnRez(InventoryItemBase item, bool userInventory, Scene scene) { - if ((OwnerID != item.Owner) || ((item.CurrentPermissions & SceneObjectGroup.SLAM) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)) + if ((OwnerID != item.Owner) || ((item.CurrentPermissions & (uint)PermissionMask.Slam) != 0) || ((item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0)) { if (scene.Permissions.PropagatePermissions()) { @@ -5212,16 +5391,13 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter if (OwnerID != item.Owner) { - //LogPermissions("Before ApplyNextOwnerPermissions"); + if(OwnerID != GroupID) + LastOwnerID = OwnerID; + OwnerID = item.Owner; + Inventory.ChangeInventoryOwner(item.Owner); if (scene.Permissions.PropagatePermissions()) ApplyNextOwnerPermissions(); - - //LogPermissions("After ApplyNextOwnerPermissions"); - - LastOwnerID = OwnerID; - OwnerID = item.Owner; - Inventory.ChangeInventoryOwner(item.Owner); } } @@ -5239,12 +5415,13 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter // Export needs to be preserved in the base and everyone // mask, but removed in the owner mask as a next owner // can never change the export status - BaseMask &= NextOwnerMask | (uint)PermissionMask.Export; + BaseMask &= (NextOwnerMask | (uint)PermissionMask.Export); OwnerMask &= NextOwnerMask; - EveryoneMask &= NextOwnerMask | (uint)PermissionMask.Export; + EveryoneMask &= (NextOwnerMask | (uint)PermissionMask.Export); GroupMask = 0; // Giving an object zaps group permissions Inventory.ApplyNextOwnerPermissions(); + AggregateInnerPerms(); } public void UpdateLookAt() @@ -5306,6 +5483,7 @@ SendFullUpdateToClient(remoteClient, Position) ignores position parameter item.OwnerChanged = false; Inventory.UpdateInventoryItem(item, false, false); } + AggregateInnerPerms(); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 6557003a12..3fd6e13c13 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -91,7 +91,8 @@ namespace OpenSim.Region.Framework.Scenes /// protected internal TaskInventoryDictionary Items { - get { + get + { return m_items; } set @@ -141,45 +142,53 @@ namespace OpenSim.Region.Framework.Scenes /// public void ResetInventoryIDs() { - if (null == m_part) - m_items.LockItemsForWrite(true); + if (m_part == null) + return; - if (Items.Count == 0) + m_items.LockItemsForWrite(true); + if (m_items.Count == 0) { m_items.LockItemsForWrite(false); return; } - IList items = new List(Items.Values); - Items.Clear(); + UUID partID = m_part.UUID; + IList items = new List(m_items.Values); + m_items.Clear(); foreach (TaskInventoryItem item in items) { - item.ResetIDs(m_part.UUID); - Items.Add(item.ItemID, item); + item.ResetIDs(partID); + m_items.Add(item.ItemID, item); } + m_inventorySerial++; m_items.LockItemsForWrite(false); } public void ResetObjectID() { + if (m_part == null) + return; + m_items.LockItemsForWrite(true); - if (Items.Count == 0) + if (m_items.Count == 0) { m_items.LockItemsForWrite(false); return; } - IList items = new List(Items.Values); - Items.Clear(); + IList items = new List(m_items.Values); + m_items.Clear(); + UUID partID = m_part.UUID; foreach (TaskInventoryItem item in items) { - item.ParentPartID = m_part.UUID; - item.ParentID = m_part.UUID; - Items.Add(item.ItemID, item); + item.ParentPartID = partID; + item.ParentID = partID; + m_items.Add(item.ItemID, item); } + m_inventorySerial++; m_items.LockItemsForWrite(false); } @@ -189,15 +198,17 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryOwner(UUID ownerId) { - List items = GetInventoryItems(); - - if (items.Count == 0) + if(m_part == null) return; m_items.LockItemsForWrite(true); - HasInventoryChanged = true; - m_part.ParentGroup.HasGroupChanged = true; - foreach (TaskInventoryItem item in items) + if (m_items.Count == 0) + { + m_items.LockItemsForWrite(false); + return; + } + + foreach (TaskInventoryItem item in m_items.Values) { if (ownerId != item.OwnerID) item.LastOwnerID = item.OwnerID; @@ -207,6 +218,9 @@ namespace OpenSim.Region.Framework.Scenes item.PermsGranter = UUID.Zero; item.OwnerChanged = true; } + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + m_inventorySerial++; m_items.LockItemsForWrite(false); } @@ -216,13 +230,16 @@ namespace OpenSim.Region.Framework.Scenes /// public void ChangeInventoryGroup(UUID groupID) { + if(m_part == null) + return; + m_items.LockItemsForWrite(true); - if (0 == Items.Count) + if (m_items.Count == 0) { m_items.LockItemsForWrite(false); return; } - + m_inventorySerial++; // Don't let this set the HasGroupChanged flag for attachments // as this happens during rez and we don't want a new asset // for each attachment each time @@ -232,14 +249,9 @@ namespace OpenSim.Region.Framework.Scenes m_part.ParentGroup.HasGroupChanged = true; } - IList items = new List(Items.Values); - foreach (TaskInventoryItem item in items) - { - if (groupID != item.GroupID) - { - item.GroupID = groupID; - } - } + foreach (TaskInventoryItem item in m_items.Values) + item.GroupID = groupID; + m_items.LockItemsForWrite(false); } @@ -248,8 +260,8 @@ namespace OpenSim.Region.Framework.Scenes if (m_part == null || m_part.ParentGroup == null || m_part.ParentGroup.Scene == null) return; - Items.LockItemsForRead(true); - foreach (TaskInventoryItem item in Items.Values) + m_items.LockItemsForRead(true); + foreach (TaskInventoryItem item in m_items.Values) { if (item.InvType == (int)InventoryType.LSL) { @@ -259,7 +271,7 @@ namespace OpenSim.Region.Framework.Scenes } } - Items.LockItemsForRead(false); + m_items.LockItemsForRead(false); } public bool TryGetScriptInstanceRunning(UUID itemId, out bool running) @@ -347,7 +359,9 @@ namespace OpenSim.Region.Framework.Scenes /// public void StopScriptInstances() { - GetInventoryItems(InventoryType.LSL).ForEach(i => StopScriptInstance(i)); + List scripts = GetInventoryItems(InventoryType.LSL); + foreach (TaskInventoryItem item in scripts) + StopScriptInstance(item); } /// @@ -360,7 +374,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat("[PRIM INVENTORY]: Starting script {0} {1} in prim {2} {3} in {4}", // item.Name, item.ItemID, m_part.Name, m_part.UUID, m_part.ParentGroup.Scene.RegionInfo.RegionName); - if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) + if (!m_part.ParentGroup.Scene.Permissions.CanRunScript(item, m_part)) { StoreScriptError(item.ItemID, "no permission"); return false; @@ -807,8 +821,8 @@ namespace OpenSim.Region.Framework.Scenes else m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + m_part.AggregateInnerPerms(); m_inventorySerial++; - //m_inventorySerial += 2; HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; } @@ -829,7 +843,7 @@ namespace OpenSim.Region.Framework.Scenes // m_part.TriggerScriptChangedEvent(Changed.INVENTORY); } m_items.LockItemsForWrite(false); - + m_part.AggregateInnerPerms(); m_inventorySerial++; } @@ -943,8 +957,7 @@ namespace OpenSim.Region.Framework.Scenes group.SetGroup(m_part.GroupID, null); - // TODO: Remove magic number badness - if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number + if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) { if (m_part.ParentGroup.Scene.Permissions.PropagatePermissions()) { @@ -964,10 +977,10 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in partList) { - // TODO: Remove magic number badness - if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) // Magic number + if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & (uint)PermissionMask.Slam) != 0 || (item.Flags & (uint)InventoryItemFlags.ObjectSlamPerm) != 0) { - part.LastOwnerID = part.OwnerID; + if(part.GroupID != part.OwnerID) + part.LastOwnerID = part.OwnerID; part.OwnerID = item.OwnerID; part.Inventory.ChangeInventoryOwner(item.OwnerID); } @@ -981,6 +994,7 @@ namespace OpenSim.Region.Framework.Scenes } // old code end rootPart.TrimPermissions(); + group.InvalidateDeepEffectivePerms(); } return true; @@ -1018,20 +1032,26 @@ namespace OpenSim.Region.Framework.Scenes if (item.GroupPermissions != (uint)PermissionMask.None) item.GroupID = m_part.GroupID; + if(item.OwnerID == UUID.Zero) // viewer to internal enconding of group owned + item.OwnerID = item.GroupID; + if (item.AssetID == UUID.Zero) item.AssetID = m_items[item.ItemID].AssetID; m_items[item.ItemID] = item; + m_inventorySerial++; if (fireScriptEvents) m_part.TriggerScriptChangedEvent(Changed.INVENTORY); if (considerChanged) { + m_part.ParentGroup.InvalidateDeepEffectivePerms(); HasInventoryChanged = true; m_part.ParentGroup.HasGroupChanged = true; } m_items.LockItemsForWrite(false); + return true; } else @@ -1068,6 +1088,9 @@ namespace OpenSim.Region.Framework.Scenes m_items.LockItemsForWrite(true); m_items.Remove(itemID); m_items.LockItemsForWrite(false); + + m_part.ParentGroup.InvalidateDeepEffectivePerms(); + m_inventorySerial++; m_part.TriggerScriptChangedEvent(Changed.INVENTORY); @@ -1118,18 +1141,18 @@ namespace OpenSim.Region.Framework.Scenes { bool changed = false; - Items.LockItemsForRead(true); + m_items.LockItemsForRead(true); if (m_inventorySerial == 0) // No inventory { - Items.LockItemsForRead(false); + m_items.LockItemsForRead(false); client.SendTaskInventory(m_part.UUID, 0, new byte[0]); return; } if (m_items.Count == 0) // No inventory { - Items.LockItemsForRead(false); + m_items.LockItemsForRead(false); client.SendTaskInventory(m_part.UUID, 0, new byte[0]); return; } @@ -1140,7 +1163,7 @@ namespace OpenSim.Region.Framework.Scenes changed = true; } - Items.LockItemsForRead(false); + m_items.LockItemsForRead(false); if (m_inventoryFileData.Length < 2) changed = true; @@ -1165,12 +1188,13 @@ namespace OpenSim.Region.Framework.Scenes InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); - Items.LockItemsForRead(true); + m_items.LockItemsForRead(true); foreach (TaskInventoryItem item in m_items.Values) { UUID ownerID = item.OwnerID; - uint everyoneMask = 0; + UUID groupID = item.GroupID; + uint everyoneMask = item.EveryonePermissions; uint baseMask = item.BasePermissions; uint ownerMask = item.CurrentPermissions; uint groupMask = item.GroupPermissions; @@ -1188,11 +1212,21 @@ namespace OpenSim.Region.Framework.Scenes invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); - invString.AddNameValueLine("owner_id", ownerID.ToString()); invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); - invString.AddNameValueLine("group_id", item.GroupID.ToString()); + invString.AddNameValueLine("group_id",groupID.ToString()); + if(groupID != UUID.Zero && ownerID == groupID) + { + invString.AddNameValueLine("owner_id", UUID.Zero.ToString()); + invString.AddNameValueLine("group_owned","1"); + } + else + { + invString.AddNameValueLine("owner_id", ownerID.ToString()); + invString.AddNameValueLine("group_owned","0"); + } + invString.AddSectionEnd(); if (includeAssets) @@ -1215,7 +1249,7 @@ namespace OpenSim.Region.Framework.Scenes invString.AddSectionEnd(); } - Items.LockItemsForRead(false); + m_items.LockItemsForRead(false); m_inventoryFileData = Utils.StringToBytes(invString.GetString()); @@ -1245,10 +1279,10 @@ namespace OpenSim.Region.Framework.Scenes // of prim inventory loss. // if (HasInventoryChanged) // { - Items.LockItemsForRead(true); - ICollection itemsvalues = Items.Values; + m_items.LockItemsForRead(true); + ICollection itemsvalues = m_items.Values; HasInventoryChanged = false; - Items.LockItemsForRead(false); + m_items.LockItemsForRead(false); try { datastore.StorePrimInventory(m_part.UUID, itemsvalues); @@ -1319,35 +1353,49 @@ namespace OpenSim.Region.Framework.Scenes } } - public uint MaskEffectivePermissions() + public void AggregateInnerPerms(ref uint owner, ref uint group, ref uint everyone) { - uint mask=0x7fffffff; - foreach (TaskInventoryItem item in m_items.Values) { - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) - mask &= ~((uint)PermissionMask.Copy >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) - mask &= ~((uint)PermissionMask.Transfer >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~((uint)PermissionMask.Modify >> 13); + if(item.InvType == (sbyte)InventoryType.Landmark) + continue; + owner &= item.CurrentPermissions; + group &= item.GroupPermissions; + everyone &= item.EveryonePermissions; + } + } - if (item.InvType == (int)InventoryType.Object) - { - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - mask &= ~((uint)PermissionMask.Copy >> 13); - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - mask &= ~((uint)PermissionMask.Transfer >> 13); - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - mask &= ~((uint)PermissionMask.Modify >> 13); - } + public uint MaskEffectivePermissions() + { + // used to propagate permissions restrictions outwards + // Modify does not propagate outwards. + uint mask=0x7fffffff; + + foreach (TaskInventoryItem item in m_items.Values) + { + if(item.InvType == (sbyte)InventoryType.Landmark) + continue; - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + // apply current to normal permission bits + uint newperms = item.CurrentPermissions; + + if ((newperms & (uint)PermissionMask.Copy) == 0) mask &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + if ((newperms & (uint)PermissionMask.Transfer) == 0) mask &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~(uint)PermissionMask.Modify; + if ((newperms & (uint)PermissionMask.Export) == 0) + mask &= ~((uint)PermissionMask.Export); + + // apply next owner restricted by current to folded bits + newperms &= item.NextPermissions; + + if ((newperms & (uint)PermissionMask.Copy) == 0) + mask &= ~((uint)PermissionMask.FoldedCopy); + if ((newperms & (uint)PermissionMask.Transfer) == 0) + mask &= ~((uint)PermissionMask.FoldedTransfer); + if ((newperms & (uint)PermissionMask.Export) == 0) + mask &= ~((uint)PermissionMask.FoldedExport); + } return mask; } @@ -1356,19 +1404,6 @@ namespace OpenSim.Region.Framework.Scenes { foreach (TaskInventoryItem item in m_items.Values) { - if (item.InvType == (int)InventoryType.Object && (item.CurrentPermissions & 7) != 0) - { -// m_log.DebugFormat ( -// "[SCENE OBJECT PART INVENTORY]: Applying next permissions {0} to {1} in {2} with current {3}, base {4}, everyone {5}", -// item.NextPermissions, item.Name, m_part.Name, item.CurrentPermissions, item.BasePermissions, item.EveryonePermissions); - - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Modify; - } item.CurrentPermissions &= item.NextPermissions; item.BasePermissions &= item.NextPermissions; item.EveryonePermissions &= item.NextPermissions; @@ -1414,15 +1449,13 @@ namespace OpenSim.Region.Framework.Scenes public int ScriptCount() { int count = 0; - Items.LockItemsForRead(true); + m_items.LockItemsForRead(true); foreach (TaskInventoryItem item in m_items.Values) { if (item.InvType == (int)InventoryType.LSL) - { count++; - } } - Items.LockItemsForRead(false); + m_items.LockItemsForRead(false); return count; } /// @@ -1445,9 +1478,7 @@ namespace OpenSim.Region.Framework.Scenes if (engine != null) { if (engine.GetScriptState(item.ItemID)) - { count++; - } } } } @@ -1456,37 +1487,35 @@ namespace OpenSim.Region.Framework.Scenes public List GetInventoryList() { - List ret = new List(); + m_items.LockItemsForRead(true); + List ret = new List(m_items.Count); foreach (TaskInventoryItem item in m_items.Values) ret.Add(item.ItemID); + m_items.LockItemsForRead(false); return ret; } public List GetInventoryItems() { - List ret = new List(); - - Items.LockItemsForRead(true); - ret = new List(m_items.Values); - Items.LockItemsForRead(false); + m_items.LockItemsForRead(true); + List ret = new List(m_items.Values); + m_items.LockItemsForRead(false); return ret; } public List GetInventoryItems(InventoryType type) { - List ret = new List(); - - Items.LockItemsForRead(true); + m_items.LockItemsForRead(true); + List ret = new List(m_items.Count); foreach (TaskInventoryItem item in m_items.Values) if (item.InvType == (int)type) ret.Add(item); - Items.LockItemsForRead(false); - + m_items.LockItemsForRead(false); return ret; } diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 9545c13d85..ba3aaaed61 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -170,6 +170,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_previusParcelHide = false; private bool m_currentParcelHide = false; private object parcelLock = new Object(); + public double ParcelDwellTickMS; public UUID currentParcelUUID { @@ -182,6 +183,7 @@ namespace OpenSim.Region.Framework.Scenes bool checksame = true; if (value != m_currentParcelUUID) { + ParcelDwellTickMS = Util.GetTimeStampMS(); m_previusParcelHide = m_currentParcelHide; m_previusParcelUUID = m_currentParcelUUID; checksame = false; @@ -277,8 +279,11 @@ namespace OpenSim.Region.Framework.Scenes private bool MouseDown = false; public Vector3 lastKnownAllowedPosition; public bool sentMessageAboutRestrictedParcelFlyingDown; + public Vector4 CollisionPlane = Vector4.UnitW; + public Vector4 m_lastCollisionPlane = Vector4.UnitW; + private byte m_lastState; private Vector3 m_lastPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; @@ -362,6 +367,7 @@ namespace OpenSim.Region.Framework.Scenes //PauPaw:Proper PID Controler for autopilot************ public bool MovingToTarget { get; private set; } public Vector3 MoveToPositionTarget { get; private set; } + private double m_delayedStop = -1.0; /// /// Controls whether an avatar automatically moving to a target will land when it gets there (if flying). @@ -968,6 +974,10 @@ namespace OpenSim.Region.Framework.Scenes m_inTransit = value; } } + // this is is only valid if IsInTransit is true + // only false on HG tps + // used work arounf viewers asking source region about destination user + public bool IsInLocalTransit {get; set; } /// @@ -1037,6 +1047,7 @@ namespace OpenSim.Region.Framework.Scenes m_uuid = client.AgentId; LocalId = m_scene.AllocateLocalId(); LegacySitOffsets = m_scene.LegacySitOffsets; + IsInLocalTransit = true; UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); if (account != null) @@ -1778,6 +1789,20 @@ namespace OpenSim.Region.Framework.Scenes private Dictionary m_knownChildRegionsSizeInfo = new Dictionary(); + public void AddNeighbourRegion(GridRegion region, string capsPath) + { + lock (m_knownChildRegions) + { + ulong regionHandle = region.RegionHandle; + m_knownChildRegions.Add(regionHandle,capsPath); + + spRegionSizeInfo sizeInfo = new spRegionSizeInfo(); + sizeInfo.sizeX = region.RegionSizeX; + sizeInfo.sizeY = region.RegionSizeY; + m_knownChildRegionsSizeInfo[regionHandle] = sizeInfo; + } + } + public void AddNeighbourRegionSizeInfo(GridRegion region) { lock (m_knownChildRegions) @@ -1802,6 +1827,7 @@ namespace OpenSim.Region.Framework.Scenes lock (m_knownChildRegions) { m_knownChildRegionsSizeInfo.Clear(); + foreach (GridRegion region in regionsList) { spRegionSizeInfo sizeInfo = new spRegionSizeInfo(); @@ -1826,6 +1852,12 @@ namespace OpenSim.Region.Framework.Scenes } } + public bool knowsNeighbourRegion(ulong regionHandle) + { + lock (m_knownChildRegions) + return m_knownChildRegions.ContainsKey(regionHandle); + } + public void DropOldNeighbours(List oldRegions) { foreach (ulong handle in oldRegions) @@ -1862,7 +1894,8 @@ namespace OpenSim.Region.Framework.Scenes { get { - return new List(KnownRegions.Keys); + lock (m_knownChildRegions) + return new List(m_knownChildRegions.Keys); } } @@ -2010,6 +2043,7 @@ namespace OpenSim.Region.Framework.Scenes return; } + m_log.DebugFormat("[CompleteMovement] MakeRootAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); if(!haveGroupInformation && !IsChildAgent && !IsNPC) @@ -2029,11 +2063,6 @@ namespace OpenSim.Region.Framework.Scenes m_log.DebugFormat("[CompleteMovement]: Missing COF for {0} is {1}", client.AgentId, COF); } - // Tell the client that we're totally ready - ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); - - m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - if (!string.IsNullOrEmpty(m_callbackURI)) { // We cannot sleep here since this would hold up the inbound packet processing thread, as @@ -2054,6 +2083,7 @@ namespace OpenSim.Region.Framework.Scenes Scene.SimulationService.ReleaseAgent(originID, UUID, m_callbackURI); m_callbackURI = null; + m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); } // else // { @@ -2062,45 +2092,27 @@ namespace OpenSim.Region.Framework.Scenes // client.Name, client.AgentId, m_scene.RegionInfo.RegionName); // } - m_log.DebugFormat("[CompleteMovement] ReleaseAgent: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - if(m_teleportFlags > 0) - { - gotCrossUpdate = false; // sanity check - Thread.Sleep(500); // let viewers catch us - } + // Tell the client that we're totally ready + ControllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look); + m_log.DebugFormat("[CompleteMovement] MoveAgentIntoRegion: {0}ms", Util.EnvironmentTickCountSubtract(ts)); - if(!gotCrossUpdate) - RotateToLookAt(look); - - // HG bool isHGTP = (m_teleportFlags & TeleportFlags.ViaHGLogin) != 0; - if(isHGTP) - { -// ControllingClient.SendNameReply(m_uuid, Firstname, Lastname); - m_log.DebugFormat("[CompleteMovement] HG"); - } - m_previusParcelHide = false; - m_previusParcelUUID = UUID.Zero; - m_currentParcelHide = false; - m_currentParcelUUID = UUID.Zero; - - if(!IsNPC) - { - GodController.SyncViewerState(); - - // start sending terrain patchs - if (!gotCrossUpdate) - Scene.SendLayerData(ControllingClient); - } - // send initial land overlay and parcel - ILandChannel landch = m_scene.LandChannel; - if (landch != null) - landch.sendClientInitialLandInfo(client); + int delayctnr = Util.EnvironmentTickCount(); if (!IsChildAgent) { + if( ParentPart != null && !IsNPC && (crossingFlags & 0x08) != 0) + { + +// SceneObjectPart root = ParentPart.ParentGroup.RootPart; +// if(root.LocalId != ParentPart.LocalId) +// ControllingClient.SendEntityTerseUpdateImmediate(root); +// ControllingClient.SendEntityTerseUpdateImmediate(ParentPart); + ParentPart.ParentGroup.SendFullUpdateToClient(ControllingClient); + } + // verify baked textures and cache bool cachedbaked = false; @@ -2118,11 +2130,52 @@ namespace OpenSim.Region.Framework.Scenes m_scene.AvatarFactory.QueueAppearanceSave(UUID); } } + m_log.DebugFormat("[CompleteMovement] Baked check: {0}ms", Util.EnvironmentTickCountSubtract(ts)); + } + if(m_teleportFlags > 0) + { + gotCrossUpdate = false; // sanity check + if(Util.EnvironmentTickCountSubtract(delayctnr)< 500) + Thread.Sleep(500); // let viewers catch us + } + + if(!gotCrossUpdate) + RotateToLookAt(look); + + // HG + if(isHGTP) + { +// ControllingClient.SendNameReply(m_uuid, Firstname, Lastname); + m_log.DebugFormat("[CompleteMovement] HG"); + } + + m_previusParcelHide = false; + m_previusParcelUUID = UUID.Zero; + m_currentParcelHide = false; + m_currentParcelUUID = UUID.Zero; + ParcelDwellTickMS = Util.GetTimeStampMS(); + + if(!IsNPC) + { + GodController.SyncViewerState(); + + // start sending terrain patchs + if (!gotCrossUpdate) + Scene.SendLayerData(ControllingClient); + } + // send initial land overlay and parcel + ILandChannel landch = m_scene.LandChannel; + if (landch != null) + landch.sendClientInitialLandInfo(client); + + if (!IsChildAgent) + { List allpresences = m_scene.GetScenePresences(); // send avatar object to all presences including us, so they cross it into region // then hide if necessary + SendInitialAvatarDataToAllAgents(allpresences); // send this look @@ -2409,7 +2462,9 @@ namespace OpenSim.Region.Framework.Scenes // This is irritating. Really. if (!AbsolutePosition.IsFinite()) { - RemoveFromPhysicalScene(); + bool isphysical = PhysicsActor != null; + if(isphysical) + RemoveFromPhysicalScene(); m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999902"); m_pos = m_LastFinitePos; @@ -2421,7 +2476,8 @@ namespace OpenSim.Region.Framework.Scenes m_log.Error("[AVATAR]: NonFinite Avatar position detected... Reset Position. Mantis this please. Error #9999903"); } - AddToPhysicalScene(false); + if(isphysical) + AddToPhysicalScene(false); } else { @@ -2681,7 +2737,6 @@ namespace OpenSim.Region.Framework.Scenes agent_control_v3.Z = 0; // else if(AgentControlStopActive %% Velocity.Z <0.01f) - // m_log.DebugFormat("[SCENE PRESENCE]: MovementFlag {0} for {1}", MovementFlag, Name); // If the agent update does move the avatar, then calculate the force ready for the velocity update, @@ -2690,6 +2745,7 @@ namespace OpenSim.Region.Framework.Scenes // held down AGENT_CONTROL_STOP whilst normal walking/running). However, we do not want to update // if the user rotated whilst holding down AGENT_CONTROL_STOP when already still (which locks the // avatar location in place). + if (update_movementflag || (update_rotation && DCFlagKeyPressed && (!AgentControlStopActive || MovementFlag != 0))) { @@ -2706,17 +2762,27 @@ namespace OpenSim.Region.Framework.Scenes } else { - AddNewMovement(agent_control_v3); + if(MovingToTarget || + (Animator.currentControlState != ScenePresenceAnimator.motionControlStates.flying && + Animator.currentControlState != ScenePresenceAnimator.motionControlStates.onsurface) + ) + AddNewMovement(agent_control_v3); + else + { + if (MovementFlag != 0) + AddNewMovement(agent_control_v3); + else + m_delayedStop = Util.GetTimeStampMS() + 200.0; + } } - } - - if (update_movementflag && ParentID == 0) +/* + if (update_movementflag && ParentID == 0 && m_delayedStop < 0) { // m_log.DebugFormat("[SCENE PRESENCE]: Updating movement animations for {0}", Name); Animator.UpdateMovementAnimations(); } - +*/ SendControlsToScripts(flagsForScripts); } @@ -2755,16 +2821,13 @@ namespace OpenSim.Region.Framework.Scenes CameraAtAxis = agentData.CameraAtAxis; CameraLeftAxis = agentData.CameraLeftAxis; CameraUpAxis = agentData.CameraUpAxis; - Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis); - CameraRotation = camRot; - - // The Agent's Draw distance setting - // When we get to the point of re-computing neighbors everytime this - // changes, then start using the agent's drawdistance rather than the - // region's draw distance. - DrawDistance = agentData.Far; + CameraAtAxis.Normalize(); + CameraLeftAxis.Normalize(); + CameraUpAxis.Normalize(); + Quaternion camRot = Util.Axes2Rot(CameraAtAxis, CameraLeftAxis, CameraUpAxis); + CameraRotation = camRot; // Check if Client has camera in 'follow cam' or 'build' mode. // Vector3 camdif = (Vector3.One * Rotation - Vector3.One * CameraRotation); @@ -2890,31 +2953,32 @@ namespace OpenSim.Region.Framework.Scenes Dir_ControlFlags.DIR_CONTROL_FLAG_DOWN)); MovementFlag &= noMovFlagsMask; - AgentControlFlags &= noMovFlagsMask; + uint tmpAgentControlFlags = (uint)m_AgentControlFlags; + tmpAgentControlFlags &= noMovFlagsMask; if (LocalVectorToTarget3D.X < 0) //MoveBack { MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; + tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_BACK; updated = true; } else if (LocalVectorToTarget3D.X > 0) //Move Forward { MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; + tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_FORWARD; updated = true; } if (LocalVectorToTarget3D.Y > 0) //MoveLeft { MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; + tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_LEFT; updated = true; } else if (LocalVectorToTarget3D.Y < 0) //MoveRight { MovementFlag |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; - AgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; + tmpAgentControlFlags |= (uint)Dir_ControlFlags.DIR_CONTROL_FLAG_RIGHT; updated = true; } @@ -2938,6 +3002,7 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE PRESENCE]: HandleMoveToTargetUpdate adding {0} to move vector {1} for {2}", // LocalVectorToTarget3D, agent_control_v3, Name); + m_AgentControlFlags = (AgentManager.ControlFlags) tmpAgentControlFlags; agent_control_v3 += LocalVectorToTarget3D; } catch (Exception e) @@ -2965,6 +3030,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void MoveToTarget(Vector3 pos, bool noFly, bool landAtTarget) { + m_delayedStop = -1; + if (SitGround) StandUp(); @@ -3110,6 +3177,7 @@ namespace OpenSim.Region.Framework.Scenes Vector3 standPos = sitPartWorldPosition + adjustmentForSitPose; m_pos = standPos; + } // We need to wait until we have calculated proper stand positions before sitting up the physical @@ -3124,6 +3192,7 @@ namespace OpenSim.Region.Framework.Scenes part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); SendAvatarDataToAllAgents(); + m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on } // reset to default sitAnimation @@ -3256,6 +3325,7 @@ namespace OpenSim.Region.Framework.Scenes // Moved here to avoid a race with default sit anim // The script event needs to be raised after the default sit anim is set. part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); + m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on } } @@ -3405,6 +3475,7 @@ namespace OpenSim.Region.Framework.Scenes Animator.SetMovementAnimations("SIT"); part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); + m_scene.EventManager.TriggerParcelPrimCountTainted(); // update select/ sat on } public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) @@ -3616,7 +3687,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[SCENE PRESENCE]: Adding new movement {0} with rotation {1}, thisAddSpeedModifier {2} for {3}", // vec, Rotation, thisAddSpeedModifier, Name); - + m_delayedStop = -1; // rotate from avatar coord space to world Quaternion rot = Rotation; if (!Flying && PresenceType != PresenceType.Npc) @@ -3634,7 +3705,7 @@ namespace OpenSim.Region.Framework.Scenes direc.Z = 0f; // Prevent camera WASD up. // odd rescalings - direc *= 0.03f * 128f * SpeedModifier * thisAddSpeedModifier; + direc *= 0.032f * 128f * SpeedModifier * thisAddSpeedModifier; // m_log.DebugFormat("[SCENE PRESENCE]: Force to apply before modification was {0} for {1}", direc, Name); @@ -3699,39 +3770,40 @@ namespace OpenSim.Region.Framework.Scenes if(MovingToTarget) { + m_delayedStop = -1; Vector3 control = Vector3.Zero; if(HandleMoveToTargetUpdate(1f, ref control)) AddNewMovement(control); } + else if(m_delayedStop > 0) + { + if(IsSatOnObject) + m_delayedStop = -1; + else + if(Util.GetTimeStampMS() > m_delayedStop) + AddNewMovement(Vector3.Zero); + } if (Appearance.AvatarSize != m_lastSize) SendAvatarDataToAllAgents(); // Send terse position update if not sitting and position, velocity, or rotation // has changed significantly from last sent update - if (!IsSatOnObject && ( - !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) - || !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) - || !m_pos.ApproxEquals(m_lastPosition, POSITION_LARGETOLERANCE) - // if velocity is zero and it wasn't zero last time, send the update - || (Velocity == Vector3.Zero && m_lastVelocity != Vector3.Zero) - // if position has moved just a little and velocity is very low, send the update - || (!m_pos.ApproxEquals(m_lastPosition, POSITION_SMALLTOLERANCE) && Velocity.LengthSquared() < LOWVELOCITYSQ ) - ) ) - { -/* if (!IsSatOnObject) { // this does need to be more complex later Vector3 vel = Velocity; Vector3 dpos = m_pos - m_lastPosition; - if( Math.Abs(vel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || + if( State != m_lastState || + Math.Abs(vel.X - m_lastVelocity.X) > VELOCITY_TOLERANCE || Math.Abs(vel.Y - m_lastVelocity.Y) > VELOCITY_TOLERANCE || Math.Abs(vel.Z - m_lastVelocity.Z) > VELOCITY_TOLERANCE || Math.Abs(m_bodyRot.X - m_lastRotation.X) > ROTATION_TOLERANCE || Math.Abs(m_bodyRot.Y - m_lastRotation.Y) > ROTATION_TOLERANCE || Math.Abs(m_bodyRot.Z - m_lastRotation.Z) > ROTATION_TOLERANCE || + + (vel == Vector3.Zero && m_lastVelocity != Vector3.Zero) || Math.Abs(dpos.X) > POSITION_LARGETOLERANCE || Math.Abs(dpos.Y) > POSITION_LARGETOLERANCE || @@ -3741,11 +3813,15 @@ namespace OpenSim.Region.Framework.Scenes Math.Abs(dpos.Y) > POSITION_SMALLTOLERANCE || Math.Abs(dpos.Z) > POSITION_SMALLTOLERANCE) && vel.LengthSquared() < LOWVELOCITYSQ - )) + ) || + + Math.Abs(CollisionPlane.X - m_lastCollisionPlane.X) > POSITION_SMALLTOLERANCE || + Math.Abs(CollisionPlane.Y - m_lastCollisionPlane.Y) > POSITION_SMALLTOLERANCE || + Math.Abs(CollisionPlane.W - m_lastCollisionPlane.W) > POSITION_SMALLTOLERANCE + ) { -*/ SendTerseUpdateToAllClients(); -// } + } } CheckForSignificantMovement(); } @@ -3841,11 +3917,14 @@ namespace OpenSim.Region.Framework.Scenes /// public void SendTerseUpdateToAllClients() { - m_scene.ForEachScenePresence(SendTerseUpdateToAgent); - // Update the "last" values + m_lastState = State; m_lastPosition = m_pos; m_lastRotation = m_bodyRot; m_lastVelocity = Velocity; + m_lastCollisionPlane = CollisionPlane; + + m_scene.ForEachScenePresence(SendTerseUpdateToAgent); + // Update the "last" values TriggerScenePresenceUpdated(); } @@ -3968,7 +4047,7 @@ namespace OpenSim.Region.Framework.Scenes int count = 0; foreach (ScenePresence p in presences) { - p.ControllingClient.SendAvatarDataImmediate(this); + p.ControllingClient.SendEntityFullUpdateImmediate(this); if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) // either just kill the object // p.ControllingClient.SendKillObject(new List {LocalId}); @@ -3981,7 +4060,7 @@ namespace OpenSim.Region.Framework.Scenes public void SendInitialAvatarDataToAgent(ScenePresence p) { - p.ControllingClient.SendAvatarDataImmediate(this); + p.ControllingClient.SendEntityFullUpdateImmediate(this); if (p != this && ParcelHideThisAvatar && currentParcelUUID != p.currentParcelUUID && !p.IsViewerUIGod) // either just kill the object // p.ControllingClient.SendKillObject(new List {LocalId}); @@ -3998,12 +4077,12 @@ namespace OpenSim.Region.Framework.Scenes //m_log.DebugFormat("[SCENE PRESENCE] SendAvatarDataToAgent from {0} ({1}) to {2} ({3})", Name, UUID, avatar.Name, avatar.UUID); if (ParcelHideThisAvatar && currentParcelUUID != avatar.currentParcelUUID && !avatar.IsViewerUIGod) return; - avatar.ControllingClient.SendAvatarDataImmediate(this); + avatar.ControllingClient.SendEntityFullUpdateImmediate(this); } public void SendAvatarDataToAgentNF(ScenePresence avatar) { - avatar.ControllingClient.SendAvatarDataImmediate(this); + avatar.ControllingClient.SendEntityFullUpdateImmediate(this); } /// @@ -4353,72 +4432,75 @@ namespace OpenSim.Region.Framework.Scenes } - /* useless. Either use MakeChild or delete the presence - public void Reset() - { - // m_log.DebugFormat("[SCENE PRESENCE]: Resetting {0} in {1}", Name, Scene.RegionInfo.RegionName); - - // Put the child agent back at the center - AbsolutePosition - = new Vector3(((float)m_scene.RegionInfo.RegionSizeX * 0.5f), ((float)m_scene.RegionInfo.RegionSizeY * 0.5f), 70); - - Animator.ResetAnimations(); - } - */ /// /// Computes which child agents to close when the scene presence moves to another region. /// Removes those regions from m_knownRegions. /// - /// The new region's x on the map - /// The new region's y on the map + /// The new region's handle + /// The new region's size x + /// The new region's size y /// - public void CloseChildAgents(bool logout, ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY) + public List GetChildAgentsToClose(ulong newRegionHandle, int newRegionSizeX, int newRegionSizeY) { - uint newRegionX, newRegionY; + ulong curRegionHandle = m_scene.RegionInfo.RegionHandle; List byebyeRegions = new List(); + + if(newRegionHandle == curRegionHandle) //?? + return byebyeRegions; + + uint newRegionX, newRegionY; List knownRegions = KnownRegionHandles; m_log.DebugFormat( "[SCENE PRESENCE]: Closing child agents. Checking {0} regions in {1}", knownRegions.Count, Scene.RegionInfo.RegionName); Util.RegionHandleToRegionLoc(newRegionHandle, out newRegionX, out newRegionY); - uint x, y; spRegionSizeInfo regInfo; foreach (ulong handle in knownRegions) { - // Don't close the agent on this region yet - if (handle != Scene.RegionInfo.RegionHandle) + if(newRegionY == 0) // HG + byebyeRegions.Add(handle); + else if(handle == curRegionHandle) { - if (logout) + RegionInfo curreg = m_scene.RegionInfo; + if (Util.IsOutsideView(255, curreg.RegionLocX, newRegionX, curreg.RegionLocY, newRegionY, + (int)curreg.RegionSizeX, (int)curreg.RegionSizeX, newRegionSizeX, newRegionSizeY)) + { byebyeRegions.Add(handle); + } + } + else + { + Util.RegionHandleToRegionLoc(handle, out x, out y); + if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo)) + { +// if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, + // for now need to close all but first order bc RegionViewDistance it the target value not ours + if (Util.IsOutsideView(255, x, newRegionX, y, newRegionY, + regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY)) + { + byebyeRegions.Add(handle); + } + } else { - Util.RegionHandleToRegionLoc(handle, out x, out y); - if (m_knownChildRegionsSizeInfo.TryGetValue(handle, out regInfo)) +// if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, + if (Util.IsOutsideView(255, x, newRegionX, y, newRegionY, + (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY)) { - if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, - regInfo.sizeX, regInfo.sizeY, newRegionSizeX, newRegionSizeY)) - { - byebyeRegions.Add(handle); - } - } - else - { - if (Util.IsOutsideView(RegionViewDistance, x, newRegionX, y, newRegionY, - (int)Constants.RegionSize, (int)Constants.RegionSize, newRegionSizeX, newRegionSizeY)) - { - byebyeRegions.Add(handle); - // this should not be here -// if(eventQueue != null) -// eventQueue.DisableSimulator(handle,UUID); - } + byebyeRegions.Add(handle); } } } } + return byebyeRegions; + } + public void CloseChildAgents(List byebyeRegions) + { + byebyeRegions.Remove(Scene.RegionInfo.RegionHandle); if (byebyeRegions.Count > 0) { m_log.Debug("[SCENE PRESENCE]: Closing " + byebyeRegions.Count + " child agents"); @@ -4624,6 +4706,11 @@ namespace OpenSim.Region.Framework.Scenes { cAgent.CrossingFlags = crossingFlags; cAgent.CrossingFlags |= 1; + cAgent.CrossExtraFlags = 0; + if((LastCommands & ScriptControlled.CONTROL_LBUTTON) != 0) + cAgent.CrossExtraFlags |= 1; + if((LastCommands & ScriptControlled.CONTROL_ML_LBUTTON) != 0) + cAgent.CrossExtraFlags |= 2; } else cAgent.CrossingFlags = 0; @@ -4633,7 +4720,10 @@ namespace OpenSim.Region.Framework.Scenes cAgent.agentCOF = COF; cAgent.ActiveGroupID = ControllingClient.ActiveGroupId; cAgent.ActiveGroupName = ControllingClient.ActiveGroupName; - cAgent.ActiveGroupTitle = Grouptitle; + if(Grouptitle == null) + cAgent.ActiveGroupTitle = String.Empty; + else + cAgent.ActiveGroupTitle = Grouptitle; } } @@ -4735,6 +4825,15 @@ namespace OpenSim.Region.Framework.Scenes crossingFlags = cAgent.CrossingFlags; gotCrossUpdate = (crossingFlags != 0); + if(gotCrossUpdate) + { + LastCommands &= ~(ScriptControlled.CONTROL_LBUTTON | ScriptControlled.CONTROL_ML_LBUTTON); + if((cAgent.CrossExtraFlags & 1) != 0) + LastCommands |= ScriptControlled.CONTROL_LBUTTON; + if((cAgent.CrossExtraFlags & 2) != 0) + LastCommands |= ScriptControlled.CONTROL_ML_LBUTTON; + MouseDown = (cAgent.CrossExtraFlags & 3) != 0; + } haveGroupInformation = false; // using this as protocol detection don't want to mess with the numbers for now @@ -4829,6 +4928,7 @@ namespace OpenSim.Region.Framework.Scenes PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong PhysicsActor.SubscribeEvents(100); PhysicsActor.LocalID = LocalId; + PhysicsActor.SetAlwaysRun = m_setAlwaysRun; } private void OutOfBoundsCall(Vector3 pos) @@ -4866,8 +4966,8 @@ namespace OpenSim.Region.Framework.Scenes // if (m_updateCount > 0) // { - if (Animator != null && Animator.UpdateMovementAnimations()) - TriggerScenePresenceUpdated(); +// if (Animator != null && Animator.UpdateMovementAnimations()) +// TriggerScenePresenceUpdated(); // m_updateCount--; // } @@ -5703,29 +5803,21 @@ namespace OpenSim.Region.Framework.Scenes if (scriptedcontrols.Count <= 0) return; - ScriptControlled allflags = ScriptControlled.CONTROL_ZERO; - - if (MouseDown) + ScriptControlled allflags; + // convert mouse from edge to level + if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || + (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) { - allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); - if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_UP) != 0 || (flags & unchecked((uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_UP)) != 0) - { - allflags = ScriptControlled.CONTROL_ZERO; - MouseDown = true; - } + allflags = ScriptControlled.CONTROL_ZERO; } + else // recover last state of mouse + allflags = LastCommands & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON); if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_ML_LBUTTON_DOWN) != 0) - { allflags |= ScriptControlled.CONTROL_ML_LBUTTON; - MouseDown = true; - } if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_LBUTTON_DOWN) != 0) - { allflags |= ScriptControlled.CONTROL_LBUTTON; - MouseDown = true; - } // find all activated controls, whether the scripts are interested in them or not if ((flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_AT_POS) != 0 || (flags & (uint)AgentManager.ControlFlags.AGENT_CONTROL_NUDGE_AT_POS) != 0) @@ -5789,6 +5881,7 @@ namespace OpenSim.Region.Framework.Scenes } LastCommands = allflags; + MouseDown = (allflags & (ScriptControlled.CONTROL_ML_LBUTTON | ScriptControlled.CONTROL_LBUTTON)) != 0; } } @@ -6440,7 +6533,7 @@ namespace OpenSim.Region.Framework.Scenes if (check) { // check is relative to current parcel only - if (currentParcelUUID == null || oldhide == currentParcelHide) + if (oldhide == currentParcelHide) return; allpresences = m_scene.GetScenePresences(); diff --git a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs index 7f7977ea25..41f3ef4020 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/CoalescedSceneObjectsSerializer.cs @@ -86,9 +86,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteStartElement("CoalescedObject"); - writer.WriteAttributeString("x", size.X.ToString()); - writer.WriteAttributeString("y", size.Y.ToString()); - writer.WriteAttributeString("z", size.Z.ToString()); + writer.WriteAttributeString("x", size.X.ToString(Culture.FormatProvider)); + writer.WriteAttributeString("y", size.Y.ToString(Culture.FormatProvider)); + writer.WriteAttributeString("z", size.Z.ToString(Culture.FormatProvider)); // Embed the offsets into the group XML for (int i = 0; i < coaObjects.Count; i++) @@ -100,9 +100,9 @@ namespace OpenSim.Region.Framework.Scenes.Serialization // i, obj.Name); writer.WriteStartElement("SceneObjectGroup"); - writer.WriteAttributeString("offsetx", offsets[i].X.ToString()); - writer.WriteAttributeString("offsety", offsets[i].Y.ToString()); - writer.WriteAttributeString("offsetz", offsets[i].Z.ToString()); + writer.WriteAttributeString("offsetx", offsets[i].X.ToString(Culture.FormatProvider)); + writer.WriteAttributeString("offsety", offsets[i].Y.ToString(Culture.FormatProvider)); + writer.WriteAttributeString("offsetz", offsets[i].Z.ToString(Culture.FormatProvider)); SceneObjectSerializer.ToOriginalXmlFormat(obj, writer, doScriptStates); diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index b8d210cac6..82bbe6f384 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -65,7 +65,8 @@ namespace OpenSim.Region.Framework.Scenes.Serialization { using (XmlReader reader = XmlReader.Create(wrappedReader, new XmlReaderSettings() { IgnoreWhitespace = true, ConformanceLevel = ConformanceLevel.Fragment })) { - try { + try + { return FromOriginalXmlFormat(reader); } catch (Exception e) @@ -109,12 +110,24 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } while (reader.ReadToNextSibling("Part")); + reader.ReadEndElement(); } + if (reader.Name == "KeyframeMotion" && reader.NodeType == XmlNodeType.Element) + { + + string innerkeytxt = reader.ReadElementContentAsString(); + sceneObject.RootPart.KeyframeMotion = + KeyframeMotion.FromData(sceneObject, Convert.FromBase64String(innerkeytxt)); + } + else + sceneObject.RootPart.KeyframeMotion = null; + // Script state may, or may not, exist. Not having any, is NOT // ever a problem. sceneObject.LoadScriptState(reader); + sceneObject.InvalidateDeepEffectivePerms(); return sceneObject; } @@ -210,9 +223,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteEndElement(); // OtherParts + if (sceneObject.RootPart.KeyframeMotion != null) + { + Byte[] data = sceneObject.RootPart.KeyframeMotion.Serialize(); + + writer.WriteStartElement(String.Empty, "KeyframeMotion", String.Empty); + writer.WriteBase64(data, 0, data.Length); + writer.WriteEndElement(); + } + if (doScriptStates) sceneObject.SaveScriptedState(writer); + if (!noRootElement) writer.WriteEndElement(); // SceneObjectGroup @@ -278,7 +301,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization // Script state may, or may not, exist. Not having any, is NOT // ever a problem. sceneObject.LoadScriptState(doc); - +// sceneObject.AggregatePerms(); return sceneObject; } catch (Exception e) @@ -453,9 +476,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization m_SOPXmlProcessors.Add("Torque", ProcessTorque); m_SOPXmlProcessors.Add("VolumeDetectActive", ProcessVolumeDetectActive); - m_SOPXmlProcessors.Add("Vehicle", ProcessVehicle); + m_SOPXmlProcessors.Add("PhysicsInertia", ProcessPhysicsInertia); + m_SOPXmlProcessors.Add("RotationAxisLocks", ProcessRotationAxisLocks); m_SOPXmlProcessors.Add("PhysicsShapeType", ProcessPhysicsShapeType); m_SOPXmlProcessors.Add("Density", ProcessDensity); @@ -781,6 +805,23 @@ namespace OpenSim.Region.Framework.Scenes.Serialization } } + private static void ProcessPhysicsInertia(SceneObjectPart obj, XmlReader reader) + { + PhysicsInertiaData pdata = PhysicsInertiaData.FromXml2(reader); + + if (pdata == null) + { + obj.PhysicsInertia = null; + m_log.DebugFormat( + "[SceneObjectSerializer]: Parsing PhysicsInertiaData for object part {0} {1} encountered errors. Please see earlier log entries.", + obj.Name, obj.UUID); + } + else + { + obj.PhysicsInertia = pdata; + } + } + private static void ProcessShape(SceneObjectPart obj, XmlReader reader) { List errorNodeNames; @@ -1343,8 +1384,27 @@ namespace OpenSim.Region.Framework.Scenes.Serialization private static void ProcessShpMedia(PrimitiveBaseShape shp, XmlReader reader) { - string value = reader.ReadElementContentAsString("Media", String.Empty); - shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); + string value = String.Empty; + try + { + // The STANDARD content of Media elemet is escaped XML string (with > etc). + value = reader.ReadElementContentAsString("Media", String.Empty); + shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); + } + catch (XmlException e) + { + // There are versions of OAR files that contain unquoted XML. + // ie ONE comercial fork that never wanted their oars to be read by our code + try + { + value = reader.ReadInnerXml(); + shp.Media = PrimitiveBaseShape.MediaList.FromXml(value); + } + catch + { + m_log.ErrorFormat("[SERIALIZER] Failed parsing halcyon MOAP information"); + } + } } #endregion @@ -1422,10 +1482,10 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("Description", sop.Description); writer.WriteStartElement("Color"); - writer.WriteElementString("R", sop.Color.R.ToString(Utils.EnUsCulture)); - writer.WriteElementString("G", sop.Color.G.ToString(Utils.EnUsCulture)); - writer.WriteElementString("B", sop.Color.B.ToString(Utils.EnUsCulture)); - writer.WriteElementString("A", sop.Color.A.ToString(Utils.EnUsCulture)); + writer.WriteElementString("R", sop.Color.R.ToString(Culture.FormatProvider)); + writer.WriteElementString("G", sop.Color.G.ToString(Culture.FormatProvider)); + writer.WriteElementString("B", sop.Color.B.ToString(Culture.FormatProvider)); + writer.WriteElementString("A", sop.Color.A.ToString(Culture.FormatProvider)); writer.WriteEndElement(); writer.WriteElementString("Text", sop.Text); @@ -1468,7 +1528,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("NextOwnerMask", sop.NextOwnerMask.ToString()); WriteFlags(writer, "Flags", sop.Flags.ToString(), options); WriteUUID(writer, "CollisionSound", sop.CollisionSound, options); - writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString()); + writer.WriteElementString("CollisionSoundVolume", sop.CollisionSoundVolume.ToString(Culture.FormatProvider)); if (sop.MediaUrl != null) writer.WriteElementString("MediaUrl", sop.MediaUrl.ToString()); WriteVector(writer, "AttachedPos", sop.AttachedPos); @@ -1488,7 +1548,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization writer.WriteElementString("PayPrice3", sop.PayPrice[3].ToString()); writer.WriteElementString("PayPrice4", sop.PayPrice[4].ToString()); - writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString()); + writer.WriteElementString("Buoyancy", sop.Buoyancy.ToString(Culture.FormatProvider)); WriteVector(writer, "Force", sop.Force); WriteVector(writer, "Torque", sop.Torque); @@ -1498,26 +1558,29 @@ namespace OpenSim.Region.Framework.Scenes.Serialization if (sop.VehicleParams != null) sop.VehicleParams.ToXml2(writer); + if (sop.PhysicsInertia != null) + sop.PhysicsInertia.ToXml2(writer); + if(sop.RotationAxisLocks != 0) writer.WriteElementString("RotationAxisLocks", sop.RotationAxisLocks.ToString().ToLower()); writer.WriteElementString("PhysicsShapeType", sop.PhysicsShapeType.ToString().ToLower()); if (sop.Density != 1000.0f) - writer.WriteElementString("Density", sop.Density.ToString().ToLower()); + writer.WriteElementString("Density", sop.Density.ToString(Culture.FormatProvider)); if (sop.Friction != 0.6f) - writer.WriteElementString("Friction", sop.Friction.ToString().ToLower()); + writer.WriteElementString("Friction", sop.Friction.ToString(Culture.FormatProvider)); if (sop.Restitution != 0.5f) - writer.WriteElementString("Bounce", sop.Restitution.ToString().ToLower()); + writer.WriteElementString("Bounce", sop.Restitution.ToString(Culture.FormatProvider)); if (sop.GravityModifier != 1.0f) - writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString().ToLower()); + writer.WriteElementString("GravityModifier", sop.GravityModifier.ToString(Culture.FormatProvider)); WriteVector(writer, "CameraEyeOffset", sop.GetCameraEyeOffset()); WriteVector(writer, "CameraAtOffset", sop.GetCameraAtOffset()); // if (sop.Sound != UUID.Zero) force it till sop crossing does clear it on child prim { WriteUUID(writer, "SoundID", sop.Sound, options); - writer.WriteElementString("SoundGain", sop.SoundGain.ToString().ToLower()); + writer.WriteElementString("SoundGain", sop.SoundGain.ToString(Culture.FormatProvider)); writer.WriteElementString("SoundFlags", sop.SoundFlags.ToString().ToLower()); - writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString().ToLower()); + writer.WriteElementString("SoundRadius", sop.SoundRadius.ToString(Culture.FormatProvider)); } writer.WriteElementString("SoundQueueing", sop.SoundQueueing.ToString().ToLower()); @@ -1537,19 +1600,19 @@ namespace OpenSim.Region.Framework.Scenes.Serialization static void WriteVector(XmlTextWriter writer, string name, Vector3 vec) { writer.WriteStartElement(name); - writer.WriteElementString("X", vec.X.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Y", vec.Y.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Z", vec.Z.ToString(Utils.EnUsCulture)); + writer.WriteElementString("X", vec.X.ToString(Culture.FormatProvider)); + writer.WriteElementString("Y", vec.Y.ToString(Culture.FormatProvider)); + writer.WriteElementString("Z", vec.Z.ToString(Culture.FormatProvider)); writer.WriteEndElement(); } static void WriteQuaternion(XmlTextWriter writer, string name, Quaternion quat) { writer.WriteStartElement(name); - writer.WriteElementString("X", quat.X.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Y", quat.Y.ToString(Utils.EnUsCulture)); - writer.WriteElementString("Z", quat.Z.ToString(Utils.EnUsCulture)); - writer.WriteElementString("W", quat.W.ToString(Utils.EnUsCulture)); + writer.WriteElementString("X", quat.X.ToString(Culture.FormatProvider)); + writer.WriteElementString("Y", quat.Y.ToString(Culture.FormatProvider)); + writer.WriteElementString("Z", quat.Z.ToString(Culture.FormatProvider)); + writer.WriteElementString("W", quat.W.ToString(Culture.FormatProvider)); writer.WriteEndElement(); } @@ -1691,22 +1754,22 @@ namespace OpenSim.Region.Framework.Scenes.Serialization // Don't serialize SculptData. It's just a copy of the asset, which can be loaded separately using 'SculptTexture'. writer.WriteElementString("FlexiSoftness", shp.FlexiSoftness.ToString()); - writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString()); - writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString()); - writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString()); - writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString()); - writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString()); - writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString()); - writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString()); + writer.WriteElementString("FlexiTension", shp.FlexiTension.ToString(Culture.FormatProvider)); + writer.WriteElementString("FlexiDrag", shp.FlexiDrag.ToString(Culture.FormatProvider)); + writer.WriteElementString("FlexiGravity", shp.FlexiGravity.ToString(Culture.FormatProvider)); + writer.WriteElementString("FlexiWind", shp.FlexiWind.ToString(Culture.FormatProvider)); + writer.WriteElementString("FlexiForceX", shp.FlexiForceX.ToString(Culture.FormatProvider)); + writer.WriteElementString("FlexiForceY", shp.FlexiForceY.ToString(Culture.FormatProvider)); + writer.WriteElementString("FlexiForceZ", shp.FlexiForceZ.ToString(Culture.FormatProvider)); - writer.WriteElementString("LightColorR", shp.LightColorR.ToString()); - writer.WriteElementString("LightColorG", shp.LightColorG.ToString()); - writer.WriteElementString("LightColorB", shp.LightColorB.ToString()); - writer.WriteElementString("LightColorA", shp.LightColorA.ToString()); - writer.WriteElementString("LightRadius", shp.LightRadius.ToString()); - writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString()); - writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString()); - writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString()); + writer.WriteElementString("LightColorR", shp.LightColorR.ToString(Culture.FormatProvider)); + writer.WriteElementString("LightColorG", shp.LightColorG.ToString(Culture.FormatProvider)); + writer.WriteElementString("LightColorB", shp.LightColorB.ToString(Culture.FormatProvider)); + writer.WriteElementString("LightColorA", shp.LightColorA.ToString(Culture.FormatProvider)); + writer.WriteElementString("LightRadius", shp.LightRadius.ToString(Culture.FormatProvider)); + writer.WriteElementString("LightCutoff", shp.LightCutoff.ToString(Culture.FormatProvider)); + writer.WriteElementString("LightFalloff", shp.LightFalloff.ToString(Culture.FormatProvider)); + writer.WriteElementString("LightIntensity", shp.LightIntensity.ToString(Culture.FormatProvider)); writer.WriteElementString("FlexiEntry", shp.FlexiEntry.ToString().ToLower()); writer.WriteElementString("LightEntry", shp.LightEntry.ToString().ToLower()); @@ -1739,6 +1802,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization reader.ReadEndElement(); // SceneObjectPart + obj.AggregateInnerPerms(); // m_log.DebugFormat("[SceneObjectSerializer]: parsed SOP {0} {1}", obj.Name, obj.UUID); return obj; } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs index 01bc491566..34fdb6df8f 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneXmlLoader.cs @@ -70,6 +70,7 @@ namespace OpenSim.Region.Framework.Scenes.Serialization //obj.RegenerateFullIDs(); scene.AddNewSceneObject(obj, true); + obj.InvalidateDeepEffectivePerms(); } } else diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs index 56723bfd95..4d2eb3fe89 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneGraphTests.cs @@ -67,7 +67,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneObjectGroup dupeSo = scene.SceneGraph.DuplicateObject( - part1.LocalId, new Vector3(10, 0, 0), 0, ownerId, UUID.Zero, Quaternion.Identity); + part1.LocalId, new Vector3(10, 0, 0), ownerId, UUID.Zero, Quaternion.Identity, false); Assert.That(dupeSo.Parts.Length, Is.EqualTo(2)); SceneObjectPart dupePart1 = dupeSo.GetLinkNumPart(1); diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs index e1e973cdd3..abf8c488c5 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectCrossingTests.cs @@ -157,29 +157,28 @@ namespace OpenSim.Region.Framework.Scenes.Tests // Cross sceneA.SceneGraph.UpdatePrimGroupPosition( - so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), userId); + so1.LocalId, new Vector3(so1StartPos.X, so1StartPos.Y - 20, so1StartPos.Z), sp1SceneA.ControllingClient); // crossing is async Thread.Sleep(500); SceneObjectGroup so1PostCross; - { - ScenePresence sp1SceneAPostCross = sceneA.GetScenePresence(userId); - Assert.IsTrue(sp1SceneAPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly false"); + ScenePresence sp1SceneAPostCross = sceneA.GetScenePresence(userId); + Assert.IsTrue(sp1SceneAPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly false"); - ScenePresence sp1SceneBPostCross = sceneB.GetScenePresence(userId); - TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient); - sceneBTc.CompleteMovement(); + ScenePresence sp1SceneBPostCross = sceneB.GetScenePresence(userId); + TestClient sceneBTc = ((TestClient)sp1SceneBPostCross.ControllingClient); + sceneBTc.CompleteMovement(); - Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true"); - Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject); + Assert.IsFalse(sp1SceneBPostCross.IsChildAgent, "sp1SceneAPostCross.IsChildAgent unexpectedly true"); + Assert.IsTrue(sp1SceneBPostCross.IsSatOnObject); + + Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id), "uck"); + so1PostCross = sceneB.GetSceneObjectGroup(so1Id); + Assert.NotNull(so1PostCross); + Assert.AreEqual(1, so1PostCross.GetSittingAvatarsCount()); - Assert.IsNull(sceneA.GetSceneObjectGroup(so1Id), "uck"); - so1PostCross = sceneB.GetSceneObjectGroup(so1Id); - Assert.NotNull(so1PostCross); - Assert.AreEqual(1, so1PostCross.GetSittingAvatarsCount()); - } Vector3 so1PostCrossPos = so1PostCross.AbsolutePosition; @@ -187,7 +186,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests // Recross sceneB.SceneGraph.UpdatePrimGroupPosition( - so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), userId); + so1PostCross.LocalId, new Vector3(so1PostCrossPos.X, so1PostCrossPos.Y + 20, so1PostCrossPos.Z), sp1SceneBPostCross.ControllingClient); // crossing is async Thread.Sleep(500); @@ -255,13 +254,19 @@ namespace OpenSim.Region.Framework.Scenes.Tests lmmA.EventManagerOnNoLandDataFromStorage(); lmmB.EventManagerOnNoLandDataFromStorage(); + AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); + TestClient tc = new TestClient(acd, sceneA); + List destinationTestClients = new List(); + EntityTransferHelpers.SetupInformClientOfNeighbourTriggersNeighbourClientCreate(tc, destinationTestClients); + ScenePresence sp1SceneA = SceneHelpers.AddScenePresence(sceneA, tc, acd); + SceneObjectGroup so1 = SceneHelpers.AddSceneObject(sceneA, 1, userId, "", sceneObjectIdTail); UUID so1Id = so1.UUID; so1.AbsolutePosition = new Vector3(128, 10, 20); // Cross with a negative value. We must make this call rather than setting AbsolutePosition directly // because only this will execute permission checks in the source region. - sceneA.SceneGraph.UpdatePrimGroupPosition(so1.LocalId, new Vector3(128, -10, 20), userId); + sceneA.SceneGraph.UpdatePrimGroupPosition(so1.LocalId, new Vector3(128, -10, 20), sp1SceneA.ControllingClient); // crossing is async Thread.Sleep(500); diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs index 42d91b954a..d650c4346d 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceAnimationTests.cs @@ -60,7 +60,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests TestScene scene = new SceneHelpers().SetupScene(); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); sp.Flying = true; - sp.PhysicsCollisionUpdate(new CollisionEventUpdate()); + sp.Animator.UpdateMovementAnimations(); Assert.That(sp.Animator.CurrentMovementAnimation, Is.EqualTo("HOVER")); } diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs index 045fd3cec5..4ce6a95f36 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/SceneStatisticsTests.cs @@ -54,8 +54,8 @@ namespace OpenSim.Region.Framework.Scenes.Tests UUID ownerId = TestHelpers.ParseTail(0x1); SceneObjectGroup so1 = SceneHelpers.CreateSceneObject(3, ownerId, "so1", 0x10); - so1.ScriptSetPhysicsStatus(true); m_scene.AddSceneObject(so1); + so1.ScriptSetPhysicsStatus(true); Assert.That(m_scene.SceneGraph.GetTotalObjectsCount(), Is.EqualTo(3)); Assert.That(m_scene.SceneGraph.GetActiveObjectsCount(), Is.EqualTo(3)); diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 93406cbb79..80d3f62339 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -65,7 +65,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// The gathered uuids. public IDictionary GatheredUuids { get; private set; } - + public HashSet FailedUUIDs { get; private set; } + public HashSet UncertainAssetsUUIDs { get; private set; } + public int possibleNotAssetCount { get; set; } + public int ErrorCount { get; private set; } /// /// Gets the next UUID to inspect. /// @@ -92,7 +95,10 @@ namespace OpenSim.Region.Framework.Scenes /// /// Asset service. /// - public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary()) {} + public UuidGatherer(IAssetService assetService) : this(assetService, new Dictionary(), + new HashSet (),new HashSet ()) {} + public UuidGatherer(IAssetService assetService, IDictionary collector) : this(assetService, collector, + new HashSet (), new HashSet ()) {} /// /// Initializes a new instance of the class. @@ -101,16 +107,20 @@ namespace OpenSim.Region.Framework.Scenes /// Asset service. /// /// - /// Gathered UUIDs will be collected in this dictinaory. + /// Gathered UUIDs will be collected in this dictionary. /// It can be pre-populated if you want to stop the gatherer from analyzing assets that have already been fetched and inspected. /// - public UuidGatherer(IAssetService assetService, IDictionary collector) + public UuidGatherer(IAssetService assetService, IDictionary collector, HashSet failedIDs, HashSet uncertainAssetsUUIDs) { m_assetService = assetService; GatheredUuids = collector; // FIXME: Not efficient for searching, can improve. m_assetUuidsToInspect = new Queue(); + FailedUUIDs = failedIDs; + UncertainAssetsUUIDs = uncertainAssetsUUIDs; + ErrorCount = 0; + possibleNotAssetCount = 0; } /// @@ -120,6 +130,19 @@ namespace OpenSim.Region.Framework.Scenes /// UUID. public bool AddForInspection(UUID uuid) { + if(uuid == UUID.Zero) + return false; + + if(FailedUUIDs.Contains(uuid)) + { + if(UncertainAssetsUUIDs.Contains(uuid)) + possibleNotAssetCount++; + else + ErrorCount++; + return false; + } + if(GatheredUuids.ContainsKey(uuid)) + return false; if (m_assetUuidsToInspect.Contains(uuid)) return false; @@ -141,7 +164,9 @@ namespace OpenSim.Region.Framework.Scenes public void AddForInspection(SceneObjectGroup sceneObject) { // m_log.DebugFormat( - // "[ASSET GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); + // "[UUID GATHERER]: Getting assets for object {0}, {1}", sceneObject.Name, sceneObject.UUID); + if(sceneObject.IsDeleted) + return; SceneObjectPart[] parts = sceneObject.Parts; for (int i = 0; i < parts.Length; i++) @@ -149,7 +174,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart part = parts[i]; // m_log.DebugFormat( - // "[ARCHIVER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); + // "[UUID GATHERER]: Getting part {0}, {1} for object {2}", part.Name, part.UUID, sceneObject.UUID); try { @@ -207,9 +232,7 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat( // "[ARCHIVER]: Analysing item {0} asset type {1} in {2} {3}", // tii.Name, tii.Type, part.Name, part.UUID); - - if (!GatheredUuids.ContainsKey(tii.AssetID)) - AddForInspection(tii.AssetID, (sbyte)tii.Type); + AddForInspection(tii.AssetID, (sbyte)tii.Type); } // FIXME: We need to make gathering modular but we cannot yet, since gatherers are not guaranteed @@ -225,9 +248,6 @@ namespace OpenSim.Region.Framework.Scenes catch (Exception e) { m_log.ErrorFormat("[UUID GATHERER]: Failed to get part - {0}", e); - m_log.DebugFormat( - "[UUID GATHERER]: Texture entry length for prim was {0} (min is 46)", - part.Shape.TextureEntry.Length); } } } @@ -278,55 +298,112 @@ namespace OpenSim.Region.Framework.Scenes /// The uuid of the asset for which to gather referenced assets private void GetAssetUuids(UUID assetUuid) { + if(assetUuid == UUID.Zero) + return; + + if(FailedUUIDs.Contains(assetUuid)) + { + if(UncertainAssetsUUIDs.Contains(assetUuid)) + possibleNotAssetCount++; + else + ErrorCount++; + return; + } + // avoid infinite loops if (GatheredUuids.ContainsKey(assetUuid)) return; + AssetBase assetBase; try { - AssetBase assetBase = GetAsset(assetUuid); + assetBase = GetAsset(assetUuid); + } + catch (Exception e) + { + m_log.ErrorFormat("[UUID GATHERER]: Failed to get asset {0} : {1}", assetUuid, e.Message); + ErrorCount++; + FailedUUIDs.Add(assetUuid); + return; + } - if (null != assetBase) + if(assetBase == null) + { +// m_log.ErrorFormat("[UUID GATHERER]: asset {0} not found", assetUuid); + FailedUUIDs.Add(assetUuid); + if(UncertainAssetsUUIDs.Contains(assetUuid)) + possibleNotAssetCount++; + else + ErrorCount++; + return; + } + + if(UncertainAssetsUUIDs.Contains(assetUuid)) + UncertainAssetsUUIDs.Remove(assetUuid); + + sbyte assetType = assetBase.Type; + + if(assetBase.Data == null || assetBase.Data.Length == 0) + { +// m_log.ErrorFormat("[UUID GATHERER]: asset {0}, type {1} has no data", assetUuid, assetType); + ErrorCount++; + FailedUUIDs.Add(assetUuid); + return; + } + + GatheredUuids[assetUuid] = assetType; + try + { + if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) { - sbyte assetType = assetBase.Type; - GatheredUuids[assetUuid] = assetType; - - if ((sbyte)AssetType.Bodypart == assetType || (sbyte)AssetType.Clothing == assetType) - { - RecordWearableAssetUuids(assetBase); - } - else if ((sbyte)AssetType.Gesture == assetType) - { - RecordGestureAssetUuids(assetBase); - } - else if ((sbyte)AssetType.Notecard == assetType) - { - RecordTextEmbeddedAssetUuids(assetBase); - } - else if ((sbyte)AssetType.LSLText == assetType) - { - RecordTextEmbeddedAssetUuids(assetBase); - } - else if ((sbyte)OpenSimAssetType.Material == assetType) - { - RecordMaterialAssetUuids(assetBase); - } - else if ((sbyte)AssetType.Object == assetType) - { - RecordSceneObjectAssetUuids(assetBase); - } + RecordWearableAssetUuids(assetBase); + } + else if ((sbyte)AssetType.Gesture == assetType) + { + RecordGestureAssetUuids(assetBase); + } + else if ((sbyte)AssetType.Notecard == assetType) + { + RecordTextEmbeddedAssetUuids(assetBase); + } + else if ((sbyte)AssetType.LSLText == assetType) + { + RecordTextEmbeddedAssetUuids(assetBase); + } + else if ((sbyte)OpenSimAssetType.Material == assetType) + { + RecordMaterialAssetUuids(assetBase); + } + else if ((sbyte)AssetType.Object == assetType) + { + RecordSceneObjectAssetUuids(assetBase); } } - catch (Exception) + catch (Exception e) { - m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset id {0}", assetUuid); - throw; + m_log.ErrorFormat("[UUID GATHERER]: Failed to gather uuids for asset with id {0} type {1}: {2}", assetUuid, assetType, e.Message); + GatheredUuids.Remove(assetUuid); + ErrorCount++; + FailedUUIDs.Add(assetUuid); } } private void AddForInspection(UUID assetUuid, sbyte assetType) { + if(assetUuid == UUID.Zero) + return; + // Here, we want to collect uuids which require further asset fetches but mark the others as gathered + if(FailedUUIDs.Contains(assetUuid)) + { + if(UncertainAssetsUUIDs.Contains(assetUuid)) + possibleNotAssetCount++; + else + ErrorCount++; + return; + } + if(GatheredUuids.ContainsKey(assetUuid)) + return; try { if ((sbyte)AssetType.Bodypart == assetType @@ -458,8 +535,11 @@ namespace OpenSim.Region.Framework.Scenes foreach (Match uuidMatch in uuidMatches) { UUID uuid = new UUID(uuidMatch.Value); + if(uuid == UUID.Zero) + continue; // m_log.DebugFormat("[UUID GATHERER]: Recording {0} in text", uuid); - + if(!UncertainAssetsUUIDs.Contains(uuid)) + UncertainAssetsUUIDs.Add(uuid); AddForInspection(uuid); } } @@ -550,7 +630,16 @@ namespace OpenSim.Region.Framework.Scenes /// private void RecordMaterialAssetUuids(AssetBase materialAsset) { - OSDMap mat = (OSDMap)OSDParser.DeserializeLLSDXml(materialAsset.Data); + OSDMap mat; + try + { + mat = (OSDMap)OSDParser.DeserializeLLSDXml(materialAsset.Data); + } + catch (Exception e) + { + m_log.WarnFormat("[Materials]: cannot decode material asset {0}: {1}", materialAsset.ID, e.Message); + return; + } UUID normMap = mat["NormMap"].AsUUID(); if (normMap != UUID.Zero) diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 83b534b0ca..d39c224129 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1097,7 +1097,12 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void SendAvatarDataImmediate(ISceneEntity avatar) + public void SendEntityFullUpdateImmediate(ISceneEntity ent) + { + + } + + public void SendEntityTerseUpdateImmediate(ISceneEntity ent) { } diff --git a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs index 3be5a07d27..490809eae1 100644 --- a/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs +++ b/OpenSim/Region/OptionalModules/Agent/UDP/Linden/LindenUDPInfoModule.cs @@ -124,15 +124,6 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden "Without the 'full' option, only root agents are shown." + " With the 'full' option child agents are also shown.", (mod, cmd) => MainConsole.Instance.Output(GetThrottlesReport(cmd))); - - scene.AddCommand( - "Comms", this, "show client stats", - "show client stats [first_name last_name]", - "Show client request stats", - "Without the 'first_name last_name' option, all clients are shown." - + " With the 'first_name last_name' option only a specific client is shown.", - (mod, cmd) => MainConsole.Instance.Output(HandleClientStatsReport(cmd))); - } public void RemoveRegion(Scene scene) @@ -540,107 +531,6 @@ namespace OpenSim.Region.OptionalModules.UDP.Linden return report.ToString(); } - /// - /// Show client stats data - /// - /// - /// - protected string HandleClientStatsReport(string[] showParams) - { - // NOTE: This writes to m_log on purpose. We want to store this information - // in case we need to analyze it later. - // - if (showParams.Length <= 4) - { - m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", "Region", "Name", "Root", "Time", "Reqs/min", "AgentUpdates"); - foreach (Scene scene in m_scenes.Values) - { - scene.ForEachClient( - delegate(IClientAPI client) - { - if (client is LLClientView) - { - LLClientView llClient = client as LLClientView; - ClientInfo cinfo = llClient.UDPClient.GetClientInfo(); - int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); - avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); - - string childAgentStatus; - - if (llClient.SceneAgent != null) - childAgentStatus = llClient.SceneAgent.IsChildAgent ? "N" : "Y"; - else - childAgentStatus = "Off!"; - - m_log.InfoFormat("[INFO]: {0,-12} {1,-20} {2,-6} {3,-11} {4,-11} {5,-16}", - scene.RegionInfo.RegionName, llClient.Name, - childAgentStatus, - (DateTime.Now - cinfo.StartedTime).Minutes, - avg_reqs, - string.Format( - "{0} ({1:0.00}%)", - llClient.TotalAgentUpdates, - cinfo.SyncRequests.ContainsKey("AgentUpdate") - ? (float)cinfo.SyncRequests["AgentUpdate"] / llClient.TotalAgentUpdates * 100 - : 0)); - } - }); - } - return string.Empty; - } - - string fname = "", lname = ""; - - if (showParams.Length > 3) - fname = showParams[3]; - if (showParams.Length > 4) - lname = showParams[4]; - - foreach (Scene scene in m_scenes.Values) - { - scene.ForEachClient( - delegate(IClientAPI client) - { - if (client is LLClientView) - { - LLClientView llClient = client as LLClientView; - - if (llClient.Name == fname + " " + lname) - { - - ClientInfo cinfo = llClient.GetClientInfo(); - AgentCircuitData aCircuit = scene.AuthenticateHandler.GetAgentCircuitData(llClient.CircuitCode); - if (aCircuit == null) // create a dummy one - aCircuit = new AgentCircuitData(); - - if (!llClient.SceneAgent.IsChildAgent) - m_log.InfoFormat("[INFO]: {0} # {1} # {2}", llClient.Name, Util.GetViewerName(aCircuit), aCircuit.Id0); - - int avg_reqs = cinfo.AsyncRequests.Values.Sum() + cinfo.GenericRequests.Values.Sum() + cinfo.SyncRequests.Values.Sum(); - avg_reqs = avg_reqs / ((DateTime.Now - cinfo.StartedTime).Minutes + 1); - - m_log.InfoFormat("[INFO]:"); - m_log.InfoFormat("[INFO]: {0} # {1} # Time: {2}min # Avg Reqs/min: {3}", scene.RegionInfo.RegionName, - (llClient.SceneAgent.IsChildAgent ? "Child" : "Root"), (DateTime.Now - cinfo.StartedTime).Minutes, avg_reqs); - - Dictionary sortedDict = (from entry in cinfo.AsyncRequests orderby entry.Value descending select entry) - .ToDictionary(pair => pair.Key, pair => pair.Value); - PrintRequests("TOP ASYNC", sortedDict, cinfo.AsyncRequests.Values.Sum()); - - sortedDict = (from entry in cinfo.SyncRequests orderby entry.Value descending select entry) - .ToDictionary(pair => pair.Key, pair => pair.Value); - PrintRequests("TOP SYNC", sortedDict, cinfo.SyncRequests.Values.Sum()); - - sortedDict = (from entry in cinfo.GenericRequests orderby entry.Value descending select entry) - .ToDictionary(pair => pair.Key, pair => pair.Value); - PrintRequests("TOP GENERIC", sortedDict, cinfo.GenericRequests.Values.Sum()); - } - } - }); - } - return string.Empty; - } - private void PrintRequests(string type, Dictionary sortedDict, int sum) { m_log.InfoFormat("[INFO]:"); diff --git a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs index ed27385efb..c3f38511dd 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Attachments/TempAttachmentsModule.cs @@ -134,11 +134,12 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments private int llAttachToAvatarTemp(UUID host, UUID script, int attachmentPoint) { SceneObjectPart hostPart = m_scene.GetSceneObjectPart(host); - if (hostPart == null) return 0; - if (hostPart.ParentGroup.IsAttachment) + SceneObjectGroup hostgroup = hostPart.ParentGroup; + + if (hostgroup== null || hostgroup.IsAttachment) return 0; IAttachmentsModule attachmentsModule = m_scene.RequestModuleInterface(); @@ -156,32 +157,32 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments if (!m_scene.TryGetScenePresence(item.PermsGranter, out target)) return 0; - if (target.UUID != hostPart.ParentGroup.OwnerID) + if (target.UUID != hostgroup.OwnerID) { - uint effectivePerms = hostPart.ParentGroup.GetEffectivePermissions(); + uint effectivePerms = hostgroup.EffectiveOwnerPerms; if ((effectivePerms & (uint)PermissionMask.Transfer) == 0) return 0; - hostPart.ParentGroup.SetOwnerId(target.UUID); - hostPart.ParentGroup.SetRootPartOwner(hostPart.ParentGroup.RootPart, target.UUID, target.ControllingClient.ActiveGroupId); + hostgroup.SetOwner(target.UUID, target.ControllingClient.ActiveGroupId); if (m_scene.Permissions.PropagatePermissions()) { - foreach (SceneObjectPart child in hostPart.ParentGroup.Parts) + foreach (SceneObjectPart child in hostgroup.Parts) { child.Inventory.ChangeInventoryOwner(target.UUID); child.TriggerScriptChangedEvent(Changed.OWNER); child.ApplyNextOwnerPermissions(); } + hostgroup.InvalidateEffectivePerms(); } - hostPart.ParentGroup.RootPart.ObjectSaleType = 0; - hostPart.ParentGroup.RootPart.SalePrice = 10; + hostgroup.RootPart.ObjectSaleType = 0; + hostgroup.RootPart.SalePrice = 10; - hostPart.ParentGroup.HasGroupChanged = true; - hostPart.ParentGroup.RootPart.SendPropertiesToClient(target.ControllingClient); - hostPart.ParentGroup.RootPart.ScheduleFullUpdate(); + hostgroup.HasGroupChanged = true; + hostgroup.RootPart.SendPropertiesToClient(target.ControllingClient); + hostgroup.RootPart.ScheduleFullUpdate(); } return attachmentsModule.AttachObject(target, hostPart.ParentGroup, (uint)attachmentPoint, false, false, true) ? 1 : 0; diff --git a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs index c0de3d95db..a5dc0ad0d0 100644 --- a/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/Concierge/ConciergeModule.cs @@ -460,9 +460,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.Concierge if (resp.ContentLength > 0) { - StreamReader content = new StreamReader(resp.GetResponseStream()); - m_log.ErrorFormat("[Concierge] response from {0} content: {1}", bs.Uri, content.ReadToEnd()); - content.Close(); + using(StreamReader content = new StreamReader(resp.GetResponseStream())) + m_log.ErrorFormat("[Concierge] response from {0} content: {1}", bs.Uri, content.ReadToEnd()); } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index d52a1d53db..65d50bb9a0 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -901,7 +901,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups remoteClient.SendCreateGroupReply(groupID, true, "Group created successfully"); // Update the founder with new group information. - SendAgentGroupDataUpdate(remoteClient, false); + SendAgentGroupDataUpdate(remoteClient, true); return groupID; } @@ -1520,6 +1520,7 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups lastname, activeGroupPowers, activeGroupName, activeGroupTitle); + if (tellOthers) SendScenePresenceUpdate(agentID, activeGroupTitle); diff --git a/OpenSim/Region/OptionalModules/Framework/Monitoring/EtcdMonitoringModule.cs b/OpenSim/Region/OptionalModules/Framework/Monitoring/EtcdMonitoringModule.cs new file mode 100644 index 0000000000..921bbfbbee --- /dev/null +++ b/OpenSim/Region/OptionalModules/Framework/Monitoring/EtcdMonitoringModule.cs @@ -0,0 +1,195 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; +using System.Text; +using log4net; +using Mono.Addins; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using netcd; +using netcd.Serialization; +using netcd.Advanced; +using netcd.Advanced.Requests; + +namespace OpenSim.Region.OptionalModules.Framework.Monitoring +{ + /// + /// Allows to store monitoring data in etcd, a high availability + /// name-value store. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "EtcdMonitoringModule")] + public class EtcdMonitoringModule : INonSharedRegionModule, IEtcdModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected Scene m_scene; + protected IEtcdClient m_client; + protected bool m_enabled = false; + protected string m_etcdBasePath = String.Empty; + protected bool m_appendRegionID = true; + + public string Name + { + get { return "EtcdMonitoringModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public void Initialise(IConfigSource source) + { + if (source.Configs["Etcd"] == null) + return; + + IConfig etcdConfig = source.Configs["Etcd"]; + + string etcdUrls = etcdConfig.GetString("EtcdUrls", String.Empty); + if (etcdUrls == String.Empty) + return; + + m_etcdBasePath = etcdConfig.GetString("BasePath", m_etcdBasePath); + m_appendRegionID = etcdConfig.GetBoolean("AppendRegionID", m_appendRegionID); + + if (!m_etcdBasePath.EndsWith("/")) + m_etcdBasePath += "/"; + + try + { + string[] endpoints = etcdUrls.Split(new char[] {','}); + List uris = new List(); + foreach (string endpoint in endpoints) + uris.Add(new Uri(endpoint.Trim())); + + m_client = new EtcdClient(uris.ToArray(), new DefaultSerializer(), new DefaultSerializer()); + } + catch (Exception e) + { + m_log.DebugFormat("[ETCD]: Error initializing connection: " + e.ToString()); + return; + } + + m_log.DebugFormat("[ETCD]: Etcd module configured"); + m_enabled = true; + } + + public void Close() + { + //m_client = null; + m_scene = null; + } + + public void AddRegion(Scene scene) + { + m_scene = scene; + + if (m_enabled) + { + if (m_appendRegionID) + m_etcdBasePath += m_scene.RegionInfo.RegionID.ToString() + "/"; + + m_log.DebugFormat("[ETCD]: Using base path {0} for all keys", m_etcdBasePath); + + try + { + m_client.Advanced.CreateDirectory(new CreateDirectoryRequest() {Key = m_etcdBasePath}); + } + catch (Exception e) + { + m_log.ErrorFormat("Exception trying to create base path {0}: " + e.ToString(), m_etcdBasePath); + } + + scene.RegisterModuleInterface(this); + } + } + + public void RemoveRegion(Scene scene) + { + } + + public void RegionLoaded(Scene scene) + { + } + + public bool Store(string k, string v) + { + return Store(k, v, 0); + } + + public bool Store(string k, string v, int ttl) + { + Response resp = m_client.Advanced.SetKey(new SetKeyRequest() { Key = m_etcdBasePath + k, Value = v, TimeToLive = ttl }); + + if (resp == null) + return false; + + if (resp.ErrorCode.HasValue) + { + m_log.DebugFormat("[ETCD]: Error {0} ({1}) storing {2} => {3}", resp.Cause, (int)resp.ErrorCode, m_etcdBasePath + k, v); + + return false; + } + + return true; + } + + public string Get(string k) + { + Response resp = m_client.Advanced.GetKey(new GetKeyRequest() { Key = m_etcdBasePath + k }); + + if (resp == null) + return String.Empty; + + if (resp.ErrorCode.HasValue) + { + m_log.DebugFormat("[ETCD]: Error {0} ({1}) getting {2}", resp.Cause, (int)resp.ErrorCode, m_etcdBasePath + k); + + return String.Empty; + } + + return resp.Node.Value; + } + + public void Delete(string k) + { + m_client.Advanced.DeleteKey(new DeleteKeyRequest() { Key = m_etcdBasePath + k }); + } + + public void Watch(string k, Action callback) + { + m_client.Advanced.WatchKey(new WatchKeyRequest() { Key = m_etcdBasePath + k, Callback = (x) => { callback(x.Node.Value); } }); + } + } +} diff --git a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs index 52fa908d4a..e8cb052263 100644 --- a/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs +++ b/OpenSim/Region/OptionalModules/Materials/MaterialsModule.cs @@ -329,7 +329,7 @@ namespace OpenSim.Region.OptionalModules.Materials AssetBase matAsset = m_scene.AssetService.Get(id.ToString()); if (matAsset == null || matAsset.Data == null || matAsset.Data.Length == 0 ) { - m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id); + //m_log.WarnFormat("[Materials]: Prim \"{0}\" ({1}) contains unknown material ID {2}", part.Name, part.UUID, id); return; } diff --git a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs index 9c0fa7577d..61b6d682e6 100644 --- a/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs +++ b/OpenSim/Region/OptionalModules/PrimLimitsModule/PrimLimitsModule.cs @@ -52,6 +52,7 @@ namespace OpenSim.Region.OptionalModules private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private bool m_enabled; + private Scene m_scene; public string Name { get { return "PrimLimitsModule"; } } public Type ReplaceableInterface { get { return null; } } @@ -77,11 +78,12 @@ namespace OpenSim.Region.OptionalModules public void AddRegion(Scene scene) { if (!m_enabled) - { return; - } + + m_scene = scene; scene.Permissions.OnRezObject += CanRezObject; scene.Permissions.OnObjectEntry += CanObjectEnter; + scene.Permissions.OnObjectEnterWithScripts += CanObjectEnterWithScripts; scene.Permissions.OnDuplicateObject += CanDuplicateObject; m_log.DebugFormat("[PRIM LIMITS]: Region {0} added", scene.RegionInfo.RegionName); @@ -89,14 +91,13 @@ namespace OpenSim.Region.OptionalModules public void RemoveRegion(Scene scene) { - if (m_enabled) - { + if (!m_enabled) return; - } - scene.Permissions.OnRezObject -= CanRezObject; - scene.Permissions.OnObjectEntry -= CanObjectEnter; - scene.Permissions.OnDuplicateObject -= CanDuplicateObject; + m_scene.Permissions.OnRezObject -= CanRezObject; + m_scene.Permissions.OnObjectEntry -= CanObjectEnter; + scene.Permissions.OnObjectEnterWithScripts -= CanObjectEnterWithScripts; + m_scene.Permissions.OnDuplicateObject -= CanDuplicateObject; } public void RegionLoaded(Scene scene) @@ -104,11 +105,12 @@ namespace OpenSim.Region.OptionalModules m_dialogModule = scene.RequestModuleInterface(); } - private bool CanRezObject(int objectCount, UUID ownerID, Vector3 objectPosition, Scene scene) + private bool CanRezObject(int objectCount, UUID ownerID, Vector3 objectPosition) { - ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); + + ILandObject lo = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); - string response = DoCommonChecks(objectCount, ownerID, lo, scene); + string response = DoCommonChecks(objectCount, ownerID, lo); if (response != null) { @@ -119,88 +121,99 @@ namespace OpenSim.Region.OptionalModules } //OnDuplicateObject - private bool CanDuplicateObject(int objectCount, UUID objectID, UUID ownerID, Scene scene, Vector3 objectPosition) + private bool CanDuplicateObject(SceneObjectGroup sog, ScenePresence sp) { - ILandObject lo = scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); + Vector3 objectPosition = sog.AbsolutePosition; + ILandObject lo = m_scene.LandChannel.GetLandObject(objectPosition.X, objectPosition.Y); - string response = DoCommonChecks(objectCount, ownerID, lo, scene); + string response = DoCommonChecks(sog.PrimCount, sp.UUID, lo); if (response != null) { - m_dialogModule.SendAlertToUser(ownerID, response); + m_dialogModule.SendAlertToUser(sp.UUID, response); return false; } return true; } - private bool CanObjectEnter(UUID objectID, bool enteringRegion, Vector3 newPoint, Scene scene) + private bool CanObjectEnter(SceneObjectGroup sog, bool enteringRegion, Vector3 newPoint) { - if (newPoint.X < -1f || newPoint.X > (scene.RegionInfo.RegionSizeX + 1) || - newPoint.Y < -1f || newPoint.Y > (scene.RegionInfo.RegionSizeY) ) + float newX = newPoint.X; + float newY = newPoint.Y; + if (newX < -1.0f || newX > (m_scene.RegionInfo.RegionSizeX + 1.0f) || + newY < -1.0f || newY > (m_scene.RegionInfo.RegionSizeY + 1.0f) ) return true; - SceneObjectPart obj = scene.GetSceneObjectPart(objectID); - - if (obj == null) + if (sog == null) return false; - // Prim counts are determined by the location of the root prim. if we're - // moving a child prim, just let it pass - if (!obj.IsRoot) - { - return true; - } - - ILandObject newParcel = scene.LandChannel.GetLandObject(newPoint.X, newPoint.Y); + ILandObject newParcel = m_scene.LandChannel.GetLandObject(newX, newY); if (newParcel == null) return true; - Vector3 oldPoint = obj.GroupPosition; - ILandObject oldParcel = scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); - - // The prim hasn't crossed a region boundry so we don't need to worry - // about prim counts here - if(oldParcel != null && oldParcel.Equals(newParcel)) + if(!enteringRegion) { - return true; + Vector3 oldPoint = sog.AbsolutePosition; + ILandObject oldParcel = m_scene.LandChannel.GetLandObject(oldPoint.X, oldPoint.Y); + if(oldParcel != null && oldParcel.Equals(newParcel)) + return true; } - int objectCount = obj.ParentGroup.PrimCount; - int usedPrims = newParcel.PrimCounts.Total; - int simulatorCapacity = newParcel.GetSimulatorMaxPrimCount(); + int objectCount = sog.PrimCount; // TODO: Add Special Case here for temporary prims - string response = DoCommonChecks(objectCount, obj.OwnerID, newParcel, scene); + string response = DoCommonChecks(objectCount, sog.OwnerID, newParcel); if (response != null) { - m_dialogModule.SendAlertToUser(obj.OwnerID, response); + if(m_dialogModule != null) + m_dialogModule.SendAlertToUser(sog.OwnerID, response); return false; } return true; } - private string DoCommonChecks(int objectCount, UUID ownerID, ILandObject lo, Scene scene) + private bool CanObjectEnterWithScripts(SceneObjectGroup sog, ILandObject newParcel) + { + if (sog == null) + return false; + + if (newParcel == null) + return true; + + int objectCount = sog.PrimCount; + + // TODO: Add Special Case here for temporary prims + + string response = DoCommonChecks(objectCount, sog.OwnerID, newParcel); + + if (response != null) + return false; + + return true; + } + + private string DoCommonChecks(int objectCount, UUID ownerID, ILandObject lo) { string response = null; int OwnedParcelsCapacity = lo.GetSimulatorMaxPrimCount(); if ((objectCount + lo.PrimCounts.Total) > OwnedParcelsCapacity) { - response = "Unable to rez object because the parcel is too full"; + response = "Unable to rez object because the parcel is full"; } else { - int maxPrimsPerUser = scene.RegionInfo.MaxPrimsPerUser; + int maxPrimsPerUser = m_scene.RegionInfo.MaxPrimsPerUser; if (maxPrimsPerUser >= 0) { // per-user prim limit is set if (ownerID != lo.LandData.OwnerID || lo.LandData.IsGroupOwned) { // caller is not the sole Parcel owner - EstateSettings estateSettings = scene.RegionInfo.EstateSettings; + EstateSettings estateSettings = m_scene.RegionInfo.EstateSettings; if (ownerID != estateSettings.EstateOwner) { // caller is NOT the Estate owner diff --git a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs index a9fdb667c4..fe8d9621e1 100644 --- a/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/JsonStore/JsonStoreScriptModule.cs @@ -665,7 +665,7 @@ namespace OpenSim.Region.OptionalModules.Scripting.JsonStore taskItem.AssetID = asset.FullID; host.Inventory.AddInventoryItem(taskItem, false); - + host.ParentGroup.InvalidateEffectivePerms(); m_comms.DispatchReply(scriptID,1,assetID.ToString(),reqID.ToString()); } diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs index 79b80f88f4..a14d8194ad 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModule.cs @@ -59,23 +59,23 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// /// /// Config Settings Documentation. - /// Each configuration setting can be specified in two places: OpenSim.ini or Regions.ini. - /// If specified in Regions.ini, the settings should be within the region's section name. - /// If specified in OpenSim.ini, the settings should be within the [AutoBackupModule] section. - /// Region-specific settings take precedence. + /// Configuration setting can be specified in two places: OpenSim.ini and/or Regions.ini. /// - /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. This setting does not support per-region basis. - /// All other settings under [AutoBackupModule] are ignored if AutoBackupModuleEnabled is false, even per-region settings! - /// AutoBackup: True/False. Default: False. If True, activate auto backup functionality. - /// This is the only required option for enabling auto-backup; the other options have sane defaults. - /// If False for a particular region, the auto-backup module becomes a no-op for the region, and all other AutoBackup* settings are ignored. - /// If False globally (the default), only regions that specifically override it in Regions.ini will get AutoBackup functionality. + /// OpenSim.ini only settings section [AutoBackupModule] + /// AutoBackupModuleEnabled: True/False. Default: False. If True, use the auto backup module. + /// if false module is disable and all rest is ignored /// AutoBackupInterval: Double, non-negative value. Default: 720 (12 hours). /// The number of minutes between each backup attempt. - /// If a negative or zero value is given, it is equivalent to setting AutoBackup = False. - /// AutoBackupBusyCheck: True/False. Default: True. - /// If True, we will only take an auto-backup if a set of conditions are met. - /// These conditions are heuristics to try and avoid taking a backup when the sim is busy. + /// AutoBackupDir: String. Default: "." (the current directory). + /// A directory (absolute or relative) where backups should be saved. + /// AutoBackupKeepFilesForDays remove files older than this number of days. 0 disables + /// + /// Next can be set on OpenSim.ini, as default, and or per region in Regions.ini + /// Region-specific settings take precedence. + /// + /// AutoBackup: True/False. Default: False. If True, activate auto backup functionality. + /// controls backup per region, with default optionaly set on OpenSim.ini + /// AutoBackupSkipAssets /// If true, assets are not saved to the oar file. Considerably reduces impact on simulator when backing up. Intended for when assets db is backed up separately /// AutoBackupKeepFilesForDays @@ -89,40 +89,28 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// AutoBackupNaming: string. Default: Time. /// One of three strings (case insensitive): /// "Time": Current timestamp is appended to file name. An existing file will never be overwritten. - /// "Sequential": A number is appended to the file name. So if RegionName_x.oar exists, we'll save to RegionName_{x+1}.oar next. An existing file will never be overwritten. - /// "Overwrite": Always save to file named "${AutoBackupDir}/RegionName.oar", even if we have to overwrite an existing file. - /// AutoBackupDir: String. Default: "." (the current directory). - /// A directory (absolute or relative) where backups should be saved. - /// AutoBackupDilationThreshold: float. Default: 0.5. Lower bound on time dilation required for BusyCheck heuristics to pass. - /// If the time dilation is below this value, don't take a backup right now. - /// AutoBackupAgentThreshold: int. Default: 10. Upper bound on # of agents in region required for BusyCheck heuristics to pass. - /// If the number of agents is greater than this value, don't take a backup right now - /// Save memory by setting low initial capacities. Minimizes impact in common cases of all regions using same interval, and instances hosting 1 ~ 4 regions. - /// Also helps if you don't want AutoBackup at all. + /// "Sequential": A number is appended to the file name. So if RegionName_x.oar exists, we'll save to RegionName_{x+1}.oar next. An existing file will never be overwritten. + /// "Overwrite": Always save to file named "${AutoBackupDir}/RegionName.oar", even if we have to overwrite an existing file. /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AutoBackupModule")] public class AutoBackupModule : ISharedRegionModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - private readonly Dictionary m_pendingSaves = new Dictionary(1); private readonly AutoBackupModuleState m_defaultState = new AutoBackupModuleState(); private readonly Dictionary m_states = new Dictionary(1); - private readonly Dictionary> m_timerMap = - new Dictionary>(1); - private readonly Dictionary m_timers = new Dictionary(1); private delegate T DefaultGetter(string settingName, T defaultValue); private bool m_enabled; private ICommandConsole m_console; private List m_Scenes = new List (); - - - /// - /// Whether the shared module should be enabled at all. NOT the same as m_Enabled in AutoBackupModuleState! - /// - private bool m_closed; + private Timer m_masterTimer; + private bool m_busy; + private int m_KeepFilesForDays = -1; + private string m_backupDir; + private bool m_doneFirst; + private double m_baseInterval; private IConfigSource m_configSource; @@ -159,36 +147,38 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup void IRegionModuleBase.Initialise(IConfigSource source) { // Determine if we have been enabled at all in OpenSim.ini -- this is part and parcel of being an optional module - this.m_configSource = source; + m_configSource = source; IConfig moduleConfig = source.Configs["AutoBackupModule"]; if (moduleConfig == null) { - this.m_enabled = false; + m_enabled = false; return; } - else - { - this.m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false); - if (this.m_enabled) - { - m_log.Info("[AUTO BACKUP]: AutoBackupModule enabled"); - } - else - { - return; - } - } - Timer defTimer = new Timer(43200000); - this.m_defaultState.Timer = defTimer; - this.m_timers.Add(43200000, defTimer); - defTimer.Elapsed += this.HandleElapsed; - defTimer.AutoReset = true; - defTimer.Start(); + m_enabled = moduleConfig.GetBoolean("AutoBackupModuleEnabled", false); + if(!m_enabled) + return; - AutoBackupModuleState abms = this.ParseConfig(null, true); - m_log.Debug("[AUTO BACKUP]: Here is the default config:"); - m_log.Debug(abms.ToString()); + ParseDefaultConfig(moduleConfig); + if(!m_enabled) + return; + + m_log.Debug("[AUTO BACKUP]: Default config:"); + m_log.Debug(m_defaultState.ToString()); + + m_log.Info("[AUTO BACKUP]: AutoBackupModule enabled"); + m_masterTimer = new Timer(); + m_masterTimer.Interval = m_baseInterval; + m_masterTimer.Elapsed += HandleElapsed; + m_masterTimer.AutoReset = false; + + m_console = MainConsole.Instance; + + m_console.Commands.AddCommand ( + "AutoBackup", true, "dooarbackup", + "dooarbackup | ALL", + "saves the single region to a oar or ALL regions in instance to oars, using same settings as AutoBackup. Note it restarts time interval", DoBackup); + m_busy = true; } /// @@ -196,13 +186,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// void IRegionModuleBase.Close() { - if (!this.m_enabled) - { + if (!m_enabled) return; - } // We don't want any timers firing while the sim's coming down; strange things may happen. - this.StopAllTimers(); + m_masterTimer.Dispose(); } /// @@ -211,18 +199,11 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// void IRegionModuleBase.AddRegion (Scene scene) { - if (!this.m_enabled) { + if (!m_enabled) return; - } - lock (m_Scenes) { - m_Scenes.Add (scene); - } - m_console = MainConsole.Instance; - m_console.Commands.AddCommand ( - "AutoBackup", false, "dobackup", - "dobackup", - "do backup.", DoBackup); + lock (m_Scenes) + m_Scenes.Add (scene); } /// @@ -231,28 +212,14 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// The scene (region) to stop performing AutoBackup on. void IRegionModuleBase.RemoveRegion(Scene scene) { - if (!this.m_enabled) - { + if (m_enabled) return; - } - m_Scenes.Remove (scene); - if (this.m_states.ContainsKey(scene)) + + lock(m_Scenes) { - AutoBackupModuleState abms = this.m_states[scene]; - - // Remove this scene out of the timer map list - Timer timer = abms.Timer; - List list = this.m_timerMap[timer]; - list.Remove(scene); - - // Shut down the timer if this was the last scene for the timer - if (list.Count == 0) - { - this.m_timerMap.Remove(timer); - this.m_timers.Remove(timer.Interval); - timer.Close(); - } - this.m_states.Remove(scene); + if (m_states.ContainsKey(scene)) + m_states.Remove(scene); + m_Scenes.Remove(scene); } } @@ -263,22 +230,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// The scene to (possibly) perform AutoBackup on. void IRegionModuleBase.RegionLoaded(Scene scene) { - if (!this.m_enabled) - { + if (!m_enabled) return; - } // This really ought not to happen, but just in case, let's pretend it didn't... if (scene == null) - { return; + + AutoBackupModuleState abms = ParseConfig(scene); + if(abms == null) + { + m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName); + m_log.Debug("DEFAULT"); + abms = new AutoBackupModuleState(m_defaultState); + } + else + { + m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName); + m_log.Debug(abms.ToString()); } - AutoBackupModuleState abms = this.ParseConfig(scene, false); - m_log.Debug("[AUTO BACKUP]: Config for " + scene.RegionInfo.RegionName); - m_log.Debug((abms == null ? "DEFAULT" : abms.ToString())); - m_states.Add(scene, abms); + m_busy = false; + m_masterTimer.Start(); } /// @@ -292,24 +266,122 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup private void DoBackup (string module, string[] args) { - if (args.Length != 2) { - MainConsole.Instance.OutputFormat ("Usage: dobackup "); + if (!m_enabled) + return; + + if (args.Length != 2) + { + MainConsole.Instance.OutputFormat ("Usage: dooarbackup "); return; } + + if(m_busy) + { + MainConsole.Instance.OutputFormat ("Already doing a backup, please try later"); + return; + } + + m_masterTimer.Stop(); + m_busy = true; + bool found = false; string name = args [1]; - lock (m_Scenes) { - foreach (Scene s in m_Scenes) { - string test = s.Name.ToString (); - if (test == name) { + Scene[] scenes; + lock (m_Scenes) + scenes = m_Scenes.ToArray(); + + if(scenes == null) + return; + + Scene s; + try + { + if(name == "ALL") + { + for(int i = 0; i < scenes.Length; i++) + { + s = scenes[i]; + DoRegionBackup(s); + if (!m_enabled) + return; + } + return; + } + + for(int i = 0; i < scenes.Length; i++) + { + s = scenes[i]; + if (s.Name == name) + { found = true; - DoRegionBackup (s); + DoRegionBackup(s); + break; } } - if (!found) { + } + catch { } + finally + { + if (m_enabled) + m_masterTimer.Start(); + m_busy = false; + } + if (!found) MainConsole.Instance.OutputFormat ("No such region {0}. Nothing to backup", name); + } + + private void ParseDefaultConfig(IConfig config) + { + + m_backupDir = "."; + string backupDir = config.GetString("AutoBackupDir", "."); + if (backupDir != ".") + { + try + { + DirectoryInfo dirinfo = new DirectoryInfo(backupDir); + if (!dirinfo.Exists) + dirinfo.Create(); + } + catch (Exception e) + { + m_enabled = false; + m_log.WarnFormat("[AUTO BACKUP]: Error accessing backup folder {0}. Module disabled. {1}", + backupDir, e); + return; } } + m_backupDir = backupDir; + + double interval = config.GetDouble("AutoBackupInterval", 720); + interval *= 60000.0; + m_baseInterval = interval; + + // How long to keep backup files in days, 0 Disables this feature + m_KeepFilesForDays = config.GetInt("AutoBackupKeepFilesForDays",m_KeepFilesForDays); + + m_defaultState.Enabled = config.GetBoolean("AutoBackup", m_defaultState.Enabled); + + m_defaultState.SkipAssets = config.GetBoolean("AutoBackupSkipAssets",m_defaultState.SkipAssets); + + // Set file naming algorithm + string stmpNamingType = config.GetString("AutoBackupNaming", m_defaultState.NamingType.ToString()); + NamingType tmpNamingType; + if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase)) + tmpNamingType = NamingType.Time; + else if (stmpNamingType.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase)) + tmpNamingType = NamingType.Sequential; + else if (stmpNamingType.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase)) + tmpNamingType = NamingType.Overwrite; + else + { + m_log.Warn("Unknown naming type specified for Default"); + tmpNamingType = NamingType.Time; + } + m_defaultState.NamingType = tmpNamingType; + + m_defaultState.Script = config.GetString("AutoBackupScript", m_defaultState.Script); + } /// @@ -319,329 +391,49 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// The scene to look at. /// Whether this call is intended to figure out what we consider the "default" config (applied to all regions unless overridden by per-region settings). /// An AutoBackupModuleState contains most information you should need to know relevant to auto-backup, as applicable to a single region. - private AutoBackupModuleState ParseConfig(IScene scene, bool parseDefault) + private AutoBackupModuleState ParseConfig(IScene scene) { - string sRegionName; - string sRegionLabel; -// string prepend; - AutoBackupModuleState state; + if(scene == null) + return null; - if (parseDefault) - { - sRegionName = null; - sRegionLabel = "DEFAULT"; -// prepend = ""; - state = this.m_defaultState; - } - else - { - sRegionName = scene.RegionInfo.RegionName; - sRegionLabel = sRegionName; -// prepend = sRegionName + "."; - state = null; - } + string sRegionName; + AutoBackupModuleState state = null; + + sRegionName = scene.RegionInfo.RegionName; // Read the config settings and set variables. - IConfig regionConfig = (scene != null ? scene.Config.Configs[sRegionName] : null); - IConfig config = this.m_configSource.Configs["AutoBackupModule"]; - if (config == null) - { - // defaultState would be disabled too if the section doesn't exist. - state = this.m_defaultState; - return state; - } + IConfig regionConfig = scene.Config.Configs[sRegionName]; + if (regionConfig == null) + return null; - bool tmpEnabled = ResolveBoolean("AutoBackup", this.m_defaultState.Enabled, config, regionConfig); - if (state == null && tmpEnabled != this.m_defaultState.Enabled) - //Varies from default state - { - state = new AutoBackupModuleState(); - } + state = new AutoBackupModuleState(); - if (state != null) - { - state.Enabled = tmpEnabled; - } - - // If you don't want AutoBackup, we stop. - if ((state == null && !this.m_defaultState.Enabled) || (state != null && !state.Enabled)) - { - return state; - } - else - { - m_log.Info("[AUTO BACKUP]: Region " + sRegionLabel + " is AutoBackup ENABLED."); - } - - // Borrow an existing timer if one exists for the same interval; otherwise, make a new one. - double interval = - this.ResolveDouble("AutoBackupInterval", this.m_defaultState.IntervalMinutes, - config, regionConfig) * 60000.0; - if (state == null && interval != this.m_defaultState.IntervalMinutes * 60000.0) - { - state = new AutoBackupModuleState(); - } - - if (this.m_timers.ContainsKey(interval)) - { - if (state != null) - { - state.Timer = this.m_timers[interval]; - } - m_log.Debug("[AUTO BACKUP]: Reusing timer for " + interval + " msec for region " + - sRegionLabel); - } - else - { - // 0 or negative interval == do nothing. - if (interval <= 0.0 && state != null) - { - state.Enabled = false; - return state; - } - if (state == null) - { - state = new AutoBackupModuleState(); - } - Timer tim = new Timer(interval); - state.Timer = tim; - //Milliseconds -> minutes - this.m_timers.Add(interval, tim); - tim.Elapsed += this.HandleElapsed; - tim.AutoReset = true; - tim.Start(); - } - - // Add the current region to the list of regions tied to this timer. - if (scene != null) - { - if (state != null) - { - if (this.m_timerMap.ContainsKey(state.Timer)) - { - this.m_timerMap[state.Timer].Add(scene); - } - else - { - List scns = new List(1); - scns.Add(scene); - this.m_timerMap.Add(state.Timer, scns); - } - } - else - { - if (this.m_timerMap.ContainsKey(this.m_defaultState.Timer)) - { - this.m_timerMap[this.m_defaultState.Timer].Add(scene); - } - else - { - List scns = new List(1); - scns.Add(scene); - this.m_timerMap.Add(this.m_defaultState.Timer, scns); - } - } - } - - bool tmpBusyCheck = ResolveBoolean("AutoBackupBusyCheck", - this.m_defaultState.BusyCheck, config, regionConfig); - if (state == null && tmpBusyCheck != this.m_defaultState.BusyCheck) - { - state = new AutoBackupModuleState(); - } - - if (state != null) - { - state.BusyCheck = tmpBusyCheck; - } + state.Enabled = regionConfig.GetBoolean("AutoBackup", m_defaultState.Enabled); // Included Option To Skip Assets - bool tmpSkipAssets = ResolveBoolean("AutoBackupSkipAssets", - this.m_defaultState.SkipAssets, config, regionConfig); - if (state == null && tmpSkipAssets != this.m_defaultState.SkipAssets) - { - state = new AutoBackupModuleState(); - } - - if (state != null) - { - state.SkipAssets = tmpSkipAssets; - } - - // How long to keep backup files in days, 0 Disables this feature - int tmpKeepFilesForDays = ResolveInt("AutoBackupKeepFilesForDays", - this.m_defaultState.KeepFilesForDays, config, regionConfig); - if (state == null && tmpKeepFilesForDays != this.m_defaultState.KeepFilesForDays) - { - state = new AutoBackupModuleState(); - } - - if (state != null) - { - state.KeepFilesForDays = tmpKeepFilesForDays; - } + state.SkipAssets = regionConfig.GetBoolean("AutoBackupSkipAssets", m_defaultState.SkipAssets); // Set file naming algorithm - string stmpNamingType = ResolveString("AutoBackupNaming", - this.m_defaultState.NamingType.ToString(), config, regionConfig); + string stmpNamingType = regionConfig.GetString("AutoBackupNaming", m_defaultState.NamingType.ToString()); NamingType tmpNamingType; if (stmpNamingType.Equals("Time", StringComparison.CurrentCultureIgnoreCase)) - { tmpNamingType = NamingType.Time; - } else if (stmpNamingType.Equals("Sequential", StringComparison.CurrentCultureIgnoreCase)) - { tmpNamingType = NamingType.Sequential; - } else if (stmpNamingType.Equals("Overwrite", StringComparison.CurrentCultureIgnoreCase)) - { tmpNamingType = NamingType.Overwrite; - } else { - m_log.Warn("Unknown naming type specified for region " + sRegionLabel + ": " + + m_log.Warn("Unknown naming type specified for region " + sRegionName + ": " + stmpNamingType); tmpNamingType = NamingType.Time; } + m_defaultState.NamingType = tmpNamingType; - if (state == null && tmpNamingType != this.m_defaultState.NamingType) - { - state = new AutoBackupModuleState(); - } - - if (state != null) - { - state.NamingType = tmpNamingType; - } - - string tmpScript = ResolveString("AutoBackupScript", - this.m_defaultState.Script, config, regionConfig); - if (state == null && tmpScript != this.m_defaultState.Script) - { - state = new AutoBackupModuleState(); - } - - if (state != null) - { - state.Script = tmpScript; - } - - string tmpBackupDir = ResolveString("AutoBackupDir", ".", config, regionConfig); - if (state == null && tmpBackupDir != this.m_defaultState.BackupDir) - { - state = new AutoBackupModuleState(); - } - - if (state != null) - { - state.BackupDir = tmpBackupDir; - // Let's give the user some convenience and auto-mkdir - if (state.BackupDir != ".") - { - try - { - DirectoryInfo dirinfo = new DirectoryInfo(state.BackupDir); - if (!dirinfo.Exists) - { - dirinfo.Create(); - } - } - catch (Exception e) - { - m_log.Warn( - "[AUTO BACKUP]: BAD NEWS. You won't be able to save backups to directory " + - state.BackupDir + - " because it doesn't exist or there's a permissions issue with it. Here's the exception.", - e); - } - } - } - - if(state == null) - return m_defaultState; - + state.Script = regionConfig.GetString("AutoBackupScript", m_defaultState.Script); return state; } - /// - /// Helper function for ParseConfig. - /// - /// - /// - /// - /// - /// - private bool ResolveBoolean(string settingName, bool defaultValue, IConfig global, IConfig local) - { - if(local != null) - { - return local.GetBoolean(settingName, global.GetBoolean(settingName, defaultValue)); - } - else - { - return global.GetBoolean(settingName, defaultValue); - } - } - - /// - /// Helper function for ParseConfig. - /// - /// - /// - /// - /// - /// - private double ResolveDouble(string settingName, double defaultValue, IConfig global, IConfig local) - { - if (local != null) - { - return local.GetDouble(settingName, global.GetDouble(settingName, defaultValue)); - } - else - { - return global.GetDouble(settingName, defaultValue); - } - } - - /// - /// Helper function for ParseConfig. - /// - /// - /// - /// - /// - /// - private int ResolveInt(string settingName, int defaultValue, IConfig global, IConfig local) - { - if (local != null) - { - return local.GetInt(settingName, global.GetInt(settingName, defaultValue)); - } - else - { - return global.GetInt(settingName, defaultValue); - } - } - - /// - /// Helper function for ParseConfig. - /// - /// - /// - /// - /// - /// - private string ResolveString(string settingName, string defaultValue, IConfig global, IConfig local) - { - if (local != null) - { - return local.GetString(settingName, global.GetString(settingName, defaultValue)); - } - else - { - return global.GetString(settingName, defaultValue); - } - } /// /// Called when any auto-backup timer expires. This starts the code path for actually performing a backup. @@ -650,63 +442,27 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// private void HandleElapsed(object sender, ElapsedEventArgs e) { - // TODO: heuristic thresholds are per-region, so we should probably run heuristics once per region - // XXX: Running heuristics once per region could add undue performance penalty for something that's supposed to - // check whether the region is too busy! Especially on sims with LOTS of regions. - // Alternative: make heuristics thresholds global to the module rather than per-region. Less flexible, - // but would allow us to be semantically correct while being easier on perf. - // Alternative 2: Run heuristics once per unique set of heuristics threshold parameters! Ay yi yi... - // Alternative 3: Don't support per-region heuristics at all; just accept them as a global only parameter. - // Since this is pretty experimental, I haven't decided which alternative makes the most sense. - if (this.m_closed) - { + if (!m_enabled || m_busy) return; - } - bool heuristicsRun = false; - bool heuristicsPassed = false; - if (!this.m_timerMap.ContainsKey((Timer) sender)) + + m_busy = true; + if(m_doneFirst && m_KeepFilesForDays > 0) + RemoveOldFiles(); + + foreach (IScene scene in m_Scenes) { - m_log.Debug("[AUTO BACKUP]: Code-up error: timerMap doesn't contain timer " + sender); + if (!m_enabled) + return; + DoRegionBackup(scene); } - List tmap = this.m_timerMap[(Timer) sender]; - if (tmap != null && tmap.Count > 0) + if (m_enabled) { - foreach (IScene scene in tmap) - { - AutoBackupModuleState state = this.m_states[scene]; - bool heuristics = state.BusyCheck; - - // Fast path: heuristics are on; already ran em; and sim is fine; OR, no heuristics for the region. - if ((heuristics && heuristicsRun && heuristicsPassed) || !heuristics) - { - this.DoRegionBackup(scene); - // Heuristics are on; ran but we're too busy -- keep going. Maybe another region will have heuristics off! - } - else if (heuristicsRun) - { - m_log.Info("[AUTO BACKUP]: Heuristics: too busy to backup " + - scene.RegionInfo.RegionName + " right now."); - continue; - // Logical Deduction: heuristics are on but haven't been run - } - else - { - heuristicsPassed = this.RunHeuristics(scene); - heuristicsRun = true; - if (!heuristicsPassed) - { - m_log.Info("[AUTO BACKUP]: Heuristics: too busy to backup " + - scene.RegionInfo.RegionName + " right now."); - continue; - } - this.DoRegionBackup(scene); - } - - // Remove Old Backups - this.RemoveOldFiles(state); - } + m_masterTimer.Start(); + m_busy = false; } + + m_doneFirst = true; } /// @@ -723,21 +479,29 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup return; } - AutoBackupModuleState state = this.m_states[scene]; + m_busy = true; + + AutoBackupModuleState state; + if(!m_states.TryGetValue(scene, out state)) + return; + + if(state == null || !state.Enabled) + return; + IRegionArchiverModule iram = scene.RequestModuleInterface(); + if(iram == null) + return; + string savePath = BuildOarPath(scene.RegionInfo.RegionName, - state.BackupDir, + m_backupDir, state.NamingType); if (savePath == null) { m_log.Warn("[AUTO BACKUP]: savePath is null in HandleElapsed"); return; } - Guid guid = Guid.NewGuid(); - m_pendingSaves.Add(guid, scene); - state.LiveRequests.Add(guid, savePath); - ((Scene) scene).EventManager.OnOarFileSaved += new EventManager.OarFileSaved(EventManager_OnOarFileSaved); + Guid guid = Guid.NewGuid(); m_log.Info("[AUTO BACKUP]: Backing up region " + scene.RegionInfo.RegionName); // Must pass options, even if dictionary is empty! @@ -747,47 +511,37 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup options["noassets"] = true; iram.ArchiveRegion(savePath, guid, options); + ExecuteScript(state.Script, savePath); } // For the given state, remove backup files older than the states KeepFilesForDays property - private void RemoveOldFiles(AutoBackupModuleState state) + private void RemoveOldFiles() { - // 0 Means Disabled, Keep Files Indefinitely - if (state.KeepFilesForDays > 0) + string[] files; + try { - string[] files = Directory.GetFiles(state.BackupDir, "*.oar"); - DateTime CuttOffDate = DateTime.Now.AddDays(0 - state.KeepFilesForDays); - - foreach (string file in files) - { - try - { - FileInfo fi = new FileInfo(file); - if (fi.CreationTime < CuttOffDate) - fi.Delete(); - } - catch (Exception Ex) - { - m_log.Error("[AUTO BACKUP]: Error deleting old backup file '" + file + "': " + Ex.Message); - } - } + files = Directory.GetFiles(m_backupDir, "*.oar"); } - } - - /// - /// Called by the Event Manager when the OnOarFileSaved event is fired. - /// - /// - /// - void EventManager_OnOarFileSaved(Guid guid, string message) - { - // Ignore if the OAR save is being done by some other part of the system - if (m_pendingSaves.ContainsKey(guid)) + catch (Exception Ex) { - AutoBackupModuleState abms = m_states[(m_pendingSaves[guid])]; - ExecuteScript(abms.Script, abms.LiveRequests[guid]); - m_pendingSaves.Remove(guid); - abms.LiveRequests.Remove(guid); + m_log.Error("[AUTO BACKUP]: Error reading backup folder " + m_backupDir + ": " + Ex.Message); + return; + } + + DateTime CuttOffDate = DateTime.Now.AddDays(-m_KeepFilesForDays); + + foreach (string file in files) + { + try + { + FileInfo fi = new FileInfo(file); + if (fi.CreationTime < CuttOffDate) + fi.Delete(); + } + catch (Exception Ex) + { + m_log.Error("[AUTO BACKUP]: Error deleting old backup file '" + file + "': " + Ex.Message); + } } } @@ -817,63 +571,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup return output; } - /// Return value of true ==> not too busy; false ==> too busy to backup an OAR right now, or error. - private bool RunHeuristics(IScene region) - { - try - { - return this.RunTimeDilationHeuristic(region) && this.RunAgentLimitHeuristic(region); - } - catch (Exception e) - { - m_log.Warn("[AUTO BACKUP]: Exception in RunHeuristics", e); - return false; - } - } - - /// - /// If the time dilation right at this instant is less than the threshold specified in AutoBackupDilationThreshold (default 0.5), - /// then we return false and trip the busy heuristic's "too busy" path (i.e. don't save an OAR). - /// AutoBackupDilationThreshold is a _LOWER BOUND_. Lower Time Dilation is bad, so if you go lower than our threshold, it's "too busy". - /// - /// - /// Returns true if we're not too busy; false means we've got worse time dilation than the threshold. - private bool RunTimeDilationHeuristic(IScene region) - { - string regionName = region.RegionInfo.RegionName; - return region.TimeDilation >= - this.m_configSource.Configs["AutoBackupModule"].GetFloat( - regionName + ".AutoBackupDilationThreshold", 0.5f); - } - - /// - /// If the root agent count right at this instant is less than the threshold specified in AutoBackupAgentThreshold (default 10), - /// then we return false and trip the busy heuristic's "too busy" path (i.e., don't save an OAR). - /// AutoBackupAgentThreshold is an _UPPER BOUND_. Higher Agent Count is bad, so if you go higher than our threshold, it's "too busy". - /// - /// - /// Returns true if we're not too busy; false means we've got more agents on the sim than the threshold. - private bool RunAgentLimitHeuristic(IScene region) - { - string regionName = region.RegionInfo.RegionName; - try - { - Scene scene = (Scene) region; - // TODO: Why isn't GetRootAgentCount() a method in the IScene interface? Seems generally useful... - return scene.GetRootAgentCount() <= - this.m_configSource.Configs["AutoBackupModule"].GetInt( - regionName + ".AutoBackupAgentThreshold", 10); - } - catch (InvalidCastException ice) - { - m_log.Debug( - "[AUTO BACKUP]: I NEED MAINTENANCE: IScene is not a Scene; can't get root agent count!", - ice); - return true; - // Non-obstructionist safest answer... - } - } - /// /// Run the script or executable specified by the "AutoBackupScript" config setting. /// Of course this is a security risk if you let anyone modify OpenSim.ini and they want to run some nasty bash script. @@ -919,18 +616,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup " is yacking on stderr: " + e.Data); } - /// - /// Quickly stop all timers from firing. - /// - private void StopAllTimers() - { - foreach (Timer t in this.m_timerMap.Keys) - { - t.Close(); - } - this.m_closed = true; - } - /// /// Determine the next unique filename by number, for "Sequential" AutoBackupNamingType. /// @@ -1033,5 +718,3 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup } } } - - diff --git a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs index b90f0c4740..fb87677d62 100644 --- a/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs +++ b/OpenSim/Region/OptionalModules/World/AutoBackup/AutoBackupModuleState.cs @@ -38,26 +38,20 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup /// public class AutoBackupModuleState { - private Dictionary m_liveRequests = null; - public AutoBackupModuleState() { - this.Enabled = false; - this.BackupDir = "."; - this.BusyCheck = true; - this.SkipAssets = false; - this.Timer = null; - this.NamingType = NamingType.Time; - this.Script = null; - this.KeepFilesForDays = 0; + Enabled = false; + SkipAssets = false; + NamingType = NamingType.Time; + Script = null; } - public Dictionary LiveRequests + public AutoBackupModuleState(AutoBackupModuleState copyFrom) { - get { - return this.m_liveRequests ?? - (this.m_liveRequests = new Dictionary(1)); - } + Enabled = copyFrom.Enabled; + SkipAssets = copyFrom.SkipAssets; + NamingType = copyFrom.NamingType; + Script = copyFrom.Script; } public bool Enabled @@ -66,33 +60,6 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup set; } - public System.Timers.Timer Timer - { - get; - set; - } - - public double IntervalMinutes - { - get - { - if (this.Timer == null) - { - return -1.0; - } - else - { - return this.Timer.Interval / 60000.0; - } - } - } - - public bool BusyCheck - { - get; - set; - } - public bool SkipAssets { get; @@ -105,36 +72,19 @@ namespace OpenSim.Region.OptionalModules.World.AutoBackup set; } - public string BackupDir - { - get; - set; - } - public NamingType NamingType { get; set; } - public int KeepFilesForDays - { - get; - set; - } - public new string ToString() { string retval = ""; - retval += "[AUTO BACKUP]: AutoBackup: " + (Enabled ? "ENABLED" : "DISABLED") + "\n"; - retval += "[AUTO BACKUP]: Interval: " + IntervalMinutes + " minutes" + "\n"; - retval += "[AUTO BACKUP]: Do Busy Check: " + (BusyCheck ? "Yes" : "No") + "\n"; retval += "[AUTO BACKUP]: Naming Type: " + NamingType.ToString() + "\n"; - retval += "[AUTO BACKUP]: Backup Dir: " + BackupDir + "\n"; retval += "[AUTO BACKUP]: Script: " + Script + "\n"; return retval; } } } - diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index 47edeb9221..3666c3f2fc 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -844,9 +844,14 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule module.BuyObject(remoteClient, categoryID, localID, saleType, salePrice); } - public void MoveMoney(UUID fromAgentID, UUID toAgentID, int amount, string text) + public void MoveMoney(UUID fromUser, UUID toUser, int amount, string text) { } + + public bool MoveMoney(UUID fromUser, UUID toUser, int amount, MoneyTransactionType type, string text) + { + return true; + } } public enum TransactionType : int diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 6a7c735fd6..151a202e49 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -813,7 +813,11 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public void SendAvatarDataImmediate(ISceneEntity avatar) + public void SendEntityFullUpdateImmediate(ISceneEntity avatar) + { + } + + public void SendEntityTerseUpdateImmediate(ISceneEntity ent) { } diff --git a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs index d0d726c96b..7e3bd7f235 100644 --- a/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs +++ b/OpenSim/Region/OptionalModules/World/SceneCommands/SceneCommandsModule.cs @@ -96,18 +96,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments "List current scene options.", "active - if false then main scene update and maintenance loops are suspended.\n" + "animations - if true then extra animations debug information is logged.\n" - + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" - + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" - + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" - + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" + "collisions - if false then collisions with other objects are turned off.\n" + "pbackup - if false then periodic scene backup is turned off.\n" + "physics - if false then all physics objects are non-physical.\n" + "scripting - if false then no scripting operations happen.\n" + "teleport - if true then some extra teleport debug information is logged.\n" - + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n" + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", HandleDebugSceneGetCommand); @@ -117,18 +110,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments "Turn on scene debugging options.", "active - if false then main scene update and maintenance loops are suspended.\n" + "animations - if true then extra animations debug information is logged.\n" - + "appear-refresh - if true then appearance is resent to other avatars every 60 seconds.\n" - + "client-pos-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-rot-upd - the tolerance before clients are updated with new rotation information for an avatar.\n" - + "client-vel-upd - the tolerance before clients are updated with new velocity information for an avatar.\n" - + "root-upd-per - if greater than 1, terse updates are only sent to root agents other than the originator on every n updates.\n" - + "child-upd-per - if greater than 1, terse updates are only sent to child agents on every n updates.\n" + "collisions - if false then collisions with other objects are turned off.\n" + "pbackup - if false then periodic scene backup is turned off.\n" + "physics - if false then all physics objects are non-physical.\n" + "scripting - if false then no scripting operations happen.\n" + "teleport - if true then some extra teleport debug information is logged.\n" - + "update-on-timer - If true then the scene is updated via a timer. If false then a thread with sleep is used.\n" + "updates - if true then any frame which exceeds double the maximum desired frame time is logged.", HandleDebugSceneSetCommand); } @@ -153,17 +139,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments ConsoleDisplayList cdl = new ConsoleDisplayList(); cdl.AddRow("active", m_scene.Active); cdl.AddRow("animations", m_scene.DebugAnimations); - cdl.AddRow("appear-refresh", m_scene.SendPeriodicAppearanceUpdates); - cdl.AddRow("client-pos-upd", m_scene.RootPositionUpdateTolerance); - cdl.AddRow("client-rot-upd", m_scene.RootRotationUpdateTolerance); - cdl.AddRow("client-vel-upd", m_scene.RootVelocityUpdateTolerance); - cdl.AddRow("root-upd-per", m_scene.RootTerseUpdatePeriod); - cdl.AddRow("child-upd-per", m_scene.ChildTerseUpdatePeriod); cdl.AddRow("pbackup", m_scene.PeriodicBackup); cdl.AddRow("physics", m_scene.PhysicsEnabled); cdl.AddRow("scripting", m_scene.ScriptsEnabled); cdl.AddRow("teleport", m_scene.DebugTeleporting); -// cdl.AddRow("update-on-timer", m_scene.UpdateOnTimer); cdl.AddRow("updates", m_scene.DebugUpdates); MainConsole.Instance.OutputFormat("Scene {0} options:", m_scene.Name); @@ -207,60 +186,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments m_scene.DebugAnimations = active; } - if (options.ContainsKey("appear-refresh")) - { - bool newValue; - - // FIXME: This can only come from the console at the moment but might not always be true. - if (ConsoleUtil.TryParseConsoleBool(MainConsole.Instance, options["appear-refresh"], out newValue)) - m_scene.SendPeriodicAppearanceUpdates = newValue; - } - - if (options.ContainsKey("client-pos-upd")) - { - float newValue; - - // FIXME: This can only come from the console at the moment but might not always be true. - if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-pos-upd"], out newValue)) - m_scene.RootPositionUpdateTolerance = newValue; - } - - if (options.ContainsKey("client-rot-upd")) - { - float newValue; - - // FIXME: This can only come from the console at the moment but might not always be true. - if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-rot-upd"], out newValue)) - m_scene.RootRotationUpdateTolerance = newValue; - } - - if (options.ContainsKey("client-vel-upd")) - { - float newValue; - - // FIXME: This can only come from the console at the moment but might not always be true. - if (ConsoleUtil.TryParseConsoleFloat(MainConsole.Instance, options["client-vel-upd"], out newValue)) - m_scene.RootVelocityUpdateTolerance = newValue; - } - - if (options.ContainsKey("root-upd-per")) - { - int newValue; - - // FIXME: This can only come from the console at the moment but might not always be true. - if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, options["root-upd-per"], out newValue)) - m_scene.RootTerseUpdatePeriod = newValue; - } - - if (options.ContainsKey("child-upd-per")) - { - int newValue; - - // FIXME: This can only come from the console at the moment but might not always be true. - if (ConsoleUtil.TryParseConsoleNaturalInt(MainConsole.Instance, options["child-upd-per"], out newValue)) - m_scene.ChildTerseUpdatePeriod = newValue; - } - if (options.ContainsKey("pbackup")) { bool active; @@ -296,21 +221,6 @@ namespace OpenSim.Region.OptionalModules.Avatar.Attachments m_scene.DebugTeleporting = enableTeleportDebugging; } - if (options.ContainsKey("update-on-timer")) - { - bool enableUpdateOnTimer; - if (bool.TryParse(options["update-on-timer"], out enableUpdateOnTimer)) - { -// m_scene.UpdateOnTimer = enableUpdateOnTimer; - m_scene.Active = false; - - while (m_scene.IsRunning) - Thread.Sleep(20); - - m_scene.Active = true; - } - } - if (options.ContainsKey("updates")) { bool enableUpdateDebugging; diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs index e22c6eae9a..6e1f8bb654 100644 --- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs @@ -27,8 +27,13 @@ using System; using System.Collections.Generic; +using System.IO; using System.Reflection; using System.Timers; +using System.Threading; +using System.Xml; +using System.Xml.Serialization; + using OpenMetaverse; using log4net; using Mono.Addins; @@ -38,9 +43,7 @@ using OpenSim.Region.CoreModules.Framework.InterfaceCommander; using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; -using System.Xml; -using System.Xml.Serialization; -using System.IO; +using Timer= System.Timers.Timer; namespace OpenSim.Region.OptionalModules.World.TreePopulator { @@ -48,7 +51,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator /// Version 2.02 - Still hacky /// [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "TreePopulatorModule")] - public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule, IVegetationModule + public class TreePopulatorModule : INonSharedRegionModule, ICommandableModule { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private readonly Commander m_commander = new Commander("tree"); @@ -82,20 +85,20 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator { Copse cp = (Copse)DeserializeObject(fileName); - this.m_name = cp.m_name; - this.m_frozen = cp.m_frozen; - this.m_tree_quantity = cp.m_tree_quantity; - this.m_treeline_high = cp.m_treeline_high; - this.m_treeline_low = cp.m_treeline_low; - this.m_range = cp.m_range; - this.m_tree_type = cp.m_tree_type; - this.m_seed_point = cp.m_seed_point; - this.m_initial_scale = cp.m_initial_scale; - this.m_maximum_scale = cp.m_maximum_scale; - this.m_initial_scale = cp.m_initial_scale; - this.m_rate = cp.m_rate; - this.m_planted = planted; - this.m_trees = new List(); + m_name = cp.m_name; + m_frozen = cp.m_frozen; + m_tree_quantity = cp.m_tree_quantity; + m_treeline_high = cp.m_treeline_high; + m_treeline_low = cp.m_treeline_low; + m_range = cp.m_range; + m_tree_type = cp.m_tree_type; + m_seed_point = cp.m_seed_point; + m_initial_scale = cp.m_initial_scale; + m_maximum_scale = cp.m_maximum_scale; + m_initial_scale = cp.m_initial_scale; + m_rate = cp.m_rate; + m_planted = planted; + m_trees = new List(); } public Copse(string copsedef) @@ -103,61 +106,63 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator char[] delimiterChars = {':', ';'}; string[] field = copsedef.Split(delimiterChars); - this.m_name = field[1].Trim(); - this.m_frozen = (copsedef[0] == 'F'); - this.m_tree_quantity = int.Parse(field[2]); - this.m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo); - this.m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo); - this.m_range = double.Parse(field[5], Culture.NumberFormatInfo); - this.m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]); - this.m_seed_point = Vector3.Parse(field[7]); - this.m_initial_scale = Vector3.Parse(field[8]); - this.m_maximum_scale = Vector3.Parse(field[9]); - this.m_rate = Vector3.Parse(field[10]); - this.m_planted = true; - this.m_trees = new List(); + m_name = field[1].Trim(); + m_frozen = (copsedef[0] == 'F'); + m_tree_quantity = int.Parse(field[2]); + m_treeline_high = float.Parse(field[3], Culture.NumberFormatInfo); + m_treeline_low = float.Parse(field[4], Culture.NumberFormatInfo); + m_range = double.Parse(field[5], Culture.NumberFormatInfo); + m_tree_type = (Tree) Enum.Parse(typeof(Tree),field[6]); + m_seed_point = Vector3.Parse(field[7]); + m_initial_scale = Vector3.Parse(field[8]); + m_maximum_scale = Vector3.Parse(field[9]); + m_rate = Vector3.Parse(field[10]); + m_planted = true; + m_trees = new List(); } public Copse(string name, int quantity, float high, float low, double range, Vector3 point, Tree type, Vector3 scale, Vector3 max_scale, Vector3 rate, List trees) { - this.m_name = name; - this.m_frozen = false; - this.m_tree_quantity = quantity; - this.m_treeline_high = high; - this.m_treeline_low = low; - this.m_range = range; - this.m_tree_type = type; - this.m_seed_point = point; - this.m_initial_scale = scale; - this.m_maximum_scale = max_scale; - this.m_rate = rate; - this.m_planted = false; - this.m_trees = trees; + m_name = name; + m_frozen = false; + m_tree_quantity = quantity; + m_treeline_high = high; + m_treeline_low = low; + m_range = range; + m_tree_type = type; + m_seed_point = point; + m_initial_scale = scale; + m_maximum_scale = max_scale; + m_rate = rate; + m_planted = false; + m_trees = trees; } public override string ToString() { - string frozen = (this.m_frozen ? "F" : "A"); + string frozen = (m_frozen ? "F" : "A"); return string.Format("{0}TPM: {1}; {2}; {3:0.0}; {4:0.0}; {5:0.0}; {6}; {7:0.0}; {8:0.0}; {9:0.0}; {10:0.00};", frozen, - this.m_name, - this.m_tree_quantity, - this.m_treeline_high, - this.m_treeline_low, - this.m_range, - this.m_tree_type, - this.m_seed_point.ToString(), - this.m_initial_scale.ToString(), - this.m_maximum_scale.ToString(), - this.m_rate.ToString()); + m_name, + m_tree_quantity, + m_treeline_high, + m_treeline_low, + m_range, + m_tree_type, + m_seed_point.ToString(), + m_initial_scale.ToString(), + m_maximum_scale.ToString(), + m_rate.ToString()); } } - private List m_copse; - + private List m_copses = new List(); + private object mylock; private double m_update_ms = 1000.0; // msec between updates private bool m_active_trees = false; + private bool m_enabled = true; // original default + private bool m_allowGrow = true; // original default Timer CalculateTrees; @@ -174,51 +179,51 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator public void Initialise(IConfigSource config) { - - // ini file settings - try + IConfig moduleConfig = config.Configs["Trees"]; + if (moduleConfig != null) { - m_active_trees = config.Configs["Trees"].GetBoolean("active_trees", m_active_trees); - } - catch (Exception) - { - m_log.Debug("[TREES]: ini failure for active_trees - using default"); + m_enabled = moduleConfig.GetBoolean("enabled", m_enabled); + m_active_trees = moduleConfig.GetBoolean("active_trees", m_active_trees); + m_allowGrow = moduleConfig.GetBoolean("allowGrow", m_allowGrow); + m_update_ms = moduleConfig.GetDouble("update_rate", m_update_ms); } - try - { - m_update_ms = config.Configs["Trees"].GetDouble("update_rate", m_update_ms); - } - catch (Exception) - { - m_log.Debug("[TREES]: ini failure for update_rate - using default"); - } + if(!m_enabled) + return; + + m_copses = new List(); + mylock = new object(); InstallCommands(); - m_log.Debug("[TREES]: Initialised tree module"); + m_log.Debug("[TREES]: Initialised tree populator module"); } public void AddRegion(Scene scene) { + if(!m_enabled) + return; m_scene = scene; m_scene.RegisterModuleCommander(m_commander); m_scene.EventManager.OnPluginConsole += EventManager_OnPluginConsole; - + m_scene.EventManager.OnPrimsLoaded += EventManager_OnPrimsLoaded; } public void RemoveRegion(Scene scene) { - } + if(!m_enabled) + return; + if(m_active_trees && CalculateTrees != null) + { + CalculateTrees.Dispose(); + CalculateTrees = null; + } + m_scene.EventManager.OnPluginConsole -= EventManager_OnPluginConsole; + m_scene.EventManager.OnPrimsLoaded -= EventManager_OnPrimsLoaded; + } public void RegionLoaded(Scene scene) { - ReloadCopse(); - if (m_copse.Count > 0) - m_log.Info("[TREES]: Copse load complete"); - - if (m_active_trees) - activeizeTreeze(true); } public void Close() @@ -240,6 +245,16 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator //-------------------------------------------------------------- + private void EventManager_OnPrimsLoaded(Scene s) + { + ReloadCopse(); + if (m_copses.Count > 0) + m_log.Info("[TREES]: Copses loaded" ); + + if (m_active_trees) + activeizeTreeze(true); + } + #region ICommandableModule Members private void HandleTreeActive(Object[] args) @@ -267,25 +282,57 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator string copsename = ((string)args[0]).Trim(); Boolean freezeState = (Boolean) args[1]; - foreach (Copse cp in m_copse) + lock(mylock) { - if (cp.m_name == copsename && (!cp.m_frozen && freezeState || cp.m_frozen && !freezeState)) + foreach (Copse cp in m_copses) { - cp.m_frozen = freezeState; - foreach (UUID tree in cp.m_trees) - { - SceneObjectPart sop = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; - sop.Name = (freezeState ? sop.Name.Replace("ATPM", "FTPM") : sop.Name.Replace("FTPM", "ATPM")); - sop.ParentGroup.HasGroupChanged = true; - } + if (cp.m_name != copsename) + continue; - m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState); - return; - } - else if (cp.m_name == copsename && (cp.m_frozen && freezeState || !cp.m_frozen && !freezeState)) - { - m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename); - return; + if(!cp.m_frozen && freezeState || cp.m_frozen && !freezeState) + { + cp.m_frozen = freezeState; + List losttrees = new List(); + foreach (UUID tree in cp.m_trees) + { + SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree); + if(sog != null && !sog.IsDeleted) + { + SceneObjectPart sop = sog.RootPart; + string name = sop.Name; + if(freezeState) + { + if(name.StartsWith("FTPM")) + continue; + if(!name.StartsWith("ATPM")) + continue; + sop.Name = sop.Name.Replace("ATPM", "FTPM"); + } + else + { + if(name.StartsWith("ATPM")) + continue; + if(!name.StartsWith("FTPM")) + continue; + sop.Name = sop.Name.Replace("FTPM", "ATPM"); + } + sop.ParentGroup.HasGroupChanged = true; + sog.ScheduleGroupForFullUpdate(); + } + else + losttrees.Add(tree); + } + foreach (UUID tree in losttrees) + cp.m_trees.Remove(tree); + + m_log.InfoFormat("[TREES]: Activity for copse {0} is frozen {1}", copsename, freezeState); + return; + } + else + { + m_log.InfoFormat("[TREES]: Copse {0} is already in the requested freeze state", copsename); + return; + } } } m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename); @@ -297,17 +344,21 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator m_log.InfoFormat("[TREES]: Loading copse definition...."); - copse = new Copse(((string)args[0]), false); - foreach (Copse cp in m_copse) + lock(mylock) { - if (cp.m_name == copse.m_name) + copse = new Copse(((string)args[0]), false); { - m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name); - return; + foreach (Copse cp in m_copses) + { + if (cp.m_name == copse.m_name) + { + m_log.InfoFormat("[TREES]: Copse: {0} is already defined - command failed", copse.m_name); + return; + } + } } + m_copses.Add(copse); } - - m_copse.Add(copse); m_log.InfoFormat("[TREES]: Loaded copse: {0}", copse.ToString()); } @@ -318,20 +369,24 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator m_log.InfoFormat("[TREES]: New tree planting for copse {0}", copsename); UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; - foreach (Copse copse in m_copse) + lock(mylock) { - if (copse.m_name == copsename) + foreach (Copse copse in m_copses) { - if (!copse.m_planted) + if (copse.m_name == copsename) { - // The first tree for a copse is created here - CreateTree(uuid, copse, copse.m_seed_point); - copse.m_planted = true; - return; - } - else - { - m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename); + if (!copse.m_planted) + { + // The first tree for a copse is created here + CreateTree(uuid, copse, copse.m_seed_point, true); + copse.m_planted = true; + return; + } + else + { + m_log.InfoFormat("[TREES]: Copse {0} has already been planted", copsename); + return; + } } } } @@ -376,45 +431,49 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator string copsename = ((string)args[0]).Trim(); Copse copseIdentity = null; - foreach (Copse cp in m_copse) + lock(mylock) { - if (cp.m_name == copsename) + foreach (Copse cp in m_copses) { - copseIdentity = cp; + if (cp.m_name == copsename) + { + copseIdentity = cp; + } } - } - if (copseIdentity != null) - { - foreach (UUID tree in copseIdentity.m_trees) + if (copseIdentity != null) { - if (m_scene.Entities.ContainsKey(tree)) + foreach (UUID tree in copseIdentity.m_trees) { - SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; - // Delete tree and alert clients (not silent) - m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); - } - else - { - m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); + if (m_scene.Entities.ContainsKey(tree)) + { + SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; + // Delete tree and alert clients (not silent) + m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); + } + else + { + m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); + } } + copseIdentity.m_trees = null; + m_copses.Remove(copseIdentity); + m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename); + } + else + { + m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename); } - copseIdentity.m_trees = new List(); - m_copse.Remove(copseIdentity); - m_log.InfoFormat("[TREES]: Copse {0} has been removed", copsename); - } - else - { - m_log.InfoFormat("[TREES]: Copse {0} was not found - command failed", copsename); } } private void HandleTreeStatistics(Object[] args) { - m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms); - foreach (Copse cp in m_copse) + m_log.InfoFormat("[TREES]: region {0}:", m_scene.Name); + m_log.InfoFormat("[TREES]: Activity State: {0}; Update Rate: {1}", m_active_trees, m_update_ms); + foreach (Copse cp in m_copses) { - m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen); + m_log.InfoFormat("[TREES]: Copse {0}; {1} trees; frozen {2}", cp.m_name, cp.m_trees.Count, cp.m_frozen); } } @@ -442,7 +501,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator treeRateCommand.AddArgument("updateRate", "The required update rate (minimum 1000.0)", "Double"); Command treeReloadCommand = - new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copse definitions from the in-scene trees"); + new Command("reload", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeReload, "Reload copses from the in-scene trees"); Command treeRemoveCommand = new Command("remove", CommandIntentions.COMMAND_HAZARDOUS, HandleTreeRemove, "Remove a copse definition and all its in-scene trees"); @@ -499,34 +558,17 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator treeShape.Scale = scale; treeShape.State = (byte)treeType; - return m_scene.AddNewPrim(uuid, groupID, position, rotation, treeShape); - } - - #endregion - - #region IEntityCreator Members - - protected static readonly PCode[] creationCapabilities = new PCode[] { PCode.NewTree, PCode.Tree }; - public PCode[] CreationCapabilities { get { return creationCapabilities; } } - - public SceneObjectGroup CreateEntity( - UUID ownerID, UUID groupID, Vector3 pos, Quaternion rot, PrimitiveBaseShape shape) - { - if (Array.IndexOf(creationCapabilities, (PCode)shape.PCode) < 0) - { - m_log.DebugFormat("[VEGETATION]: PCode {0} not handled by {1}", shape.PCode, Name); - return null; - } - - SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID); + SceneObjectGroup sog = new SceneObjectGroup(uuid, position, rotation, treeShape); + SceneObjectPart rootPart = sog.RootPart; rootPart.AddFlag(PrimFlags.Phantom); - m_scene.AddNewSceneObject(sceneObject, true); - sceneObject.SetGroup(groupID, null); - - return sceneObject; + sog.SetGroup(groupID, null); + m_scene.AddNewSceneObject(sog, true, false); + sog.IsSelected = false; + rootPart.IsSelected = false; + sog.InvalidateEffectivePerms(); + return sog; } #endregion @@ -569,26 +611,27 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator private void ReloadCopse() { - m_copse = new List(); + m_copses = new List(); - EntityBase[] objs = m_scene.GetEntities(); - foreach (EntityBase obj in objs) + List grps = m_scene.GetSceneObjectGroups(); + foreach (SceneObjectGroup grp in grps) { - if (obj is SceneObjectGroup) + if(grp.RootPart.Shape.PCode != (byte)PCode.NewTree && grp.RootPart.Shape.PCode != (byte)PCode.Tree) + continue; + + if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:")) { - SceneObjectGroup grp = (SceneObjectGroup)obj; - - if (grp.Name.Length > 5 && (grp.Name.Substring(0, 5) == "ATPM:" || grp.Name.Substring(0, 5) == "FTPM:")) + // Create a new copse definition or add uuid to an existing definition + try { - // Create a new copse definition or add uuid to an existing definition - try - { - Boolean copsefound = false; - Copse copse = new Copse(grp.Name); + Boolean copsefound = false; + Copse grpcopse = new Copse(grp.Name); - foreach (Copse cp in m_copse) + lock(mylock) + { + foreach (Copse cp in m_copses) { - if (cp.m_name == copse.m_name) + if (cp.m_name == grpcopse.m_name) { copsefound = true; cp.m_trees.Add(grp.UUID); @@ -598,15 +641,15 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator if (!copsefound) { - m_log.InfoFormat("[TREES]: Found copse {0}", grp.Name); - m_copse.Add(copse); - copse.m_trees.Add(grp.UUID); + m_log.InfoFormat("[TREES]: adding copse {0}", grpcopse.m_name); + grpcopse.m_trees.Add(grp.UUID); + m_copses.Add(grpcopse); } } - catch - { - m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name); - } + } + catch + { + m_log.InfoFormat("[TREES]: Ill formed copse definition {0} - ignoring", grp.Name); } } } @@ -617,8 +660,10 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator { if (activeYN) { - CalculateTrees = new Timer(m_update_ms); + if(CalculateTrees == null) + CalculateTrees = new Timer(m_update_ms); CalculateTrees.Elapsed += CalculateTrees_Elapsed; + CalculateTrees.AutoReset = false; CalculateTrees.Start(); } else @@ -629,154 +674,251 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator private void growTrees() { - foreach (Copse copse in m_copse) - { - if (!copse.m_frozen) - { - foreach (UUID tree in copse.m_trees) - { - if (m_scene.Entities.ContainsKey(tree)) - { - SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; + if(!m_allowGrow) + return; - if (s_tree.Scale.X < copse.m_maximum_scale.X && s_tree.Scale.Y < copse.m_maximum_scale.Y && s_tree.Scale.Z < copse.m_maximum_scale.Z) - { - s_tree.Scale += copse.m_rate; - s_tree.ParentGroup.HasGroupChanged = true; - s_tree.ScheduleFullUpdate(); - } - } - else + foreach (Copse copse in m_copses) + { + if (copse.m_frozen) + continue; + + if(copse.m_trees.Count == 0) + continue; + + float maxscale = copse.m_maximum_scale.Z; + float ratescale = 1.0f; + List losttrees = new List(); + foreach (UUID tree in copse.m_trees) + { + SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree); + + if (sog != null && !sog.IsDeleted) + { + SceneObjectPart s_tree = sog.RootPart; + if (s_tree.Scale.Z < maxscale) { - m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); + ratescale = (float)Util.RandomClass.NextDouble(); + if(ratescale < 0.2f) + ratescale = 0.2f; + s_tree.Scale += copse.m_rate * ratescale; + sog.HasGroupChanged = true; + s_tree.ScheduleFullUpdate(); } } + else + losttrees.Add(tree); } + + foreach (UUID tree in losttrees) + copse.m_trees.Remove(tree); } } private void seedTrees() { - foreach (Copse copse in m_copse) + foreach (Copse copse in m_copses) { - if (!copse.m_frozen) - { - foreach (UUID tree in copse.m_trees) - { - if (m_scene.Entities.ContainsKey(tree)) - { - SceneObjectPart s_tree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; + if (copse.m_frozen) + continue; - if (copse.m_trees.Count < copse.m_tree_quantity) - { - // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height - if (s_tree.Scale.Z > copse.m_initial_scale.Z + (copse.m_maximum_scale.Z - copse.m_initial_scale.Z) / 4.0) - { - if (Util.RandomClass.NextDouble() > 0.75) - { - SpawnChild(copse, s_tree); - } - } - } - } - else - { - m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); - } + if(copse.m_trees.Count == 0) + return; + + bool low = copse.m_trees.Count < (int)(copse.m_tree_quantity * 0.8f); + + if (!low && Util.RandomClass.NextDouble() < 0.75) + return; + + int maxbirths = (int)(copse.m_tree_quantity) - copse.m_trees.Count; + if(maxbirths <= 1) + return; + + if(maxbirths > 20) + maxbirths = 20; + + float minscale = 0; + if(!low && m_allowGrow) + minscale = copse.m_maximum_scale.Z * 0.75f;; + + int i = 0; + UUID[] current = copse.m_trees.ToArray(); + while(--maxbirths > 0) + { + if(current.Length > 1) + i = Util.RandomClass.Next(current.Length -1); + + UUID tree = current[i]; + SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree); + + if (sog != null && !sog.IsDeleted) + { + SceneObjectPart s_tree = sog.RootPart; + + // Tree has grown enough to seed if it has grown by at least 25% of seeded to full grown height + if (s_tree.Scale.Z > minscale) + SpawnChild(copse, s_tree, true); } - } + else if(copse.m_trees.Contains(tree)) + copse.m_trees.Remove(tree); + } } } private void killTrees() { - foreach (Copse copse in m_copse) + foreach (Copse copse in m_copses) { - if (!copse.m_frozen && copse.m_trees.Count >= copse.m_tree_quantity) + if (copse.m_frozen) + continue; + + if (Util.RandomClass.NextDouble() < 0.25) + return; + + int maxbdeaths = copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) ; + if(maxbdeaths < 1) + return; + + float odds; + float scale = 1.0f / copse.m_maximum_scale.Z; + + int ntries = maxbdeaths * 4; + while(ntries-- > 0 ) { - foreach (UUID tree in copse.m_trees) + int next = 0; + if (copse.m_trees.Count > 1) + next = Util.RandomClass.Next(copse.m_trees.Count - 1); + UUID tree = copse.m_trees[next]; + SceneObjectGroup sog = m_scene.GetSceneObjectGroup(tree); + if (sog != null && !sog.IsDeleted) { - double killLikelyhood = 0.0; - - if (m_scene.Entities.ContainsKey(tree)) + if(m_allowGrow) { - SceneObjectPart selectedTree = ((SceneObjectGroup)m_scene.Entities[tree]).RootPart; - double selectedTreeScale = Math.Sqrt(Math.Pow(selectedTree.Scale.X, 2) + - Math.Pow(selectedTree.Scale.Y, 2) + - Math.Pow(selectedTree.Scale.Z, 2)); - - foreach (UUID picktree in copse.m_trees) - { - if (picktree != tree) - { - SceneObjectPart pickedTree = ((SceneObjectGroup)m_scene.Entities[picktree]).RootPart; - - double pickedTreeScale = Math.Sqrt(Math.Pow(pickedTree.Scale.X, 2) + - Math.Pow(pickedTree.Scale.Y, 2) + - Math.Pow(pickedTree.Scale.Z, 2)); - - double pickedTreeDistance = Vector3.Distance(pickedTree.AbsolutePosition, selectedTree.AbsolutePosition); - - killLikelyhood += (selectedTreeScale / (pickedTreeScale * pickedTreeDistance)) * 0.1; - } - } - - if (Util.RandomClass.NextDouble() < killLikelyhood) - { - // Delete tree and alert clients (not silent) - m_scene.DeleteSceneObject(selectedTree.ParentGroup, false); - copse.m_trees.Remove(selectedTree.ParentGroup.UUID); - break; - } + odds = sog.RootPart.Scale.Z * scale; + odds = odds * odds * odds; + odds *= (float)Util.RandomClass.NextDouble(); } else { - m_log.DebugFormat("[TREES]: Tree not in scene {0}", tree); + odds = (float)Util.RandomClass.NextDouble(); + odds = odds * odds * odds; } + + if(odds > 0.9f) + { + m_scene.DeleteSceneObject(sog, false); + if(maxbdeaths <= 0) + break; + } + } + else + { + copse.m_trees.Remove(tree); + if(copse.m_trees.Count - (int)(copse.m_tree_quantity * .98f) <= 0 ) + break; } } } } - private void SpawnChild(Copse copse, SceneObjectPart s_tree) + private void SpawnChild(Copse copse, SceneObjectPart s_tree, bool low) { Vector3 position = new Vector3(); - - double randX = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); - double randY = ((Util.RandomClass.NextDouble() * 2.0) - 1.0) * (s_tree.Scale.X * 3); - + + float randX = copse.m_maximum_scale.X * 1.25f; + float randY = copse.m_maximum_scale.Y * 1.25f; + + float r = (float)Util.RandomClass.NextDouble(); + randX *= 2.0f * r - 1.0f; position.X = s_tree.AbsolutePosition.X + (float)randX; + + r = (float)Util.RandomClass.NextDouble(); + randY *= 2.0f * r - 1.0f; position.Y = s_tree.AbsolutePosition.Y + (float)randY; - if (position.X <= (m_scene.RegionInfo.RegionSizeX - 1) && position.X >= 0 && - position.Y <= (m_scene.RegionInfo.RegionSizeY - 1) && position.Y >= 0 && - Util.GetDistanceTo(position, copse.m_seed_point) <= copse.m_range) - { - UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; + if (position.X > (m_scene.RegionInfo.RegionSizeX - 1) || position.X <= 0 || + position.Y > (m_scene.RegionInfo.RegionSizeY - 1) || position.Y <= 0) + return; - CreateTree(uuid, copse, position); - } + randX = position.X - copse.m_seed_point.X; + randX *= randX; + randY = position.Y - copse.m_seed_point.Y; + randY *= randY; + randX += randY; + + if(randX > copse.m_range * copse.m_range) + return; + + UUID uuid = m_scene.RegionInfo.EstateSettings.EstateOwner; + CreateTree(uuid, copse, position, low); } - private void CreateTree(UUID uuid, Copse copse, Vector3 position) + private void CreateTree(UUID uuid, Copse copse, Vector3 position, bool randomScale) { - position.Z = (float)m_scene.Heightmap[(int)position.X, (int)position.Y]; - if (position.Z >= copse.m_treeline_low && position.Z <= copse.m_treeline_high) - { - SceneObjectGroup tree = AddTree(uuid, UUID.Zero, copse.m_initial_scale, Quaternion.Identity, position, copse.m_tree_type, false); + if (position.Z < copse.m_treeline_low || position.Z > copse.m_treeline_high) + return; - tree.Name = copse.ToString(); - copse.m_trees.Add(tree.UUID); - tree.SendGroupFullUpdate(); + Vector3 scale = copse.m_initial_scale; + if(randomScale) + { + try + { + float t; + float r = (float)Util.RandomClass.NextDouble(); + r *= (float)Util.RandomClass.NextDouble(); + r *= (float)Util.RandomClass.NextDouble(); + + t = copse.m_maximum_scale.X / copse.m_initial_scale.X; + if(t < 1.0) + t = 1 / t; + t = t * r + 1.0f; + scale.X *= t; + + t = copse.m_maximum_scale.Y / copse.m_initial_scale.Y; + if(t < 1.0) + t = 1 / t; + t = t * r + 1.0f; + scale.Y *= t; + + t = copse.m_maximum_scale.Z / copse.m_initial_scale.Z; + if(t < 1.0) + t = 1 / t; + t = t * r + 1.0f; + scale.Z *= t; + } + catch + { + scale = copse.m_initial_scale; + } } + + SceneObjectGroup tree = AddTree(uuid, UUID.Zero, scale, Quaternion.Identity, position, copse.m_tree_type, false); + tree.Name = copse.ToString(); + copse.m_trees.Add(tree.UUID); + tree.RootPart.ScheduleFullUpdate(); } private void CalculateTrees_Elapsed(object sender, ElapsedEventArgs e) { - growTrees(); - seedTrees(); - killTrees(); + if(!m_scene.IsRunning) + return; + + if(Monitor.TryEnter(mylock)) + { + try + { + if(m_scene.LoginsEnabled ) + { + growTrees(); + seedTrees(); + killTrees(); + } + } + catch { } + if(CalculateTrees != null) + CalculateTrees.Start(); + Monitor.Exit(mylock); + } } } } diff --git a/OpenSim/Region/PhysicsModules/BulletS/BSTerrainHeightmap.cs b/OpenSim/Region/PhysicsModules/BulletS/BSTerrainHeightmap.cs index 42fc11bcd5..f72ad28600 100755 --- a/OpenSim/Region/PhysicsModules/BulletS/BSTerrainHeightmap.cs +++ b/OpenSim/Region/PhysicsModules/BulletS/BSTerrainHeightmap.cs @@ -141,14 +141,30 @@ public sealed class BSTerrainHeightmap : BSTerrainPhys } // The passed position is relative to the base of the region. + // There are many assumptions herein that the heightmap increment is 1. public override float GetTerrainHeightAtXYZ(Vector3 pos) { float ret = BSTerrainManager.HEIGHT_GETHEIGHT_RET; - int mapIndex = (int)pos.Y * (int)m_mapInfo.sizeY + (int)pos.X; - try - { - ret = m_mapInfo.heightMap[mapIndex]; + try { + int baseX = (int)pos.X; + int baseY = (int)pos.Y; + int maxX = (int)m_mapInfo.sizeX; + int maxY = (int)m_mapInfo.sizeY; + float diffX = pos.X - (float)baseX; + float diffY = pos.Y - (float)baseY; + + float mapHeight1 = m_mapInfo.heightMap[baseY * maxY + baseX]; + float mapHeight2 = m_mapInfo.heightMap[Math.Min(baseY + 1, maxY - 1) * maxY + baseX]; + float mapHeight3 = m_mapInfo.heightMap[baseY * maxY + Math.Min(baseX + 1, maxX - 1)]; + float mapHeight4 = m_mapInfo.heightMap[Math.Min(baseY + 1, maxY - 1) * maxY + Math.Min(baseX + 1, maxX - 1)]; + + float Xrise = (mapHeight4 - mapHeight3) * diffX; + float Yrise = (mapHeight2 - mapHeight1) * diffY; + + ret = mapHeight1 + ((Xrise + Yrise) / 2f); + // m_physicsScene.DetailLog("{0},BSTerrainHeightMap,GetTerrainHeightAtXYZ,pos={1},{2}/{3}/{4}/{5},ret={6}", + // BSScene.DetailLogZero, pos, mapHeight1, mapHeight2, mapHeight3, mapHeight4, ret); } catch { diff --git a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs index 4f95554863..0d4b6b96f2 100644 --- a/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs +++ b/OpenSim/Region/PhysicsModules/Meshing/Meshmerizer/Meshmerizer.cs @@ -66,7 +66,7 @@ namespace OpenSim.Region.PhysicsModule.Meshing private bool cacheSculptMaps = true; private string decodedSculptMapPath = null; - private bool useMeshiesPhysicsMesh = false; + private bool useMeshiesPhysicsMesh = true; private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh diff --git a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs index 33f033759b..2fa98b579e 100644 --- a/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs +++ b/OpenSim/Region/PhysicsModules/SharedBase/PhysicsActor.cs @@ -256,6 +256,7 @@ namespace OpenSim.Region.PhysicsModules.SharedBase /// public string SOPName; + public virtual void CrossingStart() { } public abstract void CrossingFailure(); public abstract void link(PhysicsActor obj); @@ -462,6 +463,23 @@ namespace OpenSim.Region.PhysicsModules.SharedBase public abstract bool SubscribedEvents(); public virtual void AddCollisionEvent(uint CollidedWith, ContactPoint contact) { } + public virtual void AddVDTCCollisionEvent(uint CollidedWith, ContactPoint contact) { } + + public virtual PhysicsInertiaData GetInertiaData() + { + PhysicsInertiaData data = new PhysicsInertiaData(); + data.TotalMass = this.Mass; + data.CenterOfMass = CenterOfMass - Position; + data.Inertia = Vector3.Zero; + data.InertiaRotation = Vector4.Zero; + return data; + } + + public virtual void SetInertiaData(PhysicsInertiaData inertia) + { + } + + public virtual float SimulationSuspended { get; set; } // Warning in a parent part it returns itself, not null public virtual PhysicsActor ParentActor { get { return this; } } diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs index 9cef3d5496..0e46471879 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODECharacter.cs @@ -103,7 +103,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde public float walkDivisor = 1.3f; public float runDivisor = 0.8f; - private bool flying = false; + private bool m_flying = false; private bool m_iscolliding = false; private bool m_iscollidingGround = false; private bool m_iscollidingObj = false; @@ -138,7 +138,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde ); // we do land collisions not ode | CollisionCategories.Land); public IntPtr Body = IntPtr.Zero; - private ODEScene _parent_scene; + private ODEScene m_parent_scene; private IntPtr capsule = IntPtr.Zero; public IntPtr collider = IntPtr.Zero; @@ -169,6 +169,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde { m_uuid = UUID.Random(); m_localID = localID; + m_parent_scene = parent_scene; timeStep = parent_scene.ODE_STEPSIZE; invtimeStep = 1 / timeStep; @@ -187,13 +188,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde } else { - _position = new Vector3(((float)_parent_scene.WorldExtents.X * 0.5f), ((float)_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); + _position = new Vector3(((float)m_parent_scene.WorldExtents.X * 0.5f), ((float)m_parent_scene.WorldExtents.Y * 0.5f), parent_scene.GetTerrainHeightAtXY(128f, 128f) + 10f); m_log.Warn("[PHYSICS]: Got NaN Position on Character Create"); } - _parent_scene = parent_scene; - - m_size.X = pSize.X; m_size.Y = pSize.Y; m_size.Z = pSize.Z; @@ -213,7 +211,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde // force lower density for testing m_density = 3.0f; - mu = parent_scene.AvatarFriction; + mu = m_parent_scene.AvatarFriction; walkDivisor = walk_divisor; runDivisor = rundivisor; @@ -300,10 +298,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde public override bool Flying { - get { return flying; } + get { return m_flying; } set { - flying = value; + m_flying = value; // m_log.DebugFormat("[PHYSICS]: Set OdeCharacter Flying to {0}", flying); } } @@ -437,11 +435,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde { if (value.Z > 9999999f) { - value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5; + value.Z = m_parent_scene.GetTerrainHeightAtXY(127, 127) + 5; } if (value.Z < -100f) { - value.Z = _parent_scene.GetTerrainHeightAtXY(127, 127) + 5; + value.Z = m_parent_scene.GetTerrainHeightAtXY(127, 127) + 5; } AddChange(changes.Position, value); } @@ -704,7 +702,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde { if (pushforce) { - AddChange(changes.Force, force * m_density / (_parent_scene.ODE_STEPSIZE * 28f)); + AddChange(changes.Force, force * m_density / (m_parent_scene.ODE_STEPSIZE * 28f)); } else { @@ -751,9 +749,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde AvaAvaSizeYsq = 0.5f * sy; AvaAvaSizeYsq *= AvaAvaSizeYsq; - _parent_scene.waitForSpaceUnlock(_parent_scene.CharsSpace); + m_parent_scene.waitForSpaceUnlock(m_parent_scene.CharsSpace); - collider = d.HashSpaceCreate(_parent_scene.CharsSpace); + collider = d.HashSpaceCreate(m_parent_scene.CharsSpace); d.HashSpaceSetLevels(collider, -4, 3); d.SpaceSetSublevel(collider, 3); d.SpaceSetCleanup(collider, false); @@ -772,10 +770,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde d.MassSetBoxTotal(out ShellMass, m_mass, m_size.X, m_size.Y, m_size.Z); - PID_D = basePID_D * m_mass / _parent_scene.ODE_STEPSIZE; - PID_P = basePID_P * m_mass / _parent_scene.ODE_STEPSIZE; + PID_D = basePID_D * m_mass / m_parent_scene.ODE_STEPSIZE; + PID_P = basePID_P * m_mass / m_parent_scene.ODE_STEPSIZE; - Body = d.BodyCreate(_parent_scene.world); + Body = d.BodyCreate(m_parent_scene.world); _zeroFlag = false; m_pidControllerActive = true; @@ -795,7 +793,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde // The purpose of the AMotor here is to keep the avatar's physical // surrogate from rotating while moving - Amotor = d.JointCreateAMotor(_parent_scene.world, IntPtr.Zero); + Amotor = d.JointCreateAMotor(m_parent_scene.world, IntPtr.Zero); d.JointAttach(Amotor, Body, IntPtr.Zero); d.JointSetAMotorMode(Amotor, 0); @@ -854,8 +852,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde //kill the Geoms if (capsule != IntPtr.Zero) { - _parent_scene.actor_name_map.Remove(capsule); - _parent_scene.waitForSpaceUnlock(collider); + m_parent_scene.actor_name_map.Remove(capsule); + m_parent_scene.waitForSpaceUnlock(collider); d.GeomDestroy(capsule); capsule = IntPtr.Zero; } @@ -901,9 +899,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde y = tx * sin + y * cos; } - public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact, + public bool Collide(IntPtr me, IntPtr other, bool reverse, ref d.ContactGeom contact, ref d.ContactGeom altContact , ref bool useAltcontact, ref bool feetcollision) - { + { feetcollision = false; useAltcontact = false; @@ -945,12 +943,13 @@ namespace OpenSim.Region.PhysicsModule.ubOde } return true; } -/* - d.AABB aabb; - d.GeomGetAABB(other,out aabb); - float othertop = aabb.MaxZ - _position.Z; -*/ -// if (offset.Z > 0 || othertop > -feetOff || contact.normal.Z > 0.35f) + + if (gtype == d.GeomClassID.SphereClass && d.GeomGetBody(other) != IntPtr.Zero) + { + if(d.GeomSphereGetRadius(other) < 0.5) + return true; + } + if (offset.Z > 0 || contact.normal.Z > 0.35f) { if (offset.Z <= 0) @@ -967,6 +966,18 @@ namespace OpenSim.Region.PhysicsModule.ubOde return true; } + if(m_flying) + return true; + + feetcollision = true; + if (h < boneOff) + { + m_collideNormal.X = contact.normal.X; + m_collideNormal.Y = contact.normal.Y; + m_collideNormal.Z = contact.normal.Z; + IsColliding = true; + } + altContact = contact; useAltcontact = true; @@ -974,8 +985,21 @@ namespace OpenSim.Region.PhysicsModule.ubOde offset.Normalize(); - if (contact.depth > 0.1f) - contact.depth = 0.1f; + float tdp = contact.depth; + float t = offset.X; + t = Math.Abs(t); + if(t > 1e-6) + { + tdp /= t; + tdp *= contact.normal.X; + } + else + tdp *= 10; + + if (tdp > 0.25f) + tdp = 0.25f; + + altContact.depth = tdp; if (reverse) { @@ -989,15 +1013,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde altContact.normal.Y = -offset.Y; altContact.normal.Z = -offset.Z; } - - feetcollision = true; - if (h < boneOff) - { - m_collideNormal.X = contact.normal.X; - m_collideNormal.Y = contact.normal.Y; - m_collideNormal.Z = contact.normal.Z; - IsColliding = true; - } return true; } return false; @@ -1049,20 +1064,20 @@ namespace OpenSim.Region.PhysicsModule.ubOde fixbody = true; localpos.X = 0.1f; } - else if (localpos.X > _parent_scene.WorldExtents.X - 0.1f) + else if (localpos.X > m_parent_scene.WorldExtents.X - 0.1f) { fixbody = true; - localpos.X = _parent_scene.WorldExtents.X - 0.1f; + localpos.X = m_parent_scene.WorldExtents.X - 0.1f; } if (localpos.Y < 0.0f) { fixbody = true; localpos.Y = 0.1f; } - else if (localpos.Y > _parent_scene.WorldExtents.Y - 0.1) + else if (localpos.Y > m_parent_scene.WorldExtents.Y - 0.1) { fixbody = true; - localpos.Y = _parent_scene.WorldExtents.Y - 0.1f; + localpos.Y = m_parent_scene.WorldExtents.Y - 0.1f; } if (fixbody) { @@ -1100,14 +1115,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde float ftmp; - if (flying) + if (m_flying) { ftmp = timeStep; posch.X += vel.X * ftmp; posch.Y += vel.Y * ftmp; } - float terrainheight = _parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y); + float terrainheight = m_parent_scene.GetTerrainHeightAtXY(posch.X, posch.Y); if (chrminZ < terrainheight) { if (ctz.Z < 0) @@ -1119,12 +1134,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_haveLastFallVel = true; } - Vector3 n = _parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y); + Vector3 n = m_parent_scene.GetTerrainNormalAtXY(posch.X, posch.Y); float depth = terrainheight - chrminZ; vec.Z = depth * PID_P * 50; - if (!flying) + if (!m_flying) { vec.Z += -vel.Z * PID_D; if(n.Z < 0.4f) @@ -1215,7 +1230,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde break; case PIDHoverType.GroundAndWater: - float waterHeight = _parent_scene.GetWaterLevel(); + float waterHeight = m_parent_scene.GetWaterLevel(); if (terrainheight > waterHeight) m_targetHoverHeight = terrainheight + m_PIDHoverHeight; else @@ -1261,7 +1276,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde // movement relative to surface if moving on it // dont disturbe vertical movement, ie jumps - if (m_iscolliding && !flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f) + if (m_iscolliding && !m_flying && ctz.Z == 0 && m_collideNormal.Z > 0.2f && m_collideNormal.Z < 0.94f) { float p = ctz.X * m_collideNormal.X + ctz.Y * m_collideNormal.Y; ctz.X *= (float)Math.Sqrt(1 - m_collideNormal.X * m_collideNormal.X); @@ -1278,7 +1293,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde { // if velocity is zero, use position control; otherwise, velocity control - if (tviszero && m_iscolliding && !flying) + if (tviszero && m_iscolliding && !m_flying) { // keep track of where we stopped. No more slippin' & slidin' if (!_zeroFlag) @@ -1315,7 +1330,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (m_iscolliding) { - if (!flying) + if (!m_flying) { // we are on a surface if (ctz.Z > 0f) @@ -1363,7 +1378,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde } else // ie not colliding { - if (flying || hoverPIDActive) //(!m_iscolliding && flying) + if (m_flying || hoverPIDActive) //(!m_iscolliding && flying) { // we're in mid air suspended vec.X += (ctz.X - vel.X) * (PID_D); @@ -1381,7 +1396,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde vec.Y += (ctz.Y - vel.Y) * PID_D * 0.833f; // hack for breaking on fall if (ctz.Z == -9999f) - vec.Z += -vel.Z * PID_D - _parent_scene.gravityz * m_mass; + vec.Z += -vel.Z * PID_D - m_parent_scene.gravityz * m_mass; } } } @@ -1399,15 +1414,15 @@ namespace OpenSim.Region.PhysicsModule.ubOde breakfactor = m_mass; vec.X -= breakfactor * vel.X; vec.Y -= breakfactor * vel.Y; - if (flying) + if (m_flying) vec.Z -= 0.5f * breakfactor * vel.Z; else vec.Z -= .16f* m_mass * vel.Z; } - if (flying || hoverPIDActive) + if (m_flying || hoverPIDActive) { - vec.Z -= _parent_scene.gravityz * m_mass; + vec.Z -= m_parent_scene.gravityz * m_mass; if(!hoverPIDActive) { @@ -1585,7 +1600,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde public override void UnSubscribeEvents() { m_eventsubscription = 0; - _parent_scene.RemoveCollisionEventReporting(this); + m_parent_scene.RemoveCollisionEventReporting(this); lock(CollisionEventsThisFrame) CollisionEventsThisFrame.Clear(); } @@ -1594,7 +1609,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde { lock(CollisionEventsThisFrame) CollisionEventsThisFrame.AddCollider(CollidedWith, contact); - _parent_scene.AddCollisionEventReporting(this); + m_parent_scene.AddCollisionEventReporting(this); } public void SendCollisions(int timestep) @@ -1645,14 +1660,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde AvatarGeomAndBodyCreation(_position.X, _position.Y, _position.Z); - _parent_scene.actor_name_map[collider] = (PhysicsActor)this; - _parent_scene.actor_name_map[capsule] = (PhysicsActor)this; - _parent_scene.AddCharacter(this); + m_parent_scene.actor_name_map[collider] = (PhysicsActor)this; + m_parent_scene.actor_name_map[capsule] = (PhysicsActor)this; + m_parent_scene.AddCharacter(this); } else { - _parent_scene.RemoveCollisionEventReporting(this); - _parent_scene.RemoveCharacter(this); + m_parent_scene.RemoveCollisionEventReporting(this); + m_parent_scene.RemoveCharacter(this); // destroy avatar capsule and related ODE data AvatarGeomAndBodyDestroy(); } @@ -1699,8 +1714,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde // Velocity = Vector3.Zero; m_targetVelocity = Vector3.Zero; - _parent_scene.actor_name_map[collider] = (PhysicsActor)this; - _parent_scene.actor_name_map[capsule] = (PhysicsActor)this; + m_parent_scene.actor_name_map[collider] = (PhysicsActor)this; + m_parent_scene.actor_name_map[capsule] = (PhysicsActor)this; } m_freemove = false; m_pidControllerActive = true; @@ -2008,7 +2023,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde public void AddChange(changes what, object arg) { - _parent_scene.AddChange((PhysicsActor)this, what, arg); + m_parent_scene.AddChange((PhysicsActor)this, what, arg); } private struct strAvatarSize diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs index 63bef7cdc6..ce10065af9 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODEDynamics.cs @@ -243,6 +243,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde internal void ProcessFloatVehicleParam(Vehicle pParam, float pValue) { float len; + if(float.IsNaN(pValue) || float.IsInfinity(pValue)) + return; switch (pParam) { @@ -343,6 +345,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (rootPrim.Body != IntPtr.Zero && !d.BodyIsEnabled(rootPrim.Body) && !rootPrim.m_isSelected && !rootPrim.m_disabled) d.BodyEnable(rootPrim.Body); + break; case Vehicle.LINEAR_FRICTION_TIMESCALE: if (pValue < m_timestep) pValue = m_timestep; @@ -374,6 +377,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde internal void ProcessVectorVehicleParam(Vehicle pParam, Vector3 pValue) { float len; + if(!pValue.IsFinite()) + return; switch (pParam) { diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs index 923e2ff8ba..5465035c58 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODEMeshWorker.cs @@ -62,6 +62,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde public byte shapetype; public bool hasOBB; public bool hasMeshVolume; + public bool isTooSmall; public MeshState meshState; public UUID? assetID; public meshWorkerCmnds comand; @@ -69,18 +70,16 @@ namespace OpenSim.Region.PhysicsModule.ubOde public class ODEMeshWorker { - private ILog m_log; private ODEScene m_scene; private IMesher m_mesher; public bool meshSculptedPrim = true; - public bool forceSimplePrimMeshing = false; public float meshSculptLOD = 32; public float MeshSculptphysicalLOD = 32; + public float MinSizeToMeshmerize = 0.1f; - - private OpenSim.Framework.BlockingQueue createqueue = new OpenSim.Framework.BlockingQueue(); + private OpenSim.Framework.BlockingQueue workQueue = new OpenSim.Framework.BlockingQueue(); private bool m_running; private Thread m_thread; @@ -93,9 +92,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (pConfig != null) { - forceSimplePrimMeshing = pConfig.GetBoolean("force_simple_prim_meshing", forceSimplePrimMeshing); meshSculptedPrim = pConfig.GetBoolean("mesh_sculpted_prim", meshSculptedPrim); meshSculptLOD = pConfig.GetFloat("mesh_lod", meshSculptLOD); + MinSizeToMeshmerize = pConfig.GetFloat("mesh_min_size", MinSizeToMeshmerize); MeshSculptphysicalLOD = pConfig.GetFloat("mesh_physical_lod", MeshSculptphysicalLOD); } m_running = true; @@ -110,7 +109,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde while(m_running) { - ODEPhysRepData nextRep = createqueue.Dequeue(); + ODEPhysRepData nextRep = workQueue.Dequeue(); if(!m_running) return; if (nextRep == null) @@ -139,7 +138,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde try { m_thread.Abort(); - createqueue.Clear(); + workQueue.Clear(); } catch { @@ -196,7 +195,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde repData.meshState = MeshState.loadingAsset; repData.comand = meshWorkerCmnds.getmesh; - createqueue.Enqueue(repData); + workQueue.Enqueue(repData); } } @@ -242,7 +241,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (needsMeshing(repData)) // no need for pbs now? { repData.comand = meshWorkerCmnds.changefull; - createqueue.Enqueue(repData); + workQueue.Enqueue(repData); } } else @@ -288,6 +287,16 @@ namespace OpenSim.Region.PhysicsModule.ubOde { PrimitiveBaseShape pbs = repData.pbs; // check sculpts or meshs + + Vector3 scale = pbs.Scale; + if(scale.X <= MinSizeToMeshmerize && + scale.Y <= MinSizeToMeshmerize && + scale.Z <= MinSizeToMeshmerize) + { + repData.isTooSmall = true; + return false; + } + if (pbs.SculptEntry) { if (meshSculptedPrim) @@ -299,9 +308,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde return false; } - if (forceSimplePrimMeshing) - return true; - // convex shapes have no holes ushort profilehollow = pbs.ProfileHollow; if(repData.shapetype == 2) @@ -425,17 +431,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde Vector3 size = repData.size; int clod = (int)LevelOfDetail.High; - bool convex; byte shapetype = repData.shapetype; - if (shapetype == 0) - convex = false; - else - { - convex = true; - // sculpts pseudo convex - if (pbs.SculptEntry && pbs.SculptType != (byte)SculptType.Mesh) - clod = (int)LevelOfDetail.Low; - } + bool convex = shapetype == 2; mesh = m_mesher.GetMesh(actor.Name, pbs, size, clod, true, convex); @@ -563,10 +560,16 @@ namespace OpenSim.Region.PhysicsModule.ubOde private void CalculateBasicPrimVolume(ODEPhysRepData repData) { - PrimitiveBaseShape _pbs = repData.pbs; Vector3 _size = repData.size; float volume = _size.X * _size.Y * _size.Z; // default + if(repData.isTooSmall) + { + repData.volume = volume; + return; + } + + PrimitiveBaseShape _pbs = repData.pbs; float tmp; float hollowAmount = (float)_pbs.ProfileHollow * 2.0e-5f; @@ -936,7 +939,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde repData.actor.Name, asset.ID.ToString()); } else - m_log.WarnFormat("[PHYSICS]: asset provider returned null asset fo mesh of prim {0}.", + m_log.WarnFormat("[PHYSICS]: asset provider returned null asset for mesh of prim {0}.", repData.actor.Name); } } diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs index a2fbf41ec6..aa208e2370 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODEPrim.cs @@ -85,7 +85,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde private Vector3 m_lastposition; private Vector3 m_rotationalVelocity; private Vector3 _size; - private Vector3 _acceleration; + private Vector3 m_acceleration; private IntPtr Amotor; internal Vector3 m_force; @@ -109,8 +109,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde private float m_waterHeight; private float m_buoyancy; //KF: m_buoyancy should be set by llSetBuoyancy() for non-vehicle. - private int body_autodisable_frames; - public int bodydisablecontrol = 0; + private int m_body_autodisable_frames; + public int m_bodydisablecontrol = 0; private float m_gravmod = 1.0f; // Default we're a Geometry @@ -165,6 +165,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde private float m_density; private byte m_shapetype; + private byte m_fakeShapetype; public bool _zeroFlag; private bool m_lastUpdateSent; @@ -182,18 +183,21 @@ namespace OpenSim.Region.PhysicsModule.ubOde private float m_streamCost; public d.Mass primdMass; // prim inertia information on it's own referencial + private PhysicsInertiaData m_InertiaOverride; float primMass; // prim own mass float primVolume; // prim own volume; - float _mass; // object mass acording to case + float m_mass; // object mass acording to case public int givefakepos; private Vector3 fakepos; public int givefakeori; private Quaternion fakeori; + private PhysicsInertiaData m_fakeInertiaOverride; private int m_eventsubscription; private int m_cureventsubscription; private CollisionEventUpdate CollisionEventsThisFrame = null; + private CollisionEventUpdate CollisionVDTCEventsThisFrame = null; private bool SentEmptyCollisionsEvent; public volatile bool childPrim; @@ -417,7 +421,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde { if (value.IsFinite()) { - _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_shapetype); + _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, value, m_fakeShapetype); } else { @@ -465,6 +469,103 @@ namespace OpenSim.Region.PhysicsModule.ubOde } } + public override PhysicsInertiaData GetInertiaData() + { + PhysicsInertiaData inertia; + if(childPrim) + { + if(_parent != null) + return _parent.GetInertiaData(); + else + { + inertia = new PhysicsInertiaData(); + inertia.TotalMass = -1; + return inertia; + } + } + + inertia = new PhysicsInertiaData(); + + // double buffering + if(m_fakeInertiaOverride != null) + { + d.Mass objdmass = new d.Mass(); + objdmass.I.M00 = m_fakeInertiaOverride.Inertia.X; + objdmass.I.M11 = m_fakeInertiaOverride.Inertia.Y; + objdmass.I.M22 = m_fakeInertiaOverride.Inertia.Z; + + objdmass.mass = m_fakeInertiaOverride.TotalMass; + + if(Math.Abs(m_fakeInertiaOverride.InertiaRotation.W) < 0.999) + { + d.Matrix3 inertiarotmat = new d.Matrix3(); + d.Quaternion inertiarot = new d.Quaternion(); + + inertiarot.X = m_fakeInertiaOverride.InertiaRotation.X; + inertiarot.Y = m_fakeInertiaOverride.InertiaRotation.Y; + inertiarot.Z = m_fakeInertiaOverride.InertiaRotation.Z; + inertiarot.W = m_fakeInertiaOverride.InertiaRotation.W; + d.RfromQ(out inertiarotmat, ref inertiarot); + d.MassRotate(ref objdmass, ref inertiarotmat); + } + + inertia.TotalMass = m_fakeInertiaOverride.TotalMass; + inertia.CenterOfMass = m_fakeInertiaOverride.CenterOfMass; + inertia.Inertia.X = objdmass.I.M00; + inertia.Inertia.Y = objdmass.I.M11; + inertia.Inertia.Z = objdmass.I.M22; + inertia.InertiaRotation.X = objdmass.I.M01; + inertia.InertiaRotation.Y = objdmass.I.M02; + inertia.InertiaRotation.Z = objdmass.I.M12; + return inertia; + } + + inertia.TotalMass = m_mass; + + if(Body == IntPtr.Zero || prim_geom == IntPtr.Zero) + { + inertia.CenterOfMass = Vector3.Zero; + inertia.Inertia = Vector3.Zero; + inertia.InertiaRotation = Vector4.Zero; + return inertia; + } + + d.Vector3 dtmp; + d.Mass m = new d.Mass(); + lock(_parent_scene.OdeLock) + { + d.AllocateODEDataForThread(0); + dtmp = d.GeomGetOffsetPosition(prim_geom); + d.BodyGetMass(Body, out m); + } + + Vector3 cm = new Vector3(-dtmp.X, -dtmp.Y, -dtmp.Z); + inertia.CenterOfMass = cm; + inertia.Inertia = new Vector3(m.I.M00, m.I.M11, m.I.M22); + inertia.InertiaRotation = new Vector4(m.I.M01, m.I.M02 , m.I.M12, 0); + + return inertia; + } + + public override void SetInertiaData(PhysicsInertiaData inertia) + { + if(childPrim) + { + if(_parent != null) + _parent.SetInertiaData(inertia); + return; + } + + if(inertia.TotalMass > 0) + m_fakeInertiaOverride = new PhysicsInertiaData(inertia); + else + m_fakeInertiaOverride = null; + + if (inertia.TotalMass > _parent_scene.maximumMassObject) + inertia.TotalMass = _parent_scene.maximumMassObject; + AddChange(changes.SetInertia,(object)m_fakeInertiaOverride); + } + public override Vector3 CenterOfMass { get @@ -530,7 +631,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde set { // AddChange(changes.Shape, value); - _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_shapetype); + _parent_scene.m_meshWorker.ChangeActorPhysRep(this, value, _size, m_fakeShapetype); } } @@ -538,11 +639,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde { get { - return m_shapetype; + return m_fakeShapetype; } set { - m_shapetype = value; + m_fakeShapetype = value; _parent_scene.m_meshWorker.ChangeActorPhysRep(this, _pbs, _size, value); } } @@ -569,7 +670,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde { if (value.IsFinite()) { - AddChange(changes.Velocity, value); + if(m_outbounds) + _velocity = value; + else + AddChange(changes.Velocity, value); } else { @@ -642,8 +746,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde public override Vector3 Acceleration { - get { return _acceleration; } - set { } + get { return m_acceleration; } + set + { + if(m_outbounds) + m_acceleration = value; + } } public override Vector3 RotationalVelocity @@ -663,7 +771,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde { if (value.IsFinite()) { - AddChange(changes.AngVelocity, value); + if(m_outbounds) + m_rotationalVelocity = value; + else + AddChange(changes.AngVelocity, value); } else { @@ -837,7 +948,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde } public void SetAcceleration(Vector3 accel) { - _acceleration = accel; + m_acceleration = accel; } public override void AddForce(Vector3 force, bool pushforce) @@ -873,31 +984,69 @@ namespace OpenSim.Region.PhysicsModule.ubOde public override void CrossingFailure() { - if (m_outbounds) + lock(_parent_scene.OdeLock) { - _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f); - _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f); - _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f); + if (m_outbounds) + { + _position.X = Util.Clip(_position.X, 0.5f, _parent_scene.WorldExtents.X - 0.5f); + _position.Y = Util.Clip(_position.Y, 0.5f, _parent_scene.WorldExtents.Y - 0.5f); + _position.Z = Util.Clip(_position.Z + 0.2f, -100f, 50000f); + + m_lastposition = _position; + _velocity.X = 0; + _velocity.Y = 0; + _velocity.Z = 0; + + d.AllocateODEDataForThread(0); + + m_lastVelocity = _velocity; + if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) + m_vehicle.Stop(); + + if(Body != IntPtr.Zero) + d.BodySetLinearVel(Body, 0, 0, 0); // stop it + if (prim_geom != IntPtr.Zero) + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + + m_outbounds = false; + changeDisable(false); + base.RequestPhysicsterseUpdate(); + } + } + } + + public override void CrossingStart() + { + lock(_parent_scene.OdeLock) + { + if (m_outbounds || childPrim) + return; + + m_outbounds = true; m_lastposition = _position; - _velocity.X = 0; - _velocity.Y = 0; - _velocity.Z = 0; + m_lastorientation = _orientation; d.AllocateODEDataForThread(0); - - m_lastVelocity = _velocity; - if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) - m_vehicle.Stop(); - if(Body != IntPtr.Zero) - d.BodySetLinearVel(Body, 0, 0, 0); // stop it - if (prim_geom != IntPtr.Zero) - d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + { + d.Vector3 dtmp = d.BodyGetAngularVel(Body); + m_rotationalVelocity.X = dtmp.X; + m_rotationalVelocity.Y = dtmp.Y; + m_rotationalVelocity.Z = dtmp.Z; - m_outbounds = false; - changeDisable(false); - base.RequestPhysicsterseUpdate(); + dtmp = d.BodyGetLinearVel(Body); + _velocity.X = dtmp.X; + _velocity.Y = dtmp.Y; + _velocity.Z = dtmp.Z; + + d.BodySetLinearVel(Body, 0, 0, 0); // stop it + d.BodySetAngularVel(Body, 0, 0, 0); + } + if(prim_geom != IntPtr.Zero) + d.GeomSetPosition(prim_geom, _position.X, _position.Y, _position.Z); + disableBodySoft(); // stop collisions + UnSubscribeEvents(); } } @@ -920,8 +1069,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde } set { + float old = m_density; m_density = value / 100f; - // for not prim mass is not updated since this implies full rebuild of body inertia TODO + // if(m_density != old) + // UpdatePrimBodyData(); } } public override float GravModifier @@ -989,11 +1140,18 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_cureventsubscription = 0; if (CollisionEventsThisFrame == null) CollisionEventsThisFrame = new CollisionEventUpdate(); + if (CollisionVDTCEventsThisFrame == null) + CollisionVDTCEventsThisFrame = new CollisionEventUpdate(); SentEmptyCollisionsEvent = false; } public override void UnSubscribeEvents() { + if (CollisionVDTCEventsThisFrame != null) + { + CollisionVDTCEventsThisFrame.Clear(); + CollisionVDTCEventsThisFrame = null; + } if (CollisionEventsThisFrame != null) { CollisionEventsThisFrame.Clear(); @@ -1012,22 +1170,51 @@ namespace OpenSim.Region.PhysicsModule.ubOde _parent_scene.AddCollisionEventReporting(this); } + public override void AddVDTCCollisionEvent(uint CollidedWith, ContactPoint contact) + { + if (CollisionVDTCEventsThisFrame == null) + CollisionVDTCEventsThisFrame = new CollisionEventUpdate(); + + CollisionVDTCEventsThisFrame.AddCollider(CollidedWith, contact); + _parent_scene.AddCollisionEventReporting(this); + } + internal void SleeperAddCollisionEvents() { - if (CollisionEventsThisFrame == null) - return; - if(CollisionEventsThisFrame.m_objCollisionList.Count == 0) - return; - foreach(KeyValuePair kvp in CollisionEventsThisFrame.m_objCollisionList) + if(CollisionEventsThisFrame != null && CollisionEventsThisFrame.m_objCollisionList.Count != 0) { - OdePrim other = _parent_scene.getPrim(kvp.Key); - if(other == null) - continue; - ContactPoint cp = kvp.Value; - cp.SurfaceNormal = - cp.SurfaceNormal; - cp.RelativeSpeed = -cp.RelativeSpeed; - other.AddCollisionEvent(ParentActor.LocalID,cp); + foreach(KeyValuePair kvp in CollisionEventsThisFrame.m_objCollisionList) + { + if(kvp.Key == 0) + continue; + OdePrim other = _parent_scene.getPrim(kvp.Key); + if(other == null) + continue; + ContactPoint cp = kvp.Value; + cp.SurfaceNormal = - cp.SurfaceNormal; + cp.RelativeSpeed = -cp.RelativeSpeed; + other.AddCollisionEvent(ParentActor.LocalID,cp); + } } + if(CollisionVDTCEventsThisFrame != null && CollisionVDTCEventsThisFrame.m_objCollisionList.Count != 0) + { + foreach(KeyValuePair kvp in CollisionVDTCEventsThisFrame.m_objCollisionList) + { + OdePrim other = _parent_scene.getPrim(kvp.Key); + if(other == null) + continue; + ContactPoint cp = kvp.Value; + cp.SurfaceNormal = - cp.SurfaceNormal; + cp.RelativeSpeed = -cp.RelativeSpeed; + other.AddCollisionEvent(ParentActor.LocalID,cp); + } + } + } + + internal void clearSleeperCollisions() + { + if(CollisionVDTCEventsThisFrame != null && CollisionVDTCEventsThisFrame.Count >0 ) + CollisionVDTCEventsThisFrame.Clear(); } public void SendCollisions(int timestep) @@ -1035,14 +1222,15 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (m_cureventsubscription < 50000) m_cureventsubscription += timestep; + + if (m_cureventsubscription < m_eventsubscription) + return; + if (CollisionEventsThisFrame == null) return; int ncolisions = CollisionEventsThisFrame.m_objCollisionList.Count; - if (m_cureventsubscription < m_eventsubscription) - return; - if (!SentEmptyCollisionsEvent || ncolisions > 0) { base.SendCollisionUpdate(CollisionEventsThisFrame); @@ -1053,7 +1241,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde SentEmptyCollisionsEvent = true; // _parent_scene.RemoveCollisionEventReporting(this); } - else if(Body == IntPtr.Zero || d.BodyIsEnabled(Body)) + else if(Body == IntPtr.Zero || (d.BodyIsEnabled(Body) && m_bodydisablecontrol >= 0 )) { SentEmptyCollisionsEvent = false; CollisionEventsThisFrame.Clear(); @@ -1091,7 +1279,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_invTimeStep = 1f / m_timeStep; m_density = parent_scene.geomDefaultDensity; - body_autodisable_frames = parent_scene.bodyFramesAutoDisable; + m_body_autodisable_frames = parent_scene.bodyFramesAutoDisable; prim_geom = IntPtr.Zero; collide_geom = IntPtr.Zero; @@ -1143,7 +1331,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde _triMeshData = IntPtr.Zero; - m_shapetype = _shapeType; + m_fakeShapetype = _shapeType; m_lastdoneSelected = false; m_isSelected = false; @@ -1160,7 +1348,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde AddChange(changes.Add, null); // get basic mass parameters - ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, m_shapetype); + ODEPhysRepData repData = _parent_scene.m_meshWorker.NewActorPhysRep(this, _pbs, _size, _shapeType); primVolume = repData.volume; m_OBB = repData.OBB; @@ -1545,7 +1733,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde return true; } - private void CreateGeom() + private void CreateGeom(bool OverrideToBox) { bool hasMesh = false; @@ -1554,7 +1742,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if ((m_meshState & MeshState.MeshNoColide) != 0) m_NoColide = true; - else if(m_mesh != null) + else if(!OverrideToBox && m_mesh != null) { if (GetMeshGeom()) hasMesh = true; @@ -1660,8 +1848,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde ApplyCollisionCatFlags(); _zeroFlag = true; + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); - } } resetCollisionAccounting(); @@ -1714,26 +1902,29 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_log.Warn("[PHYSICS]: MakeBody root geom already had a body"); } + bool noInertiaOverride = (m_InertiaOverride == null); + + Body = d.BodyCreate(_parent_scene.world); + d.Matrix3 mymat = new d.Matrix3(); d.Quaternion myrot = new d.Quaternion(); d.Mass objdmass = new d.Mass { }; - Body = d.BodyCreate(_parent_scene.world); - - objdmass = primdMass; - - // rotate inertia myrot.X = _orientation.X; myrot.Y = _orientation.Y; myrot.Z = _orientation.Z; myrot.W = _orientation.W; - d.RfromQ(out mymat, ref myrot); - d.MassRotate(ref objdmass, ref mymat); // set the body rotation d.BodySetRotation(Body, ref mymat); + if(noInertiaOverride) + { + objdmass = primdMass; + d.MassRotate(ref objdmass, ref mymat); + } + // recompute full object inertia if needed if (childrenPrim.Count > 0) { @@ -1756,27 +1947,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde continue; } - tmpdmass = prm.primdMass; - - // apply prim current rotation to inertia quat.X = prm._orientation.X; quat.Y = prm._orientation.Y; quat.Z = prm._orientation.Z; quat.W = prm._orientation.W; d.RfromQ(out mat, ref quat); - d.MassRotate(ref tmpdmass, ref mat); - Vector3 ppos = prm._position; - ppos.X -= rcm.X; - ppos.Y -= rcm.Y; - ppos.Z -= rcm.Z; - // refer inertia to root prim center of mass position - d.MassTranslate(ref tmpdmass, - ppos.X, - ppos.Y, - ppos.Z); - - d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia // fix prim colision cats if (d.GeomGetBody(prm.prim_geom) != IntPtr.Zero) @@ -1789,6 +1965,24 @@ namespace OpenSim.Region.PhysicsModule.ubOde d.GeomSetBody(prm.prim_geom, Body); prm.Body = Body; d.GeomSetOffsetWorldRotation(prm.prim_geom, ref mat); // set relative rotation + + if(noInertiaOverride) + { + tmpdmass = prm.primdMass; + + d.MassRotate(ref tmpdmass, ref mat); + Vector3 ppos = prm._position; + ppos.X -= rcm.X; + ppos.Y -= rcm.Y; + ppos.Z -= rcm.Z; + // refer inertia to root prim center of mass position + d.MassTranslate(ref tmpdmass, + ppos.X, + ppos.Y, + ppos.Z); + + d.MassAdd(ref objdmass, ref tmpdmass); // add to total object inertia + } } } } @@ -1797,25 +1991,66 @@ namespace OpenSim.Region.PhysicsModule.ubOde // associate root geom with body d.GeomSetBody(prim_geom, Body); - d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z); + if(noInertiaOverride) + d.BodySetPosition(Body, _position.X + objdmass.c.X, _position.Y + objdmass.c.Y, _position.Z + objdmass.c.Z); + else + { + Vector3 ncm = m_InertiaOverride.CenterOfMass * _orientation; + d.BodySetPosition(Body, + _position.X + ncm.X, + _position.Y + ncm.Y, + _position.Z + ncm.Z); + } + d.GeomSetOffsetWorldPosition(prim_geom, _position.X, _position.Y, _position.Z); - d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body - myrot.X = -myrot.X; - myrot.Y = -myrot.Y; - myrot.Z = -myrot.Z; + if(noInertiaOverride) + { + d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body + myrot.X = -myrot.X; + myrot.Y = -myrot.Y; + myrot.Z = -myrot.Z; - d.RfromQ(out mymat, ref myrot); - d.MassRotate(ref objdmass, ref mymat); + d.RfromQ(out mymat, ref myrot); + d.MassRotate(ref objdmass, ref mymat); - d.BodySetMass(Body, ref objdmass); - _mass = objdmass.mass; + d.BodySetMass(Body, ref objdmass); + m_mass = objdmass.mass; + } + else + { + objdmass.c.X = 0; + objdmass.c.Y = 0; + objdmass.c.Z = 0; + + objdmass.I.M00 = m_InertiaOverride.Inertia.X; + objdmass.I.M11 = m_InertiaOverride.Inertia.Y; + objdmass.I.M22 = m_InertiaOverride.Inertia.Z; + + objdmass.mass = m_InertiaOverride.TotalMass; + + if(Math.Abs(m_InertiaOverride.InertiaRotation.W) < 0.999) + { + d.Matrix3 inertiarotmat = new d.Matrix3(); + d.Quaternion inertiarot = new d.Quaternion(); + + inertiarot.X = m_InertiaOverride.InertiaRotation.X; + inertiarot.Y = m_InertiaOverride.InertiaRotation.Y; + inertiarot.Z = m_InertiaOverride.InertiaRotation.Z; + inertiarot.W = m_InertiaOverride.InertiaRotation.W; + d.RfromQ(out inertiarotmat, ref inertiarot); + d.MassRotate(ref objdmass, ref inertiarotmat); + } + d.BodySetMass(Body, ref objdmass); + + m_mass = objdmass.mass; + } // disconnect from world gravity so we can apply buoyancy d.BodySetGravityMode(Body, false); d.BodySetAutoDisableFlag(Body, true); - d.BodySetAutoDisableSteps(Body, body_autodisable_frames); + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodySetAutoDisableAngularThreshold(Body, 0.05f); d.BodySetAutoDisableLinearThreshold(Body, 0.05f); d.BodySetDamping(Body, .004f, .001f); @@ -1909,8 +2144,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde { d.BodySetAngularVel(Body, m_rotationalVelocity.X, m_rotationalVelocity.Y, m_rotationalVelocity.Z); d.BodySetLinearVel(Body, _velocity.X, _velocity.Y, _velocity.Z); + _zeroFlag = false; - bodydisablecontrol = 0; + m_bodydisablecontrol = 0; } _parent_scene.addActiveGroups(this); } @@ -1988,7 +2224,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde SetInStaticSpace(prm); } prm.Body = IntPtr.Zero; - prm._mass = prm.primMass; + prm.m_mass = prm.primMass; prm.m_collisionscore = 0; } } @@ -2002,7 +2238,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde } Body = IntPtr.Zero; } - _mass = primMass; + m_mass = primMass; m_collisionscore = 0; } @@ -2079,7 +2315,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body d.BodySetMass(Body, ref objdmass); - _mass = objdmass.mass; + m_mass = objdmass.mass; } private void FixInertia(Vector3 NewPos) @@ -2143,7 +2379,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body d.BodySetMass(Body, ref objdmass); - _mass = objdmass.mass; + m_mass = objdmass.mass; } private void FixInertia(Quaternion newrot) @@ -2209,7 +2445,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde d.BodySetPosition(Body, dobjpos.X + thispos.X, dobjpos.Y + thispos.Y, dobjpos.Z + thispos.Z); d.MassTranslate(ref objdmass, -objdmass.c.X, -objdmass.c.Y, -objdmass.c.Z); // ode wants inertia at center of body d.BodySetMass(Body, ref objdmass); - _mass = objdmass.mass; + m_mass = objdmass.mass; } @@ -2224,7 +2460,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (primMass > _parent_scene.maximumMassObject) primMass = _parent_scene.maximumMassObject; - _mass = primMass; // just in case + m_mass = primMass; // just in case d.MassSetBoxTotal(out primdMass, primMass, 2.0f * m_OBB.X, 2.0f * m_OBB.Y, 2.0f * m_OBB.Z); @@ -2514,7 +2750,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_angularForceacc = Vector3.Zero; // m_torque = Vector3.Zero; _velocity = Vector3.Zero; - _acceleration = Vector3.Zero; + m_acceleration = Vector3.Zero; m_rotationalVelocity = Vector3.Zero; _target_velocity = Vector3.Zero; if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) @@ -2665,6 +2901,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (Body != IntPtr.Zero && !m_disabled) { _zeroFlag = true; + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); } } @@ -2698,6 +2935,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (!d.BodyIsEnabled(Body)) { _zeroFlag = true; + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); } } @@ -2712,6 +2950,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) { _zeroFlag = true; + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); } } @@ -2767,12 +3006,17 @@ namespace OpenSim.Region.PhysicsModule.ubOde myrot.W = newOri.W; d.GeomSetQuaternion(prim_geom, ref myrot); _orientation = newOri; - if (Body != IntPtr.Zero && m_angularlocks != 0) - createAMotor(m_angularlocks); + + if (Body != IntPtr.Zero) + { + if(m_angularlocks != 0) + createAMotor(m_angularlocks); + } } if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) { _zeroFlag = true; + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); } } @@ -2831,6 +3075,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) { _zeroFlag = true; + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); } } @@ -2923,7 +3168,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde { _size = repData.size; //?? _pbs = repData.pbs; - m_shapetype = repData.shapetype; m_mesh = repData.mesh; @@ -2936,7 +3180,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde primVolume = repData.volume; - CreateGeom(); + CreateGeom(repData.isTooSmall); if (prim_geom != IntPtr.Zero) { @@ -2962,9 +3206,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde { repData.size = _size; repData.pbs = _pbs; - repData.shapetype = m_shapetype; + repData.shapetype = m_fakeShapetype; _parent_scene.m_meshWorker.RequestMesh(repData); } + else + m_shapetype = repData.shapetype; } private void changePhysRepData(ODEPhysRepData repData) @@ -2998,7 +3244,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde _size = repData.size; _pbs = repData.pbs; - m_shapetype = repData.shapetype; m_mesh = repData.mesh; @@ -3011,7 +3256,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde primVolume = repData.volume; - CreateGeom(); + CreateGeom(repData.isTooSmall); if (prim_geom != IntPtr.Zero) { @@ -3049,9 +3294,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde { repData.size = _size; repData.pbs = _pbs; - repData.shapetype = m_shapetype; + repData.shapetype = m_fakeShapetype; _parent_scene.m_meshWorker.RequestMesh(repData); } + else + m_shapetype = repData.shapetype; } private void changeFloatOnWater(bool newval) @@ -3064,15 +3311,17 @@ namespace OpenSim.Region.PhysicsModule.ubOde private void changeSetTorque(Vector3 newtorque) { - if (!m_isSelected) + if (!m_isSelected && !m_outbounds) { if (m_isphysical && Body != IntPtr.Zero) { if (m_disabled) enableBodySoft(); else if (!d.BodyIsEnabled(Body)) + { + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); - + } } m_torque = newtorque; } @@ -3081,14 +3330,17 @@ namespace OpenSim.Region.PhysicsModule.ubOde private void changeForce(Vector3 force) { m_force = force; - if (Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) + if (!m_isSelected && !m_outbounds && Body != IntPtr.Zero && !d.BodyIsEnabled(Body)) + { + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); + } } private void changeAddForce(Vector3 theforce) { m_forceacc += theforce; - if (!m_isSelected) + if (!m_isSelected && !m_outbounds) { lock (this) { @@ -3098,7 +3350,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (m_disabled) enableBodySoft(); else if (!d.BodyIsEnabled(Body)) + { + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); + } } } m_collisionscore = 0; @@ -3109,7 +3364,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde private void changeAddAngularImpulse(Vector3 aimpulse) { m_angularForceacc += aimpulse * m_invTimeStep; - if (!m_isSelected) + if (!m_isSelected && !m_outbounds) { lock (this) { @@ -3118,7 +3373,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (m_disabled) enableBodySoft(); else if (!d.BodyIsEnabled(Body)) + { + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); + } } } m_collisionscore = 0; @@ -3134,15 +3392,17 @@ namespace OpenSim.Region.PhysicsModule.ubOde newVel *= len; } - if (!m_isSelected) + if (!m_isSelected && !m_outbounds) { if (Body != IntPtr.Zero) { if (m_disabled) enableBodySoft(); else if (!d.BodyIsEnabled(Body)) + { + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); - + } d.BodySetLinearVel(Body, newVel.X, newVel.Y, newVel.Z); } //resetCollisionAccounting(); @@ -3159,16 +3419,17 @@ namespace OpenSim.Region.PhysicsModule.ubOde newAngVel *= len; } - if (!m_isSelected) + if (!m_isSelected && !m_outbounds) { if (Body != IntPtr.Zero) { if (m_disabled) enableBodySoft(); else if (!d.BodyIsEnabled(Body)) + { + d.BodySetAutoDisableSteps(Body, m_body_autodisable_frames); d.BodyEnable(Body); - - + } d.BodySetAngularVel(Body, newAngVel.X, newAngVel.Y, newAngVel.Z); } //resetCollisionAccounting(); @@ -3304,6 +3565,15 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_useHoverPID = active; } + private void changeInertia(PhysicsInertiaData inertia) + { + m_InertiaOverride = inertia; + + if (Body != IntPtr.Zero) + DestroyBody(); + MakeBody(); + } + #endregion public void Move() @@ -3317,19 +3587,20 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (m_vehicle != null && m_vehicle.Type != Vehicle.TYPE_NONE) return; - if (++bodydisablecontrol < 50) + if (++m_bodydisablecontrol < 50) return; // clear residuals d.BodySetAngularVel(Body,0f,0f,0f); d.BodySetLinearVel(Body,0f,0f,0f); _zeroFlag = true; + d.BodySetAutoDisableSteps(Body, 1); d.BodyEnable(Body); - bodydisablecontrol = -4; + m_bodydisablecontrol = -3; } - if(bodydisablecontrol < 0) - bodydisablecontrol ++; + if(m_bodydisablecontrol < 0) + m_bodydisablecontrol++; d.Vector3 lpos = d.GeomGetPosition(prim_geom); // root position that is seem by rest of simulator @@ -3344,7 +3615,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde float fy = 0; float fz = 0; - float m_mass = _mass; + float mass = m_mass; if (m_usePID && m_PIDTau > 0) { @@ -3451,9 +3722,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde fz = _parent_scene.gravityz * b; } - fx *= m_mass; - fy *= m_mass; - fz *= m_mass; + fx *= mass; + fy *= mass; + fz *= mass; // constant force fx += m_force.X; @@ -3494,13 +3765,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde public void UpdatePositionAndVelocity(int frame) { - if (_parent == null && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero) + if (_parent == null && !m_isSelected && !m_disabled && !m_building && !m_outbounds && Body != IntPtr.Zero) { - bool bodyenabled = d.BodyIsEnabled(Body); - - if(bodydisablecontrol < 0) + if(m_bodydisablecontrol < 0) return; + bool bodyenabled = d.BodyIsEnabled(Body); if (bodyenabled || !_zeroFlag) { bool lastZeroFlag = _zeroFlag; @@ -3513,9 +3783,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_outbounds = true; lpos.Z = Util.Clip(lpos.Z, -100f, 100000f); - _acceleration.X = 0; - _acceleration.Y = 0; - _acceleration.Z = 0; + m_acceleration.X = 0; + m_acceleration.Y = 0; + m_acceleration.Z = 0; _velocity.X = 0; _velocity.Y = 0; @@ -3638,19 +3908,19 @@ namespace OpenSim.Region.PhysicsModule.ubOde _orientation.W = ori.W; } - // update velocities and aceleration + // update velocities and acceleration if (_zeroFlag || lastZeroFlag) { // disable interpolators _velocity = Vector3.Zero; - _acceleration = Vector3.Zero; - m_rotationalVelocity = Vector3.Zero; + m_acceleration = Vector3.Zero; + m_rotationalVelocity = Vector3.Zero; } else { d.Vector3 vel = d.BodyGetLinearVel(Body); - _acceleration = _velocity; + m_acceleration = _velocity; if ((Math.Abs(vel.X) < 0.005f) && (Math.Abs(vel.Y) < 0.005f) && @@ -3658,28 +3928,28 @@ namespace OpenSim.Region.PhysicsModule.ubOde { _velocity = Vector3.Zero; float t = -m_invTimeStep; - _acceleration = _acceleration * t; + m_acceleration = m_acceleration * t; } else { _velocity.X = vel.X; _velocity.Y = vel.Y; _velocity.Z = vel.Z; - _acceleration = (_velocity - _acceleration) * m_invTimeStep; + m_acceleration = (_velocity - m_acceleration) * m_invTimeStep; } - if ((Math.Abs(_acceleration.X) < 0.01f) && - (Math.Abs(_acceleration.Y) < 0.01f) && - (Math.Abs(_acceleration.Z) < 0.01f)) + if ((Math.Abs(m_acceleration.X) < 0.01f) && + (Math.Abs(m_acceleration.Y) < 0.01f) && + (Math.Abs(m_acceleration.Z) < 0.01f)) { - _acceleration = Vector3.Zero; + m_acceleration = Vector3.Zero; } vel = d.BodyGetAngularVel(Body); if ((Math.Abs(vel.X) < 0.0001) && - (Math.Abs(vel.Y) < 0.0001) && - (Math.Abs(vel.Z) < 0.0001) - ) + (Math.Abs(vel.Y) < 0.0001) && + (Math.Abs(vel.Z) < 0.0001) + ) { m_rotationalVelocity = Vector3.Zero; } @@ -3939,6 +4209,10 @@ namespace OpenSim.Region.PhysicsModule.ubOde changePIDHoverActive((bool)arg); break; + case changes.SetInertia: + changeInertia((PhysicsInertiaData) arg); + break; + case changes.Null: donullchange(); break; @@ -3955,7 +4229,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde _parent_scene.AddChange((PhysicsActor) this, what, arg); } - private struct strVehicleBoolParam { public int param; diff --git a/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs index bed66ccad3..004ee7f31d 100644 --- a/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs +++ b/OpenSim/Region/PhysicsModules/ubOde/ODEScene.cs @@ -155,6 +155,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde VehicleRotationParam, VehicleFlags, SetVehicle, + SetInertia, Null //keep this last used do dim the methods array. does nothing but pulsing the prim } @@ -185,7 +186,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde float frictionMovementMult = 0.8f; - float TerrainBounce = 0.1f; + float TerrainBounce = 0.001f; float TerrainFriction = 0.3f; public float AvatarFriction = 0;// 0.9f * 0.5f; @@ -202,8 +203,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde private float metersInSpace = 25.6f; private float m_timeDilation = 1.0f; - private DateTime m_lastframe; - private DateTime m_lastMeshExpire; + private double m_lastframe; + private double m_lastMeshExpire; public float gravityx = 0f; public float gravityy = 0f; @@ -480,7 +481,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde contactsPerCollision = physicsconfig.GetInt("contacts_per_collision", contactsPerCollision); geomDefaultDensity = physicsconfig.GetFloat("geometry_default_density", geomDefaultDensity); - bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable); +// bodyFramesAutoDisable = physicsconfig.GetInt("body_frames_auto_disable", bodyFramesAutoDisable); physics_logging = physicsconfig.GetBoolean("physics_logging", false); physics_logging_interval = physicsconfig.GetInt("physics_logging_interval", 0); @@ -502,7 +503,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde d.WorldSetGravity(world, gravityx, gravityy, gravityz); - d.WorldSetLinearDamping(world, 0.002f); + d.WorldSetLinearDamping(world, 0.001f); d.WorldSetAngularDamping(world, 0.002f); d.WorldSetAngularDampingThreshold(world, 0f); d.WorldSetLinearDampingThreshold(world, 0f); @@ -528,6 +529,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde SharedTmpcontact.surface.mode = comumContactFlags; SharedTmpcontact.surface.mu = 0; SharedTmpcontact.surface.bounce = 0; + SharedTmpcontact.surface.bounce_vel = 1.5f; SharedTmpcontact.surface.soft_cfm = comumContactCFM; SharedTmpcontact.surface.soft_erp = comumContactERP; SharedTmpcontact.surface.slip1 = comumContactSLIP; @@ -627,8 +629,9 @@ namespace OpenSim.Region.PhysicsModule.ubOde staticPrimspaceOffRegion[i] = newspace; } - m_lastframe = DateTime.UtcNow; + m_lastframe = Util.GetTimeStamp(); m_lastMeshExpire = m_lastframe; + step_time = -1; } internal void waitForSpaceUnlock(IntPtr space) @@ -726,8 +729,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (g1 == g2) return; // Can't collide with yourself - if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) - return; +// if (b1 != IntPtr.Zero && b2 != IntPtr.Zero && d.AreConnectedExcluding(b1, b2, d.JointType.Contact)) +// return; /* // debug PhysicsActor dp2; @@ -950,8 +953,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde SharedTmpcontact.surface.bounce = bounce; d.ContactGeom altContact = new d.ContactGeom(); - bool useAltcontact = false; - bool noskip = true; + bool useAltcontact; + bool noskip; if(dop1ava || dop2ava) smoothMesh = false; @@ -998,7 +1001,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde Joint = CreateContacJoint(ref altContact,smoothMesh); else Joint = CreateContacJoint(ref curContact,smoothMesh); - if (Joint == IntPtr.Zero) break; @@ -1082,9 +1084,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde case ActorTypes.Prim: if (p2events) { - AddCollisionEventReporting(p2); + //AddCollisionEventReporting(p2); p2.AddCollisionEvent(p1.ParentActor.LocalID, contact); } + else if(p1.IsVolumeDtc) + p2.AddVDTCCollisionEvent(p1.ParentActor.LocalID, contact); + obj2LocalID = p2.ParentActor.LocalID; break; @@ -1098,9 +1103,16 @@ namespace OpenSim.Region.PhysicsModule.ubOde { contact.SurfaceNormal = -contact.SurfaceNormal; contact.RelativeSpeed = -contact.RelativeSpeed; - AddCollisionEventReporting(p1); + //AddCollisionEventReporting(p1); p1.AddCollisionEvent(obj2LocalID, contact); } + else if(p2.IsVolumeDtc) + { + contact.SurfaceNormal = -contact.SurfaceNormal; + contact.RelativeSpeed = -contact.RelativeSpeed; + //AddCollisionEventReporting(p1); + p1.AddVDTCCollisionEvent(obj2LocalID, contact); + } break; } case ActorTypes.Ground: @@ -1109,7 +1121,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde { if (p2events && !p2.IsVolumeDtc) { - AddCollisionEventReporting(p2); + //AddCollisionEventReporting(p2); p2.AddCollisionEvent(0, contact); } break; @@ -1161,8 +1173,11 @@ namespace OpenSim.Region.PhysicsModule.ubOde { aprim.CollisionScore = 0; aprim.IsColliding = false; + if(!aprim.m_outbounds && d.BodyIsEnabled(aprim.Body)) + aprim.clearSleeperCollisions(); } } + lock (_activegroups) { try @@ -1611,6 +1626,8 @@ namespace OpenSim.Region.PhysicsModule.ubOde } m_log.InfoFormat("[ubOde] {0} prim actors loaded",_prims.Count); } + m_lastframe = Util.GetTimeStamp() + 0.5; + step_time = -0.5f; } /// @@ -1624,13 +1641,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde /// public override float Simulate(float reqTimeStep) { - DateTime now = DateTime.UtcNow; - TimeSpan timedif = now - m_lastframe; - float timeStep = (float)timedif.TotalSeconds; + double now = Util.GetTimeStamp(); + double timeStep = now - m_lastframe; m_lastframe = now; // acumulate time so we can reduce error - step_time += timeStep; + step_time += (float)timeStep; if (step_time < HalfOdeStep) return 0; @@ -1657,11 +1673,15 @@ namespace OpenSim.Region.PhysicsModule.ubOde // d.WorldSetQuickStepNumIterations(world, curphysiteractions); - int loopstartMS = Util.EnvironmentTickCount(); - int looptimeMS = 0; - int changestimeMS = 0; - int maxChangestime = (int)(reqTimeStep * 500f); // half the time - int maxLoopTime = (int)(reqTimeStep * 1200f); // 1.2 the time + double loopstartMS = Util.GetTimeStampMS(); + double looptimeMS = 0; + double changestimeMS = 0; + double maxChangestime = (int)(reqTimeStep * 500f); // half the time + double maxLoopTime = (int)(reqTimeStep * 1200f); // 1.2 the time + +// double collisionTime = 0; +// double qstepTIme = 0; +// double tmpTime = 0; d.AllocateODEDataForThread(~0U); @@ -1684,7 +1704,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde item.actor.Name, item.what.ToString()); } } - changestimeMS = Util.EnvironmentTickCountSubtract(loopstartMS); + changestimeMS = Util.GetTimeStampMS() - loopstartMS; if (changestimeMS > maxChangestime) break; } @@ -1729,9 +1749,19 @@ namespace OpenSim.Region.PhysicsModule.ubOde m_rayCastManager.ProcessQueuedRequests(); +// tmpTime = Util.GetTimeStampMS(); collision_optimized(); - List sleepers = new List(); +// collisionTime += Util.GetTimeStampMS() - tmpTime; + lock(_collisionEventPrimRemove) + { + foreach (PhysicsActor obj in _collisionEventPrimRemove) + _collisionEventPrim.Remove(obj); + + _collisionEventPrimRemove.Clear(); + } + + List sleepers = new List(); foreach (PhysicsActor obj in _collisionEventPrim) { if (obj == null) @@ -1761,18 +1791,12 @@ namespace OpenSim.Region.PhysicsModule.ubOde foreach(OdePrim prm in sleepers) prm.SleeperAddCollisionEvents(); sleepers.Clear(); - - lock(_collisionEventPrimRemove) - { - foreach (PhysicsActor obj in _collisionEventPrimRemove) - _collisionEventPrim.Remove(obj); - - _collisionEventPrimRemove.Clear(); - } - + // do a ode simulation step +// tmpTime = Util.GetTimeStampMS(); d.WorldQuickStep(world, ODE_STEPSIZE); d.JointGroupEmpty(contactgroup); +// qstepTIme += Util.GetTimeStampMS() - tmpTime; // update managed ideia of physical data and do updates to core /* @@ -1813,7 +1837,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde step_time -= ODE_STEPSIZE; nodeframes++; - looptimeMS = Util.EnvironmentTickCountSubtract(loopstartMS); + looptimeMS = Util.GetTimeStampMS() - loopstartMS; if (looptimeMS > maxLoopTime) break; } @@ -1831,14 +1855,6 @@ namespace OpenSim.Region.PhysicsModule.ubOde } } - timedif = now - m_lastMeshExpire; - - if (timedif.Seconds > 10) - { - mesher.ExpireReleaseMeshs(); - m_lastMeshExpire = now; - } - // information block for in debug breakpoint only /* int ntopactivegeoms = d.SpaceGetNumGeoms(ActiveSpace); @@ -1881,6 +1897,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde int totgeoms = nstaticgeoms + nactivegeoms + ngroundgeoms + 1; // one ray int nbodies = d.NTotalBodies; int ngeoms = d.NTotalGeoms; +*/ +/* + looptimeMS /= nodeframes; + if(looptimeMS > 0.080) + { + collisionTime /= nodeframes; + qstepTIme /= nodeframes; + } */ // Finished with all sim stepping. If requested, dump world state to file for debugging. // TODO: This call to the export function is already inside lock (OdeLock) - but is an extra lock needed? @@ -1910,7 +1934,7 @@ namespace OpenSim.Region.PhysicsModule.ubOde // if we lag too much skip frames m_timeDilation = 0.0f; step_time = 0; - m_lastframe = DateTime.UtcNow; // skip also the time lost + m_lastframe = Util.GetTimeStamp(); // skip also the time lost } else { @@ -1918,6 +1942,14 @@ namespace OpenSim.Region.PhysicsModule.ubOde if (m_timeDilation > 1) m_timeDilation = 1; } + + if (m_timeDilation == 1 && now - m_lastMeshExpire > 30) + { + mesher.ExpireReleaseMeshs(); + m_lastMeshExpire = now; + } + + } return fps; diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs index 163f43928a..a2a3f79276 100644 --- a/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs +++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/Meshmerizer.cs @@ -36,15 +36,13 @@ using OpenSim.Region.PhysicsModules.ConvexDecompositionDotNet; using OpenMetaverse; using OpenMetaverse.StructuredData; using System.Drawing; -using System.Drawing.Imaging; +using System.Threading; using System.IO.Compression; using PrimMesher; using log4net; using Nini.Config; using System.Reflection; using System.IO; -using System.Runtime.Serialization; -using System.Runtime.Serialization.Formatters.Binary; using Mono.Addins; @@ -58,22 +56,22 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing // Setting baseDir to a path will enable the dumping of raw files // raw files can be imported by blender so a visual inspection of the results can be done + private static string cacheControlFilename = "cntr"; private bool m_Enabled = false; public static object diskLock = new object(); public bool doMeshFileCache = true; - + public bool doCacheExpire = true; public string cachePath = "MeshCache"; public TimeSpan CacheExpire; - public bool doCacheExpire = true; // const string baseDir = "rawFiles"; private const string baseDir = null; //"rawFiles"; - private bool useMeshiesPhysicsMesh = false; - - private float minSizeForComplexMesh = 0.2f; // prims with all dimensions smaller than this will have a bounding box mesh + private bool useMeshiesPhysicsMesh = true; + private bool doConvexPrims = true; + private bool doConvexSculpts = true; private Dictionary m_uniqueMeshes = new Dictionary(); private Dictionary m_uniqueReleasedMeshes = new Dictionary(); @@ -103,40 +101,31 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing if (mesh_config != null) { useMeshiesPhysicsMesh = mesh_config.GetBoolean("UseMeshiesPhysicsMesh", useMeshiesPhysicsMesh); - if (useMeshiesPhysicsMesh) - { - doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache); - cachePath = mesh_config.GetString("MeshFileCachePath", cachePath); - fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache); - doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire); - } - else - { - doMeshFileCache = false; - doCacheExpire = false; - } + doConvexPrims = mesh_config.GetBoolean("ConvexPrims",doConvexPrims); + doConvexSculpts = mesh_config.GetBoolean("ConvexSculpts",doConvexPrims); + doMeshFileCache = mesh_config.GetBoolean("MeshFileCache", doMeshFileCache); + cachePath = mesh_config.GetString("MeshFileCachePath", cachePath); + fcache = mesh_config.GetFloat("MeshFileCacheExpireHours", fcache); + doCacheExpire = mesh_config.GetBoolean("MeshFileCacheDoExpire", doCacheExpire); m_Enabled = true; } CacheExpire = TimeSpan.FromHours(fcache); - lock (diskLock) + if(String.IsNullOrEmpty(cachePath)) + doMeshFileCache = false; + + if(doMeshFileCache) { - if(doMeshFileCache && cachePath != "") + if(!checkCache()) { - try - { - if (!Directory.Exists(cachePath)) - Directory.CreateDirectory(cachePath); - } - catch - { - doMeshFileCache = false; - doCacheExpire = false; - } + doMeshFileCache = false; + doCacheExpire = false; } } + else + doCacheExpire = false; } } @@ -168,87 +157,6 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing #endregion - /// - /// creates a simple box mesh of the specified size. This mesh is of very low vertex count and may - /// be useful as a backup proxy when level of detail is not needed or when more complex meshes fail - /// for some reason - /// - /// - /// - /// - /// - /// - /// - /// - private static Mesh CreateSimpleBoxMesh(float minX, float maxX, float minY, float maxY, float minZ, float maxZ) - { - Mesh box = new Mesh(true); - List vertices = new List(); - // bottom - - vertices.Add(new Vertex(minX, maxY, minZ)); - vertices.Add(new Vertex(maxX, maxY, minZ)); - vertices.Add(new Vertex(maxX, minY, minZ)); - vertices.Add(new Vertex(minX, minY, minZ)); - - box.Add(new Triangle(vertices[0], vertices[1], vertices[2])); - box.Add(new Triangle(vertices[0], vertices[2], vertices[3])); - - // top - - vertices.Add(new Vertex(maxX, maxY, maxZ)); - vertices.Add(new Vertex(minX, maxY, maxZ)); - vertices.Add(new Vertex(minX, minY, maxZ)); - vertices.Add(new Vertex(maxX, minY, maxZ)); - - box.Add(new Triangle(vertices[4], vertices[5], vertices[6])); - box.Add(new Triangle(vertices[4], vertices[6], vertices[7])); - - // sides - - box.Add(new Triangle(vertices[5], vertices[0], vertices[3])); - box.Add(new Triangle(vertices[5], vertices[3], vertices[6])); - - box.Add(new Triangle(vertices[1], vertices[0], vertices[5])); - box.Add(new Triangle(vertices[1], vertices[5], vertices[4])); - - box.Add(new Triangle(vertices[7], vertices[1], vertices[4])); - box.Add(new Triangle(vertices[7], vertices[2], vertices[1])); - - box.Add(new Triangle(vertices[3], vertices[2], vertices[7])); - box.Add(new Triangle(vertices[3], vertices[7], vertices[6])); - - return box; - } - - /// - /// Creates a simple bounding box mesh for a complex input mesh - /// - /// - /// - private static Mesh CreateBoundingBoxMesh(Mesh meshIn) - { - float minX = float.MaxValue; - float maxX = float.MinValue; - float minY = float.MaxValue; - float maxY = float.MinValue; - float minZ = float.MaxValue; - float maxZ = float.MinValue; - - foreach (Vector3 v in meshIn.getVertexList()) - { - if (v.X < minX) minX = v.X; - if (v.Y < minY) minY = v.Y; - if (v.Z < minZ) minZ = v.Z; - - if (v.X > maxX) maxX = v.X; - if (v.Y > maxY) maxY = v.Y; - if (v.Z > maxZ) maxZ = v.Z; - } - - return CreateSimpleBoxMesh(minX, maxX, minY, maxY, minZ, maxZ); - } - private void ReportPrimError(string message, string primName, PrimMesh primMesh) { m_log.Error(message); @@ -265,7 +173,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing /// private void AddSubMesh(OSDMap subMeshData, List coords, List faces) { - // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); + // Console.WriteLine("subMeshMap for {0} - {1}", primName, Util.GetFormattedXml((OSD)subMeshMap)); // As per http://wiki.secondlife.com/wiki/Mesh/Mesh_Asset_Format, some Mesh Level // of Detail Blocks (maps) contain just a NoGeometry key to signal there is no @@ -330,6 +238,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing List coords; List faces; + bool needsConvexProcessing = convex; if (primShape.SculptEntry) { @@ -340,23 +249,49 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing if (!GenerateCoordsAndFacesFromPrimMeshData(primName, primShape, out coords, out faces, convex)) return null; + needsConvexProcessing = false; } else { if (!GenerateCoordsAndFacesFromPrimSculptData(primName, primShape, lod, out coords, out faces)) return null; + needsConvexProcessing &= doConvexSculpts; } } else { if (!GenerateCoordsAndFacesFromPrimShapeData(primName, primShape, lod, convex, out coords, out faces)) return null; + needsConvexProcessing &= doConvexPrims; } - int numCoords = coords.Count; int numFaces = faces.Count; + if(numCoords < 3 || (!needsConvexProcessing && numFaces < 1)) + { + m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim {0} ignored", primName); + return null; + } + + if(needsConvexProcessing) + { + List convexcoords; + List convexfaces; + if(CreateBoundingHull(coords, out convexcoords, out convexfaces) && convexcoords != null && convexfaces != null) + { + coords.Clear(); + coords = convexcoords; + numCoords = coords.Count; + + faces.Clear(); + faces = convexfaces; + numFaces = faces.Count; + } + else + m_log.ErrorFormat("[ubMESH]: failed to create convex for {0} using normal mesh", primName); + } + Mesh mesh = new Mesh(true); // Add the corresponding triangles to the mesh for (int i = 0; i < numFaces; i++) @@ -371,10 +306,10 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing faces.Clear(); if(mesh.numberVertices() < 3 || mesh.numberTriangles() < 1) - { - m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim " + primName + " ignored"); + { + m_log.ErrorFormat("[MESH]: invalid degenerated mesh for prim {0} ignored", primName); return null; - } + } primShape.SculptData = Utils.EmptyBytes; @@ -454,7 +389,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing if (physicsParms == null) { - m_log.WarnFormat("[MESH]: unknown mesh type for prim {0}",primName); + //m_log.WarnFormat("[MESH]: unknown mesh type for prim {0}",primName); return false; } @@ -625,45 +560,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing vs.Clear(); continue; } - /* - if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f)) - { - vs.Clear(); - continue; - } - nverts = hullr.Vertices.Count; - nindexs = hullr.Indices.Count; - - if (nindexs % 3 != 0) - { - vs.Clear(); - continue; - } - - for (i = 0; i < nverts; i++) - { - c.X = hullr.Vertices[i].x; - c.Y = hullr.Vertices[i].y; - c.Z = hullr.Vertices[i].z; - coords.Add(c); - } - - for (i = 0; i < nindexs; i += 3) - { - t1 = hullr.Indices[i]; - if (t1 > nverts) - break; - t2 = hullr.Indices[i + 1]; - if (t2 > nverts) - break; - t3 = hullr.Indices[i + 2]; - if (t3 > nverts) - break; - f = new Face(vertsoffset + t1, vertsoffset + t2, vertsoffset + t3); - faces.Add(f); - } - */ List indices; if (!HullUtils.ComputeHull(vs, out indices)) { @@ -712,7 +609,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing else { // if neither mesh or decomposition present, warn and use convex - m_log.WarnFormat("[MESH]: Data for PRIM shape type ( mesh or decomposition) not found for prim {0}",primName); + //m_log.WarnFormat("[MESH]: Data for PRIM shape type ( mesh or decomposition) not found for prim {0}",primName); } } vs.Clear(); @@ -769,38 +666,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing vs.Clear(); return true; } -/* - if (!HullUtils.ComputeHull(vs, ref hullr, 0, 0.0f)) - return false; - nverts = hullr.Vertices.Count; - nindexs = hullr.Indices.Count; - - if (nindexs % 3 != 0) - return false; - - for (i = 0; i < nverts; i++) - { - c.X = hullr.Vertices[i].x; - c.Y = hullr.Vertices[i].y; - c.Z = hullr.Vertices[i].z; - coords.Add(c); - } - for (i = 0; i < nindexs; i += 3) - { - t1 = hullr.Indices[i]; - if (t1 > nverts) - break; - t2 = hullr.Indices[i + 1]; - if (t2 > nverts) - break; - t3 = hullr.Indices[i + 2]; - if (t3 > nverts) - break; - f = new Face(t1, t2, t3); - faces.Add(f); - } -*/ List indices; if (!HullUtils.ComputeHull(vs, out indices)) return false; @@ -1413,7 +1279,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing } } - public void FileNames(AMeshKey key, out string dir,out string fullFileName) + public void FileNames(AMeshKey key, out string dir, out string fullFileName) { string id = key.ToString(); string init = id.Substring(0, 1); @@ -1530,7 +1396,7 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing if (!doCacheExpire) return; - string controlfile = System.IO.Path.Combine(cachePath, "cntr"); + string controlfile = System.IO.Path.Combine(cachePath, cacheControlFilename); lock (diskLock) { @@ -1583,5 +1449,153 @@ namespace OpenSim.Region.PhysicsModule.ubODEMeshing catch { } } } + + public bool checkCache() + { + string controlfile = System.IO.Path.Combine(cachePath, cacheControlFilename); + lock (diskLock) + { + try + { + if (!Directory.Exists(cachePath)) + { + Directory.CreateDirectory(cachePath); + Thread.Sleep(100); + FileStream fs = File.Create(controlfile, 4096, FileOptions.WriteThrough); + fs.Close(); + return true; + } + } + catch + { + doMeshFileCache = false; + doCacheExpire = false; + return false; + } + finally {} + + if (File.Exists(controlfile)) + return true; + + try + { + Directory.Delete(cachePath, true); + while(Directory.Exists(cachePath)) + Thread.Sleep(100); + } + catch(Exception e) + { + m_log.Error("[MESH CACHE]: failed to delete old version of the cache: " + e.Message); + doMeshFileCache = false; + doCacheExpire = false; + return false; + } + finally {} + try + { + Directory.CreateDirectory(cachePath); + while(!Directory.Exists(cachePath)) + Thread.Sleep(100); + } + catch(Exception e) + { + m_log.Error("[MESH CACHE]: failed to create new cache folder: " + e.Message); + doMeshFileCache = false; + doCacheExpire = false; + return false; + } + finally {} + + try + { + FileStream fs = File.Create(controlfile, 4096, FileOptions.WriteThrough); + fs.Close(); + } + catch(Exception e) + { + m_log.Error("[MESH CACHE]: failed to create new control file: " + e.Message); + doMeshFileCache = false; + doCacheExpire = false; + return false; + } + finally {} + + return true; + } + } + + public bool CreateBoundingHull(List inputVertices, out List convexcoords, out List newfaces) + { + convexcoords = null; + newfaces = null; + HullDesc desc = new HullDesc(); + HullResult result = new HullResult(); + + int nInputVerts = inputVertices.Count; + int i; + + List vs = new List(nInputVerts); + float3 f3; + + //useless copy + for(i = 0 ; i < nInputVerts; i++) + { + f3 = new float3(inputVertices[i].X, inputVertices[i].Y, inputVertices[i].Z); + vs.Add(f3); + } + + desc.Vertices = vs; + desc.Flags = HullFlag.QF_TRIANGLES; + desc.MaxVertices = 256; + + try + { + HullError ret = HullUtils.CreateConvexHull(desc, ref result); + if (ret != HullError.QE_OK) + return false; + int nverts = result.OutputVertices.Count; + int nindx = result.Indices.Count; + if(nverts < 3 || nindx< 3) + return false; + if(nindx % 3 != 0) + return false; + + convexcoords = new List(nverts); + Coord c; + vs = result.OutputVertices; + + for(i = 0 ; i < nverts; i++) + { + c = new Coord(vs[i].x, vs[i].y, vs[i].z); + convexcoords.Add(c); + } + + newfaces = new List(nindx / 3); + List indxs = result.Indices; + int k, l, m; + Face f; + for(i = 0 ; i < nindx;) + { + k = indxs[i++]; + l = indxs[i++]; + m = indxs[i++]; + if(k > nInputVerts) + continue; + if(l > nInputVerts) + continue; + if(m > nInputVerts) + continue; + f = new Face(k,l,m); + newfaces.Add(f); + } + return true; + } + catch + { + + return false; + } + return false; + } } } diff --git a/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs index 10facf2713..e93175f081 100644 --- a/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs +++ b/OpenSim/Region/PhysicsModules/ubOdeMeshing/PrimMesher.cs @@ -755,8 +755,8 @@ namespace PrimMesher if (hollowAngles.angles[0].angle - angles.angles[i].angle < angles.angles[i].angle - hollowAngles.angles[maxJ].angle + 0.000001f) { newFace.v1 = 0; - newFace.v2 = numTotalVerts - maxJ - 1; - newFace.v3 = numTotalVerts - 1; + newFace.v2 = numTotalVerts - 1; + newFace.v3 = numTotalVerts - maxJ - 1; faces.Add(newFace); } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs index 6a39bb95e0..e01d2e44ea 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/AsyncCommandManager.cs @@ -51,7 +51,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api private static Thread cmdHandlerThread; private static int cmdHandlerThreadCycleSleepms; - + private static int numInstances; /// /// Lock for reading/writing static components of AsyncCommandManager. /// @@ -172,18 +172,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!m_XmlRequest.ContainsKey(m_ScriptEngine)) m_XmlRequest[m_ScriptEngine] = new XmlRequest(this); - StartThread(); - } - } - - private static void StartThread() - { - if (cmdHandlerThread == null) - { - // Start the thread that will be doing the work - cmdHandlerThread - = WorkManager.StartThread( + numInstances++; + if (cmdHandlerThread == null) + { + cmdHandlerThread = WorkManager.StartThread( CmdHandlerThreadLoop, "AsyncLSLCmdHandlerThread", ThreadPriority.Normal, true, true); + } } } @@ -194,25 +188,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api cmdHandlerThreadCycleSleepms = 100; } +/* ~AsyncCommandManager() { // Shut down thread -// try -// { -// if (cmdHandlerThread != null) -// { -// if (cmdHandlerThread.IsAlive == true) -// { -// cmdHandlerThread.Abort(); -// //cmdHandlerThread.Join(); -// } -// } -// } -// catch -// { -// } - } + try + { + lock (staticLock) + { + numInstances--; + if(numInstances > 0) + return; + if (cmdHandlerThread != null) + { + if (cmdHandlerThread.IsAlive == true) + { + cmdHandlerThread.Abort(); + //cmdHandlerThread.Join(); + cmdHandlerThread = null; + } + } + } + } + catch + { + } + } +*/ /// /// Main loop for the manager thread /// @@ -223,11 +226,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api try { Thread.Sleep(cmdHandlerThreadCycleSleepms); - + Watchdog.UpdateThread(); DoOneCmdHandlerPass(); - Watchdog.UpdateThread(); } + catch ( System.Threading.ThreadAbortException) { } catch (Exception e) { m_log.Error("[ASYNC COMMAND MANAGER]: Exception in command handler pass: ", e); @@ -240,24 +243,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api lock (staticLock) { // Check HttpRequests - m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests(); + try { m_HttpRequest[m_ScriptEngines[0]].CheckHttpRequests(); } catch {} // Check XMLRPCRequests - m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests(); + try { m_XmlRequest[m_ScriptEngines[0]].CheckXMLRPCRequests(); } catch {} foreach (IScriptEngine s in m_ScriptEngines) { // Check Listeners - m_Listener[s].CheckListeners(); + try { m_Listener[s].CheckListeners(); } catch {} + // Check timers - m_Timer[s].CheckTimerEvents(); + try { m_Timer[s].CheckTimerEvents(); } catch {} // Check Sensors - m_SensorRepeat[s].CheckSenseRepeaterEvents(); + try { m_SensorRepeat[s].CheckSenseRepeaterEvents(); } catch {} // Check dataserver - m_Dataserver[s].ExpireRequests(); + try { m_Dataserver[s].ExpireRequests(); } catch {} } } } @@ -387,8 +391,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - - public static Object[] GetSerializationData(IScriptEngine engine, UUID itemID) { List data = new List(); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 45bdb41ba3..75b6b0e61b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Collections.Specialized; using System.Diagnostics; using System.Drawing; using System.Drawing.Imaging; @@ -40,7 +41,7 @@ using Nini.Config; using log4net; using OpenMetaverse; using OpenMetaverse.Assets; -using OpenMetaverse.StructuredData; +using OpenMetaverse.StructuredData; // LitJson is hidden on this using OpenMetaverse.Packets; using OpenMetaverse.Rendering; using OpenSim; @@ -424,6 +425,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return lease; } + protected SceneObjectPart MonitoringObject() + { + UUID m = m_host.ParentGroup.MonitoringObject; + if (m == UUID.Zero) + return null; + + SceneObjectPart p = m_ScriptEngine.World.GetSceneObjectPart(m); + if (p == null) + m_host.ParentGroup.MonitoringObject = UUID.Zero; + + return p; + } + protected virtual void ScriptSleep(int delay) { delay = (int)((float)delay * m_ScriptDelayFactor); @@ -481,12 +495,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { UUID item; - m_host.AddScriptLPS(1); - - if ((item = GetScriptByName(name)) != UUID.Zero) - m_ScriptEngine.ResetScript(item); - else + if ((item = GetScriptByName(name)) == UUID.Zero) + { + m_host.AddScriptLPS(1); Error("llResetOtherScript", "Can't find script '" + name + "'"); + return; + } + if(item == m_item.ItemID) + llResetScript(); + else + { + m_host.AddScriptLPS(1); + m_ScriptEngine.ResetScript(item); + } } public LSL_Integer llGetScriptState(string name) @@ -2712,9 +2733,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// if TRUE, will cap the distance to 10m. protected void SetPos(SceneObjectPart part, LSL_Vector targetPos, bool adjust) { - if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) + if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted || part.ParentGroup.inTransit) return; + LSL_Vector currentPos = GetPartLocalPos(part); LSL_Vector toPos = GetSetPosTarget(part, targetPos, currentPos, adjust); @@ -2722,7 +2744,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (part.ParentGroup.RootPart == part) { SceneObjectGroup parent = part.ParentGroup; - if (!parent.IsAttachment && !World.Permissions.CanObjectEntry(parent.UUID, false, (Vector3)toPos)) + if (!parent.IsAttachment && !World.Permissions.CanObjectEntry(parent, false, (Vector3)toPos)) return; parent.UpdateGroupPosition((Vector3)toPos); } @@ -3512,32 +3534,34 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void doObjectRez(string inventory, LSL_Vector pos, LSL_Vector vel, LSL_Rotation rot, int param, bool atRoot) { m_host.AddScriptLPS(1); + if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) + return; + + float dist = (float)llVecDist(llGetPos(), pos); + + if (dist > m_ScriptDistanceFactor * 10.0f) + return; + + TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); + + if (item == null) + { + Error("llRez(AtRoot/Object)", "Can't find object '" + inventory + "'"); + return; + } + + if (item.InvType != (int)InventoryType.Object) + { + Error("llRez(AtRoot/Object)", "Can't create requested object; object is missing from database"); + return; + } Util.FireAndForget(x => { - if (Double.IsNaN(rot.x) || Double.IsNaN(rot.y) || Double.IsNaN(rot.z) || Double.IsNaN(rot.s)) - return; - float dist = (float)llVecDist(llGetPos(), pos); - - if (dist > m_ScriptDistanceFactor * 10.0f) - return; - - TaskInventoryItem item = m_host.Inventory.GetInventoryItem(inventory); - - if (item == null) - { - Error("llRez(AtRoot/Object)", "Can't find object '" + inventory + "'"); - return; - } - - if (item.InvType != (int)InventoryType.Object) - { - Error("llRez(AtRoot/Object)", "Can't create requested object; object is missing from database"); - return; - } - - List new_groups = World.RezObject(m_host, item, pos, rot, vel, param, atRoot); + Quaternion wrot = rot; + wrot.Normalize(); + List new_groups = World.RezObject(m_host, item, pos, wrot, vel, param, atRoot); // If either of these are null, then there was an unknown error. if (new_groups == null) @@ -3574,9 +3598,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } - // Variable script delay? (see (http://wiki.secondlife.com/wiki/LSL_Delay) - } - + } }, null, "LSL_Api.doObjectRez"); //ScriptSleep((int)((groupmass * velmag) / 10)); @@ -5738,29 +5760,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); if (index < 0) - { index = src.Length + index; - } + if (index >= src.Length || index < 0) - { return 0; - } + + object item = src.Data[index]; // Vectors & Rotations always return zero in SL, but // keys don't always return zero, it seems to be a bit complex. - else if (src.Data[index] is LSL_Vector || - src.Data[index] is LSL_Rotation) - { + if (item is LSL_Vector || item is LSL_Rotation) return 0; - } + try { - - if (src.Data[index] is LSL_Integer) - return (LSL_Integer)src.Data[index]; - else if (src.Data[index] is LSL_Float) - return Convert.ToInt32(((LSL_Float)src.Data[index]).value); - return new LSL_Integer(src.Data[index].ToString()); + if (item is LSL_Integer) + return (LSL_Integer)item; + else if (item is LSL_Float) + return Convert.ToInt32(((LSL_Float)item).value);; + return new LSL_Integer(item.ToString()); } catch (FormatException) { @@ -5772,38 +5790,38 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); if (index < 0) - { index = src.Length + index; - } + if (index >= src.Length || index < 0) - { - return 0.0; - } + return 0; + + object item = src.Data[index]; // Vectors & Rotations always return zero in SL - else if (src.Data[index] is LSL_Vector || - src.Data[index] is LSL_Rotation) - { + if(item is LSL_Vector || item is LSL_Rotation) return 0; - } + // valid keys seem to get parsed as integers then converted to floats - else + if (item is LSL_Key) { UUID uuidt; - if (src.Data[index] is LSL_Key && UUID.TryParse(src.Data[index].ToString(), out uuidt)) - { - return Convert.ToDouble(new LSL_Integer(src.Data[index].ToString()).value); - } + string s = item.ToString(); + if(UUID.TryParse(s, out uuidt)) + return Convert.ToDouble(new LSL_Integer(s).value); +// we can't do this because a string is also a LSL_Key for now :( +// else +// return 0; } + try { - if (src.Data[index] is LSL_Integer) - return Convert.ToDouble(((LSL_Integer)src.Data[index]).value); - else if (src.Data[index] is LSL_Float) - return Convert.ToDouble(((LSL_Float)src.Data[index]).value); - else if (src.Data[index] is LSL_String) + if (item is LSL_Integer) + return Convert.ToDouble(((LSL_Integer)item).value); + else if (item is LSL_Float) + return Convert.ToDouble(((LSL_Float)item).value); + else if (item is LSL_String) { - string str = ((LSL_String) src.Data[index]).m_string; + string str = ((LSL_String)item).m_string; Match m = Regex.Match(str, "^\\s*(-?\\+?[,0-9]+\\.?[0-9]*)"); if (m != Match.Empty) { @@ -5811,12 +5829,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api double d = 0.0; if (!Double.TryParse(str, out d)) return 0.0; - return d; } return 0.0; } - return Convert.ToDouble(src.Data[index]); + return Convert.ToDouble(item); } catch (FormatException) { @@ -5828,13 +5845,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); if (index < 0) - { index = src.Length + index; - } + if (index >= src.Length || index < 0) - { return String.Empty; - } + return src.Data[index].ToString(); } @@ -5842,14 +5857,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { m_host.AddScriptLPS(1); if (index < 0) - { index = src.Length + index; - } if (index >= src.Length || index < 0) - { - return ""; - } + return String.Empty; + + object item = src.Data[index]; // SL spits out an empty string for types other than key & string // At the time of patching, LSL_Key is currently LSL_String, @@ -5858,31 +5871,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // as it's own struct // NOTE: 3rd case is needed because a NULL_KEY comes through as // type 'obj' and wrongly returns "" - else if (!(src.Data[index] is LSL_String || - src.Data[index] is LSL_Key || - src.Data[index].ToString() == "00000000-0000-0000-0000-000000000000")) + if (!(item is LSL_String || + item is LSL_Key || + item.ToString() == "00000000-0000-0000-0000-000000000000")) { - return ""; + return String.Empty; } - return src.Data[index].ToString(); + return item.ToString(); } public LSL_Vector llList2Vector(LSL_List src, int index) { m_host.AddScriptLPS(1); if (index < 0) - { index = src.Length + index; - } + if (index >= src.Length || index < 0) - { return new LSL_Vector(0, 0, 0); - } - if (src.Data[index].GetType() == typeof(LSL_Vector)) - { - return (LSL_Vector)src.Data[index]; - } + + object item = src.Data[index]; + + if (item.GetType() == typeof(LSL_Vector)) + return (LSL_Vector)item; // SL spits always out ZERO_VECTOR for anything other than // strings or vectors. Although keys always return ZERO_VECTOR, @@ -5890,28 +5901,25 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // a string, a key as string and a string that by coincidence // is a string, so we're going to leave that up to the // LSL_Vector constructor. - else if (!(src.Data[index] is LSL_String || - src.Data[index] is LSL_Vector)) - { - return new LSL_Vector(0, 0, 0); - } - else - { - return new LSL_Vector(src.Data[index].ToString()); - } + if(item is LSL_Vector) + return (LSL_Vector) item; + + if (item is LSL_String) + return new LSL_Vector(item.ToString()); + + return new LSL_Vector(0, 0, 0); } public LSL_Rotation llList2Rot(LSL_List src, int index) { m_host.AddScriptLPS(1); if (index < 0) - { index = src.Length + index; - } + if (index >= src.Length || index < 0) - { return new LSL_Rotation(0, 0, 0, 1); - } + + object item = src.Data[index]; // SL spits always out ZERO_ROTATION for anything other than // strings or vectors. Although keys always return ZERO_ROTATION, @@ -5919,19 +5927,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // a string, a key as string and a string that by coincidence // is a string, so we're going to leave that up to the // LSL_Rotation constructor. - else if (!(src.Data[index] is LSL_String || - src.Data[index] is LSL_Rotation)) - { - return new LSL_Rotation(0, 0, 0, 1); - } - else if (src.Data[index].GetType() == typeof(LSL_Rotation)) - { - return (LSL_Rotation)src.Data[index]; - } - else - { + + if (item.GetType() == typeof(LSL_Rotation)) + return (LSL_Rotation)item; + + if (item is LSL_String) return new LSL_Rotation(src.Data[index].ToString()); - } + + return new LSL_Rotation(0, 0, 0, 1); } public LSL_List llList2List(LSL_List src, int start, int end) @@ -7848,7 +7851,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api UUID key; ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); - if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageBanned, false)) + if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManagePasses, false)) { int expires = 0; if (hours != 0) @@ -7963,7 +7966,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.LSLScriptDanger(m_host, pos); if (result) { return 1; @@ -7972,7 +7975,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { return 0; } - } public void llDialog(string avatar, string message, LSL_List buttons, int chat_channel) @@ -11297,6 +11299,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } break; + case (int)ScriptBaseClass.PRIM_NORMAL: + case (int)ScriptBaseClass.PRIM_SPECULAR: + case (int)ScriptBaseClass.PRIM_ALPHA_MODE: + if (remain < 1) + return new LSL_List(); + + face = (int)rules.GetLSLIntegerItem(idx++); + tex = part.Shape.Textures; + if (face == ScriptBaseClass.ALL_SIDES) + { + for (face = 0; face < GetNumberOfSides(part); face++) + { + Primitive.TextureEntryFace texface = tex.GetFace((uint)face); + getLSLFaceMaterial(ref res, code, part, texface); + } + } + else + { + if (face >= 0 && face < GetNumberOfSides(part)) + { + Primitive.TextureEntryFace texface = tex.GetFace((uint)face); + getLSLFaceMaterial(ref res, code, part, texface); + } + } + break; + case (int)ScriptBaseClass.PRIM_LINK_TARGET: // TODO: Should be issuing a runtime script warning in this case. @@ -11310,6 +11338,108 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return new LSL_List(); } +/* + private string filterTextureUUIDbyRights(UUID origID, SceneObjectPart part, bool checkTaskInventory, bool returnInvName) + { + if(checkTaskInventory) + { + lock (part.TaskInventory) + { + foreach (KeyValuePair inv in part.TaskInventory) + { + if (inv.Value.AssetID == origID) + { + if(inv.Value.InvType == (int)InventoryType.Texture) + { + if(returnInvName) + return inv.Value.Name; + else + return origID.ToString(); + } + else + return UUID.Zero.ToString(); + } + } + } + } + + if(World.Permissions.CanEditObject(m_host.ParentGroup.UUID, m_host.ParentGroup.RootPart.OwnerID)) + return origID.ToString(); + + return UUID.Zero.ToString(); + } +*/ + private void getLSLFaceMaterial(ref LSL_List res, int code, SceneObjectPart part, Primitive.TextureEntryFace texface) + { + UUID matID = texface.MaterialID; + if(matID != UUID.Zero) + { + AssetBase MatAsset = World.AssetService.Get(matID.ToString()); + if(MatAsset != null) + { + Byte[] data = MatAsset.Data; + OSDMap osdmat = (OSDMap)OSDParser.DeserializeLLSDXml(data); + if(osdmat != null && osdmat.ContainsKey("NormMap")) + { + string mapIDstr; + FaceMaterial mat = new FaceMaterial(matID, osdmat); + if(code == ScriptBaseClass.PRIM_NORMAL) + { +// mapIDstr = filterTextureUUIDbyRights(mat.NormalMapID, part, true, false); + mapIDstr = mat.NormalMapID.ToString(); + res.Add(new LSL_String(mapIDstr)); + res.Add(new LSL_Vector(mat.NormalRepeatX, mat.NormalRepeatY, 0)); + res.Add(new LSL_Vector(mat.NormalOffsetX, mat.NormalOffsetY, 0)); + res.Add(new LSL_Float(mat.NormalRotation)); + } + else if(code == ScriptBaseClass.PRIM_SPECULAR ) + { +// mapIDstr = filterTextureUUIDbyRights(mat.SpecularMapID, part, true, false); + const float colorScale = 1.0f/255f; + mapIDstr = mat.SpecularMapID.ToString(); + res.Add(new LSL_String(mapIDstr)); + res.Add(new LSL_Vector(mat.SpecularRepeatX, mat.SpecularRepeatY, 0)); + res.Add(new LSL_Vector(mat.SpecularOffsetX, mat.SpecularOffsetY, 0)); + res.Add(new LSL_Float(mat.SpecularRotation)); + res.Add(new LSL_Vector(mat.SpecularLightColor.R * colorScale, + mat.SpecularLightColor.G * colorScale, + mat.SpecularLightColor.B * colorScale)); + res.Add(new LSL_Integer(mat.SpecularLightExponent)); + res.Add(new LSL_Integer(mat.EnvironmentIntensity)); + } + else if(code == ScriptBaseClass.PRIM_ALPHA_MODE) + { + res.Add(new LSL_Integer(mat.DiffuseAlphaMode)); + res.Add(new LSL_Integer(mat.AlphaMaskCutoff)); + } + return; + } + } + matID = UUID.Zero; + } + if(matID == UUID.Zero) + { + if(code == (int)ScriptBaseClass.PRIM_NORMAL || code == (int)ScriptBaseClass.PRIM_SPECULAR ) + { + res.Add(new LSL_String(UUID.Zero.ToString())); + res.Add(new LSL_Vector(1.0, 1.0, 0)); + res.Add(new LSL_Vector(0, 0, 0)); + res.Add(new LSL_Float(0)); + + if(code == (int)ScriptBaseClass.PRIM_SPECULAR) + { + res.Add(new LSL_Vector(1.0, 1.0, 1.0)); + res.Add(new LSL_Integer(51)); + res.Add(new LSL_Integer(0)); + } + } + else if(code == (int)ScriptBaseClass.PRIM_ALPHA_MODE) + { + res.Add(new LSL_Integer(1)); + res.Add(new LSL_Integer(0)); + } + } + } public LSL_List llGetPrimMediaParams(int face, LSL_List rules) { @@ -12943,7 +13073,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.AddScriptLPS(1); UUID key; ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); - if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManageAllowed, false)) + if (World.Permissions.CanEditParcelProperties(m_host.OwnerID, land, GroupPowers.LandManagePasses, false)) { if (UUID.TryParse(avatar, out key)) { @@ -13276,6 +13406,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api List param = new List(); bool ok; Int32 flag; + int nCustomHeaders = 0; for (int i = 0; i < parameters.Data.Length; i += 2) { @@ -13302,6 +13433,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Second Life documentation for llHTTPRequest. for (int count = 1; count <= 8; ++count) { + if(nCustomHeaders >= 8) + { + Error("llHTTPRequest", "Max number of custom headers is 8, excess ignored"); + break; + } + //Enough parameters remaining for (another) header? if (parameters.Data.Length - i < 2) { @@ -13316,15 +13453,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api param.Add(parameters.Data[i].ToString()); param.Add(parameters.Data[i+1].ToString()); + nCustomHeaders++; //Have we reached the end of the list of headers? //End is marked by a string with a single digit. - if (i+2 >= parameters.Data.Length || - Char.IsDigit(parameters.Data[i].ToString()[0])) + if (i + 2 >= parameters.Data.Length || + Char.IsDigit(parameters.Data[i + 2].ToString()[0])) { break; } - i += 2; } } @@ -15867,7 +16004,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return; } - group.RootPart.AttachPoint = group.RootPart.Shape.State; group.RootPart.AttachedPos = group.AbsolutePosition; group.ResetIDs(); @@ -16565,92 +16701,158 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return String.Empty; } - public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers) - { - OSD o = OSDParser.DeserializeJson(json); - OSD specVal = JsonGetSpecific(o, specifiers, 0); - - return specVal.AsString(); - } - public LSL_List llJson2List(LSL_String json) { + if(String.IsNullOrEmpty(json)) + return new LSL_List(); + if(json == "[]") + return new LSL_List(); + if(json == "{}") + return new LSL_List(); + char first = ((string)json)[0]; + + if(first != '[' && first !='{') + { + // we already have a single element + LSL_List l = new LSL_List(); + l.Add(json); + return l; + } + + LitJson.JsonData jsdata; try { - OSD o = OSDParser.DeserializeJson(json); - return (LSL_List)ParseJsonNode(o); + jsdata = LitJson.JsonMapper.ToObject(json); } - catch (Exception) + catch (Exception e) { - return new LSL_List(ScriptBaseClass.JSON_INVALID); + string m = e.Message; // debug point + return json; + } + try + { + return JsonParseTop(jsdata); + } + catch (Exception e) + { + string m = e.Message; // debug point + return (LSL_String)ScriptBaseClass.JSON_INVALID; } } - private object ParseJsonNode(OSD node) + private LSL_List JsonParseTop(LitJson.JsonData elem) { - if (node.Type == OSDType.Integer) - return new LSL_Integer(node.AsInteger()); - if (node.Type == OSDType.Boolean) - return new LSL_Integer(node.AsBoolean() ? 1 : 0); - if (node.Type == OSDType.Real) - return new LSL_Float(node.AsReal()); - if (node.Type == OSDType.UUID || node.Type == OSDType.String) - return new LSL_String(node.AsString()); - if (node.Type == OSDType.Array) + LSL_List retl = new LSL_List(); + if(elem == null) + retl.Add((LSL_String)ScriptBaseClass.JSON_NULL); + + LitJson.JsonType elemType = elem.GetJsonType(); + switch (elemType) { - LSL_List resp = new LSL_List(); - OSDArray ar = node as OSDArray; - foreach (OSD o in ar) - resp.Add(ParseJsonNode(o)); - return resp; + case LitJson.JsonType.Int: + retl.Add(new LSL_Integer((int)elem)); + return retl; + case LitJson.JsonType.Boolean: + retl.Add((LSL_String)((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE)); + return retl; + case LitJson.JsonType.Double: + retl.Add(new LSL_Float((double)elem)); + return retl; + case LitJson.JsonType.None: + retl.Add((LSL_String)ScriptBaseClass.JSON_NULL); + return retl; + case LitJson.JsonType.String: + retl.Add(new LSL_String((string)elem)); + return retl; + case LitJson.JsonType.Array: + foreach (LitJson.JsonData subelem in elem) + retl.Add(JsonParseTopNodes(subelem)); + return retl; + case LitJson.JsonType.Object: + IDictionaryEnumerator e = ((IOrderedDictionary)elem).GetEnumerator(); + while (e.MoveNext()) + { + retl.Add(new LSL_String((string)e.Key)); + retl.Add(JsonParseTopNodes((LitJson.JsonData)e.Value)); + } + return retl; + default: + throw new Exception(ScriptBaseClass.JSON_INVALID); } - if (node.Type == OSDType.Map) + } + + private object JsonParseTopNodes(LitJson.JsonData elem) + { + if(elem == null) + return ((LSL_String)ScriptBaseClass.JSON_NULL); + + LitJson.JsonType elemType = elem.GetJsonType(); + switch (elemType) { - LSL_List resp = new LSL_List(); - OSDMap ar = node as OSDMap; - foreach (KeyValuePair o in ar) - { - resp.Add(new LSL_String(o.Key)); - resp.Add(ParseJsonNode(o.Value)); - } - return resp; + case LitJson.JsonType.Int: + return (new LSL_Integer((int)elem)); + case LitJson.JsonType.Boolean: + return ((bool)elem ? (LSL_String)ScriptBaseClass.JSON_TRUE : (LSL_String)ScriptBaseClass.JSON_FALSE); + case LitJson.JsonType.Double: + return (new LSL_Float((double)elem)); + case LitJson.JsonType.None: + return ((LSL_String)ScriptBaseClass.JSON_NULL); + case LitJson.JsonType.String: + return (new LSL_String((string)elem)); + case LitJson.JsonType.Array: + case LitJson.JsonType.Object: + string s = LitJson.JsonMapper.ToJson(elem); + return (LSL_String)s; + default: + throw new Exception(ScriptBaseClass.JSON_INVALID); } - throw new Exception(ScriptBaseClass.JSON_INVALID); } public LSL_String llList2Json(LSL_String type, LSL_List values) { try { + StringBuilder sb = new StringBuilder(); if (type == ScriptBaseClass.JSON_ARRAY) { - OSDArray array = new OSDArray(); + sb.Append("["); + int i= 0; foreach (object o in values.Data) { - array.Add(ListToJson(o)); + sb.Append(ListToJson(o)); + if((i++) < values.Data.Length - 1) + sb.Append(","); } - return OSDParser.SerializeJsonString(array); + sb.Append("]"); + return (LSL_String)sb.ToString();; } else if (type == ScriptBaseClass.JSON_OBJECT) { - OSDMap map = new OSDMap(); + sb.Append("{"); for (int i = 0; i < values.Data.Length; i += 2) { if (!(values.Data[i] is LSL_String)) return ScriptBaseClass.JSON_INVALID; - map.Add(((LSL_String)values.Data[i]).m_string, ListToJson(values.Data[i + 1])); + string key = ((LSL_String)values.Data[i]).m_string; + key = EscapeForJSON(key, true); + sb.Append(key); + sb.Append(":"); + sb.Append(ListToJson(values.Data[i+1])); + if(i < values.Data.Length - 2) + sb.Append(","); } - return OSDParser.SerializeJsonString(map); + sb.Append("}"); + return (LSL_String)sb.ToString(); } return ScriptBaseClass.JSON_INVALID; } - catch (Exception ex) + catch { - return ex.Message; + return ScriptBaseClass.JSON_INVALID; } } - private OSD ListToJson(object o) + private string ListToJson(object o) { if (o is LSL_Float || o is double) { @@ -16660,7 +16862,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else float_val = ((LSL_Float)o).value; - return OSD.FromReal(float_val); + if(double.IsInfinity(float_val)) + return "\"Inf\""; + if(double.IsNaN(float_val)) + return "\"NaN\""; + + return ((LSL_Float)float_val).ToString(); } if (o is LSL_Integer || o is int) { @@ -16669,17 +16876,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api i = ((int)o); else i = ((LSL_Integer)o).value; - - if (i == 0) - return OSD.FromBoolean(false); - else if (i == 1) - return OSD.FromBoolean(true); - return OSD.FromInteger(i); + return i.ToString(); } if (o is LSL_Rotation) - return OSD.FromString(((LSL_Rotation)o).ToString()); + { + StringBuilder sb = new StringBuilder(128); + sb.Append("\""); + LSL_Rotation r = (LSL_Rotation)o; + sb.Append(r.ToString()); + sb.Append("\""); + return sb.ToString(); + } if (o is LSL_Vector) - return OSD.FromString(((LSL_Vector)o).ToString()); + { + StringBuilder sb = new StringBuilder(128); + sb.Append("\""); + LSL_Vector v = (LSL_Vector)o; + sb.Append(v.ToString()); + sb.Append("\""); + return sb.ToString(); + } if (o is LSL_String || o is string) { string str; @@ -16688,137 +16904,579 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api else str = ((LSL_String)o).m_string; - if (str == ScriptBaseClass.JSON_NULL) - return new OSD(); - return OSD.FromString(str); + if(str == ScriptBaseClass.JSON_TRUE || str == "true") + return "true"; + if(str == ScriptBaseClass.JSON_FALSE ||str == "false") + return "false"; + if(str == ScriptBaseClass.JSON_NULL || str == "null") + return "null"; + str.Trim(); + if (str[0] == '{') + return str; + if (str[0] == '[') + return str; + return EscapeForJSON(str, true); } - throw new Exception(ScriptBaseClass.JSON_INVALID); + throw new IndexOutOfRangeException(); } - private OSD JsonGetSpecific(OSD o, LSL_List specifiers, int i) + private string EscapeForJSON(string s, bool AddOuter) { - object spec = specifiers.Data[i]; - OSD nextVal = null; - if (o is OSDArray) + int i; + char c; + String t; + int len = s.Length; + + StringBuilder sb = new StringBuilder(len + 64); + if(AddOuter) + sb.Append("\""); + + for (i = 0; i < len; i++) { - if (spec is LSL_Integer) - nextVal = ((OSDArray)o)[((LSL_Integer)spec).value]; + c = s[i]; + switch (c) + { + case '\\': + case '"': + case '/': + sb.Append('\\'); + sb.Append(c); + break; + case '\b': + sb.Append("\\b"); + break; + case '\t': + sb.Append("\\t"); + break; + case '\n': + sb.Append("\\n"); + break; + case '\f': + sb.Append("\\f"); + break; + case '\r': + sb.Append("\\r"); + break; + default: + if (c < ' ') + { + t = "000" + String.Format("X", c); + sb.Append("\\u" + t.Substring(t.Length - 4)); + } + else + { + sb.Append(c); + } + break; + } } - if (o is OSDMap) - { - if (spec is LSL_String) - nextVal = ((OSDMap)o)[((LSL_String)spec).m_string]; - } - if (nextVal != null) - { - if (specifiers.Data.Length - 1 > i) - return JsonGetSpecific(nextVal, specifiers, i + 1); - } - return nextVal; + if(AddOuter) + sb.Append("\""); + return sb.ToString(); } public LSL_String llJsonSetValue(LSL_String json, LSL_List specifiers, LSL_String value) { + bool noSpecifiers = specifiers.Length == 0; + LitJson.JsonData workData; try { - OSD o = OSDParser.DeserializeJson(json); - JsonSetSpecific(o, specifiers, 0, value); - return OSDParser.SerializeJsonString(o); + if(noSpecifiers) + specifiers.Add(new LSL_Integer(0)); + + if(!String.IsNullOrEmpty(json)) + workData = LitJson.JsonMapper.ToObject(json); + else + { + workData = new LitJson.JsonData(); + workData.SetJsonType(LitJson.JsonType.Array); + } } - catch (Exception) + catch (Exception e) { + string m = e.Message; // debug point + return ScriptBaseClass.JSON_INVALID; + } + try + { + LitJson.JsonData replace = JsonSetSpecific(workData, specifiers, 0, value); + if(replace != null) + workData = replace; + } + catch (Exception e) + { + string m = e.Message; // debug point + return ScriptBaseClass.JSON_INVALID; + } + + try + { + string r = LitJson.JsonMapper.ToJson(workData); + if(noSpecifiers) + r = r.Substring(1,r.Length -2); // strip leading and trailing brakets + return r; + } + catch (Exception e) + { + string m = e.Message; // debug point } return ScriptBaseClass.JSON_INVALID; } - private void JsonSetSpecific(OSD o, LSL_List specifiers, int i, LSL_String val) + private LitJson.JsonData JsonSetSpecific(LitJson.JsonData elem, LSL_List specifiers, int level, LSL_String val) { - object spec = specifiers.Data[i]; - // 20131224 not used object specNext = i+1 == specifiers.Data.Length ? null : specifiers.Data[i+1]; - OSD nextVal = null; - if (o is OSDArray) + object spec = specifiers.Data[level]; + if(spec is LSL_String) + spec = ((LSL_String)spec).m_string; + else if (spec is LSL_Integer) + spec = ((LSL_Integer)spec).value; + + if(!(spec is string || spec is int)) + throw new IndexOutOfRangeException(); + + int speclen = specifiers.Data.Length - 1; + + bool hasvalue = false; + LitJson.JsonData value = null; + + LitJson.JsonType elemType = elem.GetJsonType(); + if (elemType == LitJson.JsonType.Array) + { + if (spec is int) + { + int v = (int)spec; + int c = elem.Count; + if(v < 0 || (v != 0 && v > c)) + throw new IndexOutOfRangeException(); + if(v == c) + elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); + else + { + hasvalue = true; + value = elem[v]; + } + } + else if (spec is string) + { + if((string)spec == ScriptBaseClass.JSON_APPEND) + elem.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); + else if(elem.Count < 2) + { + // our initial guess of array was wrong + LitJson.JsonData newdata = new LitJson.JsonData(); + newdata.SetJsonType(LitJson.JsonType.Object); + IOrderedDictionary no = newdata as IOrderedDictionary; + no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val)); + return newdata; + } + } + } + else if (elemType == LitJson.JsonType.Object) + { + if (spec is string) + { + IOrderedDictionary e = elem as IOrderedDictionary; + string key = (string)spec; + if(e.Contains(key)) + { + hasvalue = true; + value = (LitJson.JsonData)e[key]; + } + else + e.Add(key, JsonBuildRestOfSpec(specifiers, level + 1, val)); + } + else if(spec is int && (int)spec == 0) + { + //we are replacing a object by a array + LitJson.JsonData newData = new LitJson.JsonData(); + newData.SetJsonType(LitJson.JsonType.Array); + newData.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); + return newData; + } + } + else + { + LitJson.JsonData newData = JsonBuildRestOfSpec(specifiers, level, val); + return newData; + } + + if (hasvalue) + { + if (level < speclen) + { + LitJson.JsonData replace = JsonSetSpecific(value, specifiers, level + 1, val); + if(replace != null) + { + if(elemType == LitJson.JsonType.Array) + { + if(spec is int) + elem[(int)spec] = replace; + else if( spec is string) + { + LitJson.JsonData newdata = new LitJson.JsonData(); + newdata.SetJsonType(LitJson.JsonType.Object); + IOrderedDictionary no = newdata as IOrderedDictionary; + no.Add((string)spec, replace); + return newdata; + } + } + else if(elemType == LitJson.JsonType.Object) + { + if(spec is string) + elem[(string)spec] = replace; + else if(spec is int && (int)spec == 0) + { + LitJson.JsonData newdata = new LitJson.JsonData(); + newdata.SetJsonType(LitJson.JsonType.Array); + newdata.Add(replace); + return newdata; + } + } + } + return null; + } + else if(speclen == level) + { + if(val == ScriptBaseClass.JSON_DELETE) + { + if(elemType == LitJson.JsonType.Array) + { + if(spec is int) + { + IList el = elem as IList; + el.RemoveAt((int)spec); + } + } + else if(elemType == LitJson.JsonType.Object) + { + if(spec is string) + { + IOrderedDictionary eo = elem as IOrderedDictionary; + eo.Remove((string) spec); + } + } + return null; + } + + LitJson.JsonData newval = null; + float num; + if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null") + newval = null; + else if(val == ScriptBaseClass.JSON_TRUE || val == "true") + newval = new LitJson.JsonData(true); + else if(val == ScriptBaseClass.JSON_FALSE || val == "false") + newval = new LitJson.JsonData(false); + else if(float.TryParse(val, out num)) + { + // assuming we are at en.us already + if(num - (int)num == 0.0f && !val.Contains(".")) + newval = new LitJson.JsonData((int)num); + else + { + num = (float)Math.Round(num,6); + newval = new LitJson.JsonData((double)num); + } + } + else + { + string str = val.m_string; + newval = new LitJson.JsonData(str); + } + + if(elemType == LitJson.JsonType.Array) + { + if(spec is int) + elem[(int)spec] = newval; + else if( spec is string) + { + LitJson.JsonData newdata = new LitJson.JsonData(); + newdata.SetJsonType(LitJson.JsonType.Object); + IOrderedDictionary no = newdata as IOrderedDictionary; + no.Add((string)spec,newval); + return newdata; + } + } + else if(elemType == LitJson.JsonType.Object) + { + if(spec is string) + elem[(string)spec] = newval; + else if(spec is int && (int)spec == 0) + { + LitJson.JsonData newdata = new LitJson.JsonData(); + newdata.SetJsonType(LitJson.JsonType.Array); + newdata.Add(newval); + return newdata; + } + } + } + } + if(val == ScriptBaseClass.JSON_DELETE) + throw new IndexOutOfRangeException(); + return null; + } + + private LitJson.JsonData JsonBuildRestOfSpec(LSL_List specifiers, int level, LSL_String val) + { + object spec = level >= specifiers.Data.Length ? null : specifiers.Data[level]; + // 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1]; + + float num; + if (spec == null) + { + if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null") + return null; + if(val == ScriptBaseClass.JSON_DELETE) + throw new IndexOutOfRangeException(); + if(val == ScriptBaseClass.JSON_TRUE || val == "true") + return new LitJson.JsonData(true); + if(val == ScriptBaseClass.JSON_FALSE || val == "false") + return new LitJson.JsonData(false); + if(val == null || val == ScriptBaseClass.JSON_NULL || val == "null") + return null; + if(float.TryParse(val, out num)) + { + // assuming we are at en.us already + if(num - (int)num == 0.0f && !val.Contains(".")) + return new LitJson.JsonData((int)num); + else + { + num = (float)Math.Round(num,6); + return new LitJson.JsonData(num); + } + } + else + { + string str = val.m_string; + return new LitJson.JsonData(str); + } + throw new IndexOutOfRangeException(); + } + + if(spec is LSL_String) + spec = ((LSL_String)spec).m_string; + else if (spec is LSL_Integer) + spec = ((LSL_Integer)spec).value; + + if (spec is int || + (spec is string && ((string)spec) == ScriptBaseClass.JSON_APPEND) ) + { + if(spec is int && (int)spec != 0) + throw new IndexOutOfRangeException(); + LitJson.JsonData newdata = new LitJson.JsonData(); + newdata.SetJsonType(LitJson.JsonType.Array); + newdata.Add(JsonBuildRestOfSpec(specifiers, level + 1, val)); + return newdata; + } + else if (spec is string) + { + LitJson.JsonData newdata = new LitJson.JsonData(); + newdata.SetJsonType(LitJson.JsonType.Object); + IOrderedDictionary no = newdata as IOrderedDictionary; + no.Add((string)spec,JsonBuildRestOfSpec(specifiers, level + 1, val)); + return newdata; + } + throw new IndexOutOfRangeException(); + } + + private bool JsonFind(LitJson.JsonData elem, LSL_List specifiers, int level, out LitJson.JsonData value) + { + value = null; + if(elem == null) + return false; + + object spec; + spec = specifiers.Data[level]; + + bool haveVal = false; + LitJson.JsonData next = null; + + if (elem.GetJsonType() == LitJson.JsonType.Array) { - OSDArray array = ((OSDArray)o); if (spec is LSL_Integer) { - int v = ((LSL_Integer)spec).value; - if (v >= array.Count) - array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val)); - else - nextVal = ((OSDArray)o)[v]; + int indx = (LSL_Integer)spec; + if(indx >= 0 && indx < elem.Count) + { + haveVal = true; + next = (LitJson.JsonData)elem[indx]; + } } - else if (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND) - array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val)); } - if (o is OSDMap) + else if (elem.GetJsonType() == LitJson.JsonType.Object) { if (spec is LSL_String) { - OSDMap map = ((OSDMap)o); - if (map.ContainsKey(((LSL_String)spec).m_string)) - nextVal = map[((LSL_String)spec).m_string]; - else - map.Add(((LSL_String)spec).m_string, JsonBuildRestOfSpec(specifiers, i + 1, val)); + IOrderedDictionary e = elem as IOrderedDictionary; + string key = (LSL_String)spec; + if(e.Contains(key)) + { + haveVal = true; + next = (LitJson.JsonData)e[key]; + } } } - if (nextVal != null) + + if (haveVal) { - if (specifiers.Data.Length - 1 > i) + if(level == specifiers.Data.Length - 1) { - JsonSetSpecific(nextVal, specifiers, i + 1, val); - return; + value = next; + return true; } + + level++; + if(next == null) + return false; + + LitJson.JsonType nextType = next.GetJsonType(); + if(nextType != LitJson.JsonType.Object && nextType != LitJson.JsonType.Array) + return false; + + return JsonFind(next, specifiers, level, out value); } + return false; } - private OSD JsonBuildRestOfSpec(LSL_List specifiers, int i, LSL_String val) + public LSL_String llJsonGetValue(LSL_String json, LSL_List specifiers) { - object spec = i >= specifiers.Data.Length ? null : specifiers.Data[i]; - // 20131224 not used object specNext = i+1 >= specifiers.Data.Length ? null : specifiers.Data[i+1]; + if(String.IsNullOrWhiteSpace(json)) + return ScriptBaseClass.JSON_INVALID; - if (spec == null) - return OSD.FromString(val); + if(specifiers.Length > 0 && (json == "{}" || json == "[]")) + return ScriptBaseClass.JSON_INVALID; - if (spec is LSL_Integer || - (spec is LSL_String && ((LSL_String)spec) == ScriptBaseClass.JSON_APPEND)) + char first = ((string)json)[0]; + if((first != '[' && first !='{')) { - OSDArray array = new OSDArray(); - array.Add(JsonBuildRestOfSpec(specifiers, i + 1, val)); - return array; + if(specifiers.Length > 0) + return ScriptBaseClass.JSON_INVALID; + json = "[" + json + "]"; // could handle single element case.. but easier like this + specifiers.Add((LSL_Integer)0); } - else if (spec is LSL_String) + + LitJson.JsonData jsonData; + try { - OSDMap map = new OSDMap(); - map.Add((LSL_String)spec, JsonBuildRestOfSpec(specifiers, i + 1, val)); - return map; + jsonData = LitJson.JsonMapper.ToObject(json); + } + catch (Exception e) + { + string m = e.Message; // debug point + return ScriptBaseClass.JSON_INVALID; + } + + LitJson.JsonData elem = null; + if(specifiers.Length == 0) + elem = jsonData; + else + { + if(!JsonFind(jsonData, specifiers, 0, out elem)) + return ScriptBaseClass.JSON_INVALID; + } + return JsonElementToString(elem); + } + + private LSL_String JsonElementToString(LitJson.JsonData elem) + { + if(elem == null) + return ScriptBaseClass.JSON_NULL; + + LitJson.JsonType elemType = elem.GetJsonType(); + switch(elemType) + { + case LitJson.JsonType.Array: + return new LSL_String(LitJson.JsonMapper.ToJson(elem)); + case LitJson.JsonType.Boolean: + return new LSL_String((bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE); + case LitJson.JsonType.Double: + double d= (double)elem; + string sd = String.Format(Culture.FormatProvider, "{0:0.0#####}",d); + return new LSL_String(sd); + case LitJson.JsonType.Int: + int i = (int)elem; + return new LSL_String(i.ToString()); + case LitJson.JsonType.Long: + long l = (long)elem; + return new LSL_String(l.ToString()); + case LitJson.JsonType.Object: + return new LSL_String(LitJson.JsonMapper.ToJson(elem)); + case LitJson.JsonType.String: + string s = (string)elem; + return new LSL_String(s); + case LitJson.JsonType.None: + return ScriptBaseClass.JSON_NULL; + default: + return ScriptBaseClass.JSON_INVALID; } - return new OSD(); } public LSL_String llJsonValueType(LSL_String json, LSL_List specifiers) { - OSD o = OSDParser.DeserializeJson(json); - OSD specVal = JsonGetSpecific(o, specifiers, 0); - if (specVal == null) + if(String.IsNullOrWhiteSpace(json)) return ScriptBaseClass.JSON_INVALID; - switch (specVal.Type) + + if(specifiers.Length > 0 && (json == "{}" || json == "[]")) + return ScriptBaseClass.JSON_INVALID; + + char first = ((string)json)[0]; + if((first != '[' && first !='{')) { - case OSDType.Array: - return ScriptBaseClass.JSON_ARRAY; - case OSDType.Boolean: - return specVal.AsBoolean() ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE; - case OSDType.Integer: - case OSDType.Real: - return ScriptBaseClass.JSON_NUMBER; - case OSDType.Map: - return ScriptBaseClass.JSON_OBJECT; - case OSDType.String: - case OSDType.UUID: - return ScriptBaseClass.JSON_STRING; - case OSDType.Unknown: - return ScriptBaseClass.JSON_NULL; + if(specifiers.Length > 0) + return ScriptBaseClass.JSON_INVALID; + json = "[" + json + "]"; // could handle single element case.. but easier like this + specifiers.Add((LSL_Integer)0); + } + + LitJson.JsonData jsonData; + try + { + jsonData = LitJson.JsonMapper.ToObject(json); + } + catch (Exception e) + { + string m = e.Message; // debug point + return ScriptBaseClass.JSON_INVALID; + } + + LitJson.JsonData elem = null; + if(specifiers.Length == 0) + elem = jsonData; + else + { + if(!JsonFind(jsonData, specifiers, 0, out elem)) + return ScriptBaseClass.JSON_INVALID; + } + + if(elem == null) + return ScriptBaseClass.JSON_NULL; + + LitJson.JsonType elemType = elem.GetJsonType(); + switch(elemType) + { + case LitJson.JsonType.Array: + return ScriptBaseClass.JSON_ARRAY; + case LitJson.JsonType.Boolean: + return (bool)elem ? ScriptBaseClass.JSON_TRUE : ScriptBaseClass.JSON_FALSE; + case LitJson.JsonType.Double: + case LitJson.JsonType.Int: + case LitJson.JsonType.Long: + return ScriptBaseClass.JSON_NUMBER; + case LitJson.JsonType.Object: + return ScriptBaseClass.JSON_OBJECT; + case LitJson.JsonType.String: + string s = (string)elem; + if(s == ScriptBaseClass.JSON_NULL) + return ScriptBaseClass.JSON_NULL; + if(s == ScriptBaseClass.JSON_TRUE) + return ScriptBaseClass.JSON_TRUE; + if(s == ScriptBaseClass.JSON_FALSE) + return ScriptBaseClass.JSON_FALSE; + return ScriptBaseClass.JSON_STRING; + case LitJson.JsonType.None: + return ScriptBaseClass.JSON_NULL; + default: + return ScriptBaseClass.JSON_INVALID; } - return ScriptBaseClass.JSON_INVALID; } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index e769c6da10..79367fbae3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -260,9 +260,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api wComm.DeliverMessage(ChatTypeEnum.Shout, ScriptBaseClass.DEBUG_CHANNEL, m_host.Name, m_host.UUID, message); } - // Returns of the function is allowed. Throws a script exception if not allowed. + // Returns if OSSL is enabled. Throws a script exception if OSSL is not allowed.. + // for safe funtions always active + public void CheckThreatLevel() + { + m_host.AddScriptLPS(1); + if (!m_OSFunctionsEnabled) + OSSLError(String.Format("{0} permission denied. All OS functions are disabled.")); // throws + } + + // Returns if the function is allowed. Throws a script exception if not allowed. public void CheckThreatLevel(ThreatLevel level, string function) { + m_host.AddScriptLPS(1); if (!m_OSFunctionsEnabled) OSSLError(String.Format("{0} permission denied. All OS functions are disabled.", function)); // throws @@ -444,7 +454,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } - if (!m_FunctionPerms[function].AllowedCreators.Contains(m_item.CreatorID)) return( String.Format("{0} permission denied. Script creator is not in the list of users allowed to execute this function and prim owner also has no permission.", @@ -491,8 +500,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api private LSL_Integer SetTerrainHeight(int x, int y, double val) { - m_host.AddScriptLPS(1); - if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0) OSSLError("osSetTerrainHeight: Coordinate out of bounds"); @@ -509,20 +516,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float osGetTerrainHeight(int x, int y) { - CheckThreatLevel(ThreatLevel.None, "osGetTerrainHeight"); + CheckThreatLevel(); return GetTerrainHeight(x, y); } public LSL_Float osTerrainGetHeight(int x, int y) { - CheckThreatLevel(ThreatLevel.None, "osTerrainGetHeight"); + CheckThreatLevel(); OSSLDeprecated("osTerrainGetHeight", "osGetTerrainHeight"); return GetTerrainHeight(x, y); } private LSL_Float GetTerrainHeight(int x, int y) { - m_host.AddScriptLPS(1); if (x > (World.RegionInfo.RegionSizeX - 1) || x < 0 || y > (World.RegionInfo.RegionSizeY - 1) || y < 0) OSSLError("osGetTerrainHeight: Coordinate out of bounds"); @@ -532,7 +538,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osTerrainFlush() { CheckThreatLevel(ThreatLevel.VeryLow, "osTerrainFlush"); - m_host.AddScriptLPS(1); ITerrainModule terrainModule = World.RequestModuleInterface(); if (terrainModule != null) terrainModule.TaintTerrain(); @@ -549,7 +554,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.High, "osRegionRestart"); IRestartModule restartModule = World.RequestModuleInterface(); - m_host.AddScriptLPS(1); if (World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false) && (restartModule != null)) { if (seconds < 15) @@ -572,7 +576,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api CheckThreatLevel(ThreatLevel.High, "osRegionRestart"); IRestartModule restartModule = World.RequestModuleInterface(); - m_host.AddScriptLPS(1); if (World.Permissions.CanIssueEstateCommand(m_host.OwnerID, false) && (restartModule != null)) { if (seconds < 15) @@ -623,8 +626,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.VeryHigh, "osRegionNotice"); - m_host.AddScriptLPS(1); - IDialogModule dm = World.RequestModuleInterface(); if (dm != null) @@ -638,7 +639,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.VeryHigh, "osSetRot"); - m_host.AddScriptLPS(1); if (World.Entities.ContainsKey(target)) { EntityBase entity; @@ -664,13 +664,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURL"); - m_host.AddScriptLPS(1); if (dynamicID == String.Empty) { IDynamicTextureManager textureManager = World.RequestModuleInterface(); UUID createdTexture = textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, - extraParams, timer); + extraParams); return createdTexture.ToString(); } else @@ -686,13 +685,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlend"); - m_host.AddScriptLPS(1); if (dynamicID == String.Empty) { IDynamicTextureManager textureManager = World.RequestModuleInterface(); UUID createdTexture = textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, - extraParams, timer, true, (byte) alpha); + extraParams, true, (byte) alpha); return createdTexture.ToString(); } else @@ -708,13 +706,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureURLBlendFace"); - m_host.AddScriptLPS(1); if (dynamicID == String.Empty) { IDynamicTextureManager textureManager = World.RequestModuleInterface(); UUID createdTexture = textureManager.AddDynamicTextureURL(World.RegionInfo.RegionID, m_host.UUID, contentType, url, - extraParams, timer, blend, disp, (byte) alpha, face); + extraParams, blend, disp, (byte) alpha, face); return createdTexture.ToString(); } else @@ -727,10 +724,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer) + { + return osSetDynamicTextureDataFace(dynamicID, contentType, data, extraParams, timer, -1); + } + + public string osSetDynamicTextureDataFace(string dynamicID, string contentType, string data, string extraParams, + int timer, int face) { CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureData"); - m_host.AddScriptLPS(1); if (dynamicID == String.Empty) { IDynamicTextureManager textureManager = World.RequestModuleInterface(); @@ -742,7 +744,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } UUID createdTexture = textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, - extraParams, timer); + extraParams, false, 3, 255, face); + return createdTexture.ToString(); } } @@ -759,7 +762,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlend"); - m_host.AddScriptLPS(1); if (dynamicID == String.Empty) { IDynamicTextureManager textureManager = World.RequestModuleInterface(); @@ -771,7 +773,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } UUID createdTexture = textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, - extraParams, timer, true, (byte) alpha); + extraParams, true, (byte) alpha); return createdTexture.ToString(); } } @@ -786,9 +788,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams, bool blend, int disp, int timer, int alpha, int face) { - CheckThreatLevel(ThreatLevel.VeryLow, "osSetDynamicTextureDataBlendFace"); + CheckThreatLevel(ThreatLevel.VeryLow , "osSetDynamicTextureDataBlendFace"); - m_host.AddScriptLPS(1); if (dynamicID == String.Empty) { IDynamicTextureManager textureManager = World.RequestModuleInterface(); @@ -800,7 +801,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } UUID createdTexture = textureManager.AddDynamicTextureData(World.RegionInfo.RegionID, m_host.UUID, contentType, data, - extraParams, timer, blend, disp, (byte) alpha, face); + extraParams, blend, disp, (byte) alpha, face); return createdTexture.ToString(); } } @@ -816,8 +817,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.Severe, "osConsoleCommand"); - m_host.AddScriptLPS(1); - // For safety, we add another permission check here, and don't rely only on the standard OSSL permissions if (World.Permissions.CanRunConsoleCommand(m_host.OwnerID)) { @@ -832,11 +831,50 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryLow, "osSetPrimFloatOnWater"); - m_host.AddScriptLPS(1); - m_host.ParentGroup.RootPart.SetFloatOnWater(floatYN); } + private bool checkAllowAgentTPbyLandOwner(UUID agentId, Vector3 pos) + { + UUID hostOwner = m_host.OwnerID; + + if(hostOwner == agentId) + return true; + + if (m_item.PermsGranter == agentId) + { + if ((m_item.PermsMask & ScriptBaseClass.PERMISSION_TELEPORT) != 0) + return true; + } + + ILandObject land = World.LandChannel.GetLandObject(pos); + if(land == null) + return true; + + LandData landdata = land.LandData; + if(landdata == null) + return true; + + if(landdata.OwnerID == hostOwner) + return true; + + EstateSettings es = World.RegionInfo.EstateSettings; + if(es != null && es.IsEstateManagerOrOwner(hostOwner)) + return true; + + if(!landdata.IsGroupOwned) + return false; + + UUID landGroup = landdata.GroupID; + if(landGroup == UUID.Zero) + return false; + + if(landGroup == m_host.GroupID) + return true; + + return false; + } + // Teleport functions public void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) { @@ -844,41 +882,46 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent"); - TeleportAgent(agent, regionName, position, lookat, false); + TeleportAgent(agent, regionName, position, lookat); } private void TeleportAgent(string agent, string regionName, - LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) + LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) { - m_host.AddScriptLPS(1); - UUID agentId = new UUID(); + if(String.IsNullOrEmpty(regionName)) + regionName = World.RegionInfo.RegionName; + + UUID agentId; if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); - if (presence != null) + if (presence == null || presence.IsDeleted || presence.IsInTransit) + return; + + Vector3 pos = presence.AbsolutePosition; + if(!checkAllowAgentTPbyLandOwner(agentId, pos)) { - // For osTeleportAgent, agent must be over owners land to avoid abuse - // For osTeleportOwner, this restriction isn't necessary - - // commented out because its redundant and uneeded please remove eventually. - // if (relaxRestrictions || - // m_host.OwnerID - // == World.LandChannel.GetLandObject( - // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) - // { - - // We will launch the teleport on a new thread so that when the script threads are terminated - // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget( - o => World.RequestTeleportLocation( - presence.ControllingClient, regionName, position, - lookat, (uint)TPFlags.ViaLocation), - null, "OSSL_Api.TeleportAgentByRegionCoords"); - - ScriptSleep(5000); - - // } + ScriptSleep(500); + return; + } + if(regionName == World.RegionInfo.RegionName) + { + // should be faster than going to threadpool + World.RequestTeleportLocation(presence.ControllingClient, regionName, position, + lookat, (uint)TPFlags.ViaLocation); + ScriptSleep(500); + } + else + { + // 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), + null, "OSSL_Api.TeleportAgentByRegionCoords"); + ScriptSleep(5000); } } } @@ -889,50 +932,58 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.Severe, "osTeleportAgent"); - TeleportAgent(agent, regionGridX, regionGridY, position, lookat, false); + TeleportAgent(agent, regionGridX, regionGridY, position, lookat); } private void TeleportAgent(string agent, int regionGridX, int regionGridY, - LSL_Types.Vector3 position, LSL_Types.Vector3 lookat, bool relaxRestrictions) + LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) { ulong regionHandle = Util.RegionGridLocToHandle((uint)regionGridX, (uint)regionGridY); - m_host.AddScriptLPS(1); - UUID agentId = new UUID(); + UUID agentId; if (UUID.TryParse(agent, out agentId)) { ScenePresence presence = World.GetScenePresence(agentId); - if (presence != null) + if (presence == null || presence.IsDeleted || presence.IsInTransit) + return; + + Vector3 pos = presence.AbsolutePosition; + if(!checkAllowAgentTPbyLandOwner(agentId, pos)) { - // For osTeleportAgent, agent must be over owners land to avoid abuse - // For osTeleportOwner, this restriction isn't necessary - - // commented out because its redundant and uneeded please remove eventually. - // if (relaxRestrictions || - // m_host.OwnerID - // == World.LandChannel.GetLandObject( - // presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) - // { - - // We will launch the teleport on a new thread so that when the script threads are terminated - // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting. - Util.FireAndForget( - o => World.RequestTeleportLocation( - presence.ControllingClient, regionHandle, - position, lookat, (uint)TPFlags.ViaLocation), - null, "OSSL_Api.TeleportAgentByRegionName"); - - ScriptSleep(5000); - - // } - + ScriptSleep(500); + return; } + + Util.FireAndForget( + o => World.RequestTeleportLocation( + presence.ControllingClient, regionHandle, + position, lookat, (uint)TPFlags.ViaLocation), + null, "OSSL_Api.TeleportAgentByRegionName"); + + ScriptSleep(5000); } } public void osTeleportAgent(string agent, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) { - osTeleportAgent(agent, World.RegionInfo.RegionName, position, lookat); + UUID agentId; + if (UUID.TryParse(agent, out agentId)) + { + ScenePresence presence = World.GetScenePresence(agentId); + if (presence == null || presence.IsDeleted || presence.IsInTransit) + return; + + Vector3 pos = presence.AbsolutePosition; + if(!checkAllowAgentTPbyLandOwner(agentId, pos)) + { + ScriptSleep(500); + return; + } + + World.RequestTeleportLocation(presence.ControllingClient, World.RegionInfo.RegionName, position, + lookat, (uint)TPFlags.ViaLocation); + ScriptSleep(500); + } } public void osTeleportOwner(string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) @@ -940,19 +991,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Threat level None because this is what can already be done with the World Map in the viewer CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); - TeleportAgent(m_host.OwnerID.ToString(), regionName, position, lookat, true); - } - - public void osTeleportOwner(LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) - { - osTeleportOwner(World.RegionInfo.RegionName, position, lookat); + TeleportAgent(m_host.OwnerID.ToString(), regionName, position, lookat); } public void osTeleportOwner(int regionGridX, int regionGridY, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) { CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); - TeleportAgent(m_host.OwnerID.ToString(), regionGridX, regionGridY, position, lookat, true); + TeleportAgent(m_host.OwnerID.ToString(), regionGridX, regionGridY, position, lookat); + } + + public void osTeleportOwner(LSL_Types.Vector3 position, LSL_Types.Vector3 lookat) + { + CheckThreatLevel(ThreatLevel.None, "osTeleportOwner"); + + osTeleportAgent(m_host.OwnerID.ToString(), position, lookat); } /// @@ -966,8 +1019,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryHigh, "osForceOtherSit"); - m_host.AddScriptLPS(1); - ForceSit(avatar, m_host.UUID); } @@ -981,8 +1032,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryHigh, "osForceOtherSit"); - m_host.AddScriptLPS(1); - UUID targetID = new UUID(target); ForceSit(avatar, targetID); @@ -1007,21 +1056,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api targetID, part.SitTargetPosition); } + + // Get a list of all the avatars/agents in the region + public LSL_List osGetAgents() + { + // threat level is None as we could get this information with an + // in-world script as well, just not as efficient + CheckThreatLevel(ThreatLevel.None, "osGetAgents"); + + LSL_List result = new LSL_List(); + World.ForEachRootScenePresence(delegate(ScenePresence sp) + { + result.Add(new LSL_String(sp.Name)); + }); + return result; + } - // Functions that get information from the agent itself. - // - // osGetAgentIP - this is used to determine the IP address of - //the client. This is needed to help configure other in world - //resources based on the IP address of the clients connected. - //I think High is a good risk level for this, as it is an - //information leak. public string osGetAgentIP(string agent) { - CheckThreatLevel(ThreatLevel.High, "osGetAgentIP"); + CheckThreatLevel(ThreatLevel.Severe, "osGetAgentIP"); + if(!(World.Permissions.IsGod(m_host.OwnerID))) // user god always needed + return ""; UUID avatarID = (UUID)agent; - m_host.AddScriptLPS(1); if (World.Entities.ContainsKey((UUID)agent) && World.Entities[avatarID] is ScenePresence) { ScenePresence target = (ScenePresence)World.Entities[avatarID]; @@ -1032,22 +1090,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api return ""; } - // Get a list of all the avatars/agents in the region - public LSL_List osGetAgents() - { - // threat level is None as we could get this information with an - // in-world script as well, just not as efficient - CheckThreatLevel(ThreatLevel.None, "osGetAgents"); - m_host.AddScriptLPS(1); - - LSL_List result = new LSL_List(); - World.ForEachRootScenePresence(delegate(ScenePresence sp) - { - result.Add(new LSL_String(sp.Name)); - }); - return result; - } - // Adam's super super custom animation functions public void osAvatarPlayAnimation(string avatar, string animation) { @@ -1058,19 +1100,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api private void AvatarPlayAnimation(string avatar, string animation) { - m_host.AddScriptLPS(1); - UUID avatarID; if(!UUID.TryParse(avatar, out avatarID)) return; - if(!World.Entities.ContainsKey(avatarID)) - return; - - ScenePresence target = null; - if ((World.Entities[avatarID] is ScenePresence)) - target = (ScenePresence)World.Entities[avatarID]; - + ScenePresence target = World.GetScenePresence(avatarID); if (target == null) return; @@ -1106,8 +1140,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { UUID avatarID = (UUID)avatar; - m_host.AddScriptLPS(1); - // FIXME: What we really want to do here is factor out the similar code in llStopAnimation() to a common // method (though see that doesn't do the is animation check, which is probably a bug) and have both // these functions call that common code. However, this does mean navigating the brain-dead requirement @@ -1138,29 +1170,59 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } //Texture draw functions + + public string osDrawResetTransform(string drawList) + { + CheckThreatLevel(); + + drawList += "ResetTransf;"; + return drawList; + } + + public string osDrawRotationTransform(string drawList, LSL_Float x) + { + CheckThreatLevel(); + + drawList += "RotTransf " + x + ";"; + return drawList; + } + + public string osDrawScaleTransform(string drawList, LSL_Float x, LSL_Float y) + { + CheckThreatLevel(); + + drawList += "ScaleTransf " + x + "," + y + ";"; + return drawList; + } + + public string osDrawTranslationTransform(string drawList, LSL_Float x, LSL_Float y) + { + CheckThreatLevel(); + + drawList += "TransTransf " + x + "," + y + ";"; + return drawList; + } + public string osMovePen(string drawList, int x, int y) { - CheckThreatLevel(ThreatLevel.None, "osMovePen"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "MoveTo " + x + "," + y + ";"; return drawList; } public string osDrawLine(string drawList, int startX, int startY, int endX, int endY) { - CheckThreatLevel(ThreatLevel.None, "osDrawLine"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "MoveTo "+ startX+","+ startY +"; LineTo "+endX +","+endY +"; "; return drawList; } public string osDrawLine(string drawList, int endX, int endY) { - CheckThreatLevel(ThreatLevel.None, "osDrawLine"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "LineTo " + endX + "," + endY + "; "; return drawList; } @@ -1169,43 +1231,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.None, "osDrawText"); - m_host.AddScriptLPS(1); drawList += "Text " + text + "; "; return drawList; } public string osDrawEllipse(string drawList, int width, int height) { - CheckThreatLevel(ThreatLevel.None, "osDrawEllipse"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "Ellipse " + width + "," + height + "; "; return drawList; } + public string osDrawFilledEllipse(string drawList, int width, int height) + { + CheckThreatLevel(); + + drawList += "FillEllipse " + width + "," + height + "; "; + return drawList; + } + public string osDrawRectangle(string drawList, int width, int height) { - CheckThreatLevel(ThreatLevel.None, "osDrawRectangle"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "Rectangle " + width + "," + height + "; "; return drawList; } public string osDrawFilledRectangle(string drawList, int width, int height) { - CheckThreatLevel(ThreatLevel.None, "osDrawFilledRectangle"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "FillRectangle " + width + "," + height + "; "; return drawList; } public string osDrawFilledPolygon(string drawList, LSL_List x, LSL_List y) { - CheckThreatLevel(ThreatLevel.None, "osDrawFilledPolygon"); - - m_host.AddScriptLPS(1); + CheckThreatLevel(); if (x.Length != y.Length || x.Length < 3) { @@ -1222,9 +1286,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osDrawPolygon(string drawList, LSL_List x, LSL_List y) { - CheckThreatLevel(ThreatLevel.None, "osDrawPolygon"); - - m_host.AddScriptLPS(1); + CheckThreatLevel(); if (x.Length != y.Length || x.Length < 3) { @@ -1241,36 +1303,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osSetFontSize(string drawList, int fontSize) { - CheckThreatLevel(ThreatLevel.None, "osSetFontSize"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "FontSize "+ fontSize +"; "; return drawList; } public string osSetFontName(string drawList, string fontName) { - CheckThreatLevel(ThreatLevel.None, "osSetFontName"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "FontName "+ fontName +"; "; return drawList; } public string osSetPenSize(string drawList, int penSize) { - CheckThreatLevel(ThreatLevel.None, "osSetPenSize"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "PenSize " + penSize + "; "; return drawList; } public string osSetPenColor(string drawList, string color) { - CheckThreatLevel(ThreatLevel.None, "osSetPenColor"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "PenColor " + color + "; "; return drawList; } @@ -1278,36 +1336,32 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // Deprecated public string osSetPenColour(string drawList, string colour) { - CheckThreatLevel(ThreatLevel.None, "osSetPenColour"); + CheckThreatLevel(); OSSLDeprecated("osSetPenColour", "osSetPenColor"); - m_host.AddScriptLPS(1); drawList += "PenColour " + colour + "; "; return drawList; } public string osSetPenCap(string drawList, string direction, string type) { - CheckThreatLevel(ThreatLevel.None, "osSetPenCap"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList += "PenCap " + direction + "," + type + "; "; return drawList; } public string osDrawImage(string drawList, int width, int height, string imageUrl) { - CheckThreatLevel(ThreatLevel.None, "osDrawImage"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); drawList +="Image " +width + "," + height+ ","+ imageUrl +"; " ; return drawList; } public LSL_Vector osGetDrawStringSize(string contentType, string text, string fontName, int fontSize) { - CheckThreatLevel(ThreatLevel.VeryLow, "osGetDrawStringSize"); - m_host.AddScriptLPS(1); + CheckThreatLevel(); LSL_Vector vec = new LSL_Vector(0,0,0); IDynamicTextureManager textureManager = World.RequestModuleInterface(); @@ -1330,7 +1384,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // should be removed // CheckThreatLevel(ThreatLevel.High, "osSetStateEvents"); - m_host.AddScriptLPS(1); m_host.SetScriptEvents(m_item.ItemID, events); } @@ -1339,8 +1392,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osSetRegionWaterHeight"); - m_host.AddScriptLPS(1); - World.EventManager.TriggerRequestChangeWaterHeight((float)height); } @@ -1354,8 +1405,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osSetRegionSunSettings"); - m_host.AddScriptLPS(1); - while (sunHour > 24.0) sunHour -= 24.0; @@ -1379,8 +1428,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osSetEstateSunSettings"); - m_host.AddScriptLPS(1); - while (sunHour > 24.0) sunHour -= 24.0; @@ -1401,9 +1448,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public double osGetCurrentSunHour() { - CheckThreatLevel(ThreatLevel.None, "osGetCurrentSunHour"); - - m_host.AddScriptLPS(1); + CheckThreatLevel(); // Must adjust for the fact that Region Sun Settings are still LL offset double sunHour = World.RegionInfo.RegionSettings.SunPosition - 6; @@ -1427,14 +1472,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public double osGetSunParam(string param) { - CheckThreatLevel(ThreatLevel.None, "osGetSunParam"); + CheckThreatLevel(); return GetSunParam(param); } private double GetSunParam(string param) { - m_host.AddScriptLPS(1); - double value = 0.0; ISunModule module = World.RequestModuleInterface(); @@ -1461,8 +1504,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api private void SetSunParam(string param, double value) { - m_host.AddScriptLPS(1); - ISunModule module = World.RequestModuleInterface(); if (module != null) { @@ -1473,7 +1514,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osWindActiveModelPluginName() { CheckThreatLevel(ThreatLevel.None, "osWindActiveModelPluginName"); - m_host.AddScriptLPS(1); IWindModule module = World.RequestModuleInterface(); if (module != null) @@ -1487,7 +1527,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osSetWindParam(string plugin, string param, LSL_Float value) { CheckThreatLevel(ThreatLevel.VeryLow, "osSetWindParam"); - m_host.AddScriptLPS(1); IWindModule module = World.RequestModuleInterface(); if (module != null) @@ -1503,7 +1542,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Float osGetWindParam(string plugin, string param) { CheckThreatLevel(ThreatLevel.VeryLow, "osGetWindParam"); - m_host.AddScriptLPS(1); IWindModule module = World.RequestModuleInterface(); if (module != null) @@ -1518,7 +1556,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osParcelJoin(LSL_Vector pos1, LSL_Vector pos2) { CheckThreatLevel(ThreatLevel.High, "osParcelJoin"); - m_host.AddScriptLPS(1); int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x); int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y); @@ -1531,7 +1568,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osParcelSubdivide(LSL_Vector pos1, LSL_Vector pos2) { CheckThreatLevel(ThreatLevel.High, "osParcelSubdivide"); - m_host.AddScriptLPS(1); int startx = (int)(pos1.x < pos2.x ? pos1.x : pos2.x); int starty = (int)(pos1.y < pos2.y ? pos1.y : pos2.y); @@ -1558,8 +1594,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api private void SetParcelDetails(LSL_Vector pos, LSL_List rules, string functionName) { - m_host.AddScriptLPS(1); - // Get a reference to the land data and make sure the owner of the script // can modify it @@ -1572,13 +1606,19 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (!World.Permissions.CanEditParcelProperties(m_host.OwnerID, startLandObject, GroupPowers.LandOptions, false)) { - OSSLShoutError("You do not have permission to modify the parcel"); + OSSLShoutError("script owner does not have permission to modify the parcel"); return; } // Create a new land data object we can modify LandData newLand = startLandObject.LandData.Copy(); UUID uuid; + EstateSettings es = World.RegionInfo.EstateSettings; + + bool changed = false; + bool changedSeeAvs = false; + bool changedoverlay = false; + bool changedneedupdate = false; // Process the rules, not sure what the impact would be of changing owner or group for (int idx = 0; idx < rules.Length;) @@ -1588,35 +1628,151 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api switch (code) { case ScriptBaseClass.PARCEL_DETAILS_NAME: - newLand.Name = arg; + if(newLand.Name != arg) + { + newLand.Name = arg; + changed = true; + } break; case ScriptBaseClass.PARCEL_DETAILS_DESC: - newLand.Description = arg; + if(newLand.Description != arg) + { + newLand.Description = arg; + changed = true; + } break; case ScriptBaseClass.PARCEL_DETAILS_OWNER: - CheckThreatLevel(ThreatLevel.VeryHigh, functionName); - if (UUID.TryParse(arg, out uuid)) - newLand.OwnerID = uuid; + if(es != null && !es.IsEstateManagerOrOwner(m_host.OwnerID)) + { + OSSLError("script owner does not have permission to modify the parcel owner"); + } + else + { + if (UUID.TryParse(arg, out uuid)) + { + if(newLand.OwnerID != uuid) + { + changed = true; + newLand.OwnerID = uuid; + newLand.GroupID = UUID.Zero; + } + } + } break; case ScriptBaseClass.PARCEL_DETAILS_GROUP: - CheckThreatLevel(ThreatLevel.VeryHigh, functionName); - if (UUID.TryParse(arg, out uuid)) - newLand.GroupID = uuid; + if(m_host.OwnerID == newLand.OwnerID || es == null || es.IsEstateManagerOrOwner(m_host.OwnerID)) + { + if (UUID.TryParse(arg, out uuid)) + { + if(newLand.GroupID != uuid) + { + if(uuid == UUID.Zero) + { + changed = true; + newLand.GroupID = uuid; + } + else + { + IGroupsModule groupsModule = m_ScriptEngine.World.RequestModuleInterface(); + GroupMembershipData member = null; + if (groupsModule != null) + member = groupsModule.GetMembershipData(uuid, newLand.OwnerID); + if (member == null) + OSSLError(string.Format("land owner is not member of the new group for parcel")); + else + { + changed = true; + newLand.GroupID = uuid; + } + } + } + } + } + else + { + OSSLError("script owner does not have permission to modify the parcel group"); + } break; case ScriptBaseClass.PARCEL_DETAILS_CLAIMDATE: - CheckThreatLevel(ThreatLevel.VeryHigh, functionName); - newLand.ClaimDate = Convert.ToInt32(arg); - if (newLand.ClaimDate == 0) - newLand.ClaimDate = Util.UnixTimeSinceEpoch(); + if(es != null && !es.IsEstateManagerOrOwner(m_host.OwnerID)) + { + OSSLError("script owner does not have permission to modify the parcel CLAIM DATE"); + } + else + { + int date = Convert.ToInt32(arg); + if (date == 0) + date = Util.UnixTimeSinceEpoch(); + if(newLand.ClaimDate != date) + { + changed = true; + newLand.ClaimDate = date; + } + } break; - } - } - World.LandChannel.UpdateLandObject(newLand.LocalID,newLand); + case ScriptBaseClass.PARCEL_DETAILS_SEE_AVATARS: + bool newavs = (Convert.ToInt32(arg) != 0); + if(newLand.SeeAVs != newavs) + { + changed = true; + changedSeeAvs = true; + changedoverlay = true; + changedneedupdate = true; + newLand.SeeAVs = newavs; + } + break; + + case ScriptBaseClass.PARCEL_DETAILS_ANY_AVATAR_SOUNDS: + bool newavsounds = (Convert.ToInt32(arg) != 0); + if(newLand.AnyAVSounds != newavsounds) + { + changed = true; + newLand.AnyAVSounds = newavsounds; + } + break; + + case ScriptBaseClass.PARCEL_DETAILS_GROUP_SOUNDS: + bool newgrpsounds = (Convert.ToInt32(arg) != 0); + if(newLand.GroupAVSounds != newgrpsounds) + { + changed = true; + newLand.GroupAVSounds = newgrpsounds; + } + break; + } + } + if(changed) + { + World.LandChannel.UpdateLandObject(newLand.LocalID, newLand); + + if(changedneedupdate) + { + UUID parcelID= newLand.GlobalID; + World.ForEachRootScenePresence(delegate (ScenePresence avatar) + { + if (avatar == null || avatar.IsDeleted || avatar.IsInTransit) + return; + + if(changedSeeAvs && avatar.currentParcelUUID == parcelID ) + avatar.currentParcelUUID = parcelID; // force parcel flags review + + if(avatar.ControllingClient == null) + return; + + // this will be needed for some things like damage etc +// if(avatar.currentParcelUUID == parcelID) +// startLandObject.SendLandUpdateToClient(avatar.ControllingClient); + + if(changedoverlay && !avatar.IsNPC) + World.LandChannel.SendParcelsOverlay(avatar.ControllingClient); + }); + } + } } public double osList2Double(LSL_Types.list src, int index) @@ -1626,9 +1782,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // is not allowed to contain any. // This really should be removed. // - CheckThreatLevel(ThreatLevel.None, "osList2Double"); + CheckThreatLevel(); - m_host.AddScriptLPS(1); if (index < 0) { index = src.Length + index; @@ -1646,8 +1801,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelMediaURL"); - m_host.AddScriptLPS(1); - ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); if (land.LandData.OwnerID != m_host.OwnerID) @@ -1662,8 +1815,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.VeryLow, "osSetParcelSIPAddress"); - m_host.AddScriptLPS(1); - ILandObject land = World.LandChannel.GetLandObject(m_host.AbsolutePosition); if (land.LandData.OwnerID != m_host.OwnerID) @@ -1690,8 +1841,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // CheckThreatLevel(ThreatLevel.High, "osGetScriptEngineName"); - m_host.AddScriptLPS(1); - int scriptEngineNameIndex = 0; if (!String.IsNullOrEmpty(m_ScriptEngine.ScriptEngineName)) @@ -1716,7 +1865,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer osCheckODE() { - m_host.AddScriptLPS(1); + CheckThreatLevel(); + LSL_Integer ret = 0; // false if (m_ScriptEngine.World.PhysicsScene != null) { @@ -1739,6 +1889,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // about the physics engine, this function returns an empty string if // the user does not have permission to see it. This as opposed to // throwing an exception. + m_host.AddScriptLPS(1); string ret = String.Empty; if (String.IsNullOrEmpty(CheckThreatLevelTest(ThreatLevel.High, "osGetPhysicsEngineType"))) @@ -1757,10 +1908,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetPhysicsEngineName() { - // not doing security checks - // this whould limit the use of this + CheckThreatLevel(); - m_host.AddScriptLPS(1); string ret = "NoEngine"; if (m_ScriptEngine.World.PhysicsScene != null) { @@ -1771,6 +1920,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } return ret; } + public string osGetSimulatorVersion() { // High because it can be used to target attacks to known weaknesses @@ -1779,7 +1929,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // kiddie) // CheckThreatLevel(ThreatLevel.High,"osGetSimulatorVersion"); - m_host.AddScriptLPS(1); return m_ScriptEngine.World.GetSimulatorVersion(); } @@ -1825,8 +1974,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.None, "osParseJSONNew"); - m_host.AddScriptLPS(1); - try { OSD decoded = OSDParser.DeserializeJson(JSON); @@ -1843,8 +1990,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.None, "osParseJSON"); - m_host.AddScriptLPS(1); - Object decoded = osParseJSONNew(JSON); if ( decoded is Hashtable ) { @@ -1875,7 +2020,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osMessageObject(LSL_Key objectUUID, string message) { CheckThreatLevel(ThreatLevel.Low, "osMessageObject"); - m_host.AddScriptLPS(1); UUID objUUID; if (!UUID.TryParse(objectUUID, out objUUID)) // prior to patching, a thrown exception regarding invalid GUID format would be shouted instead. @@ -1916,7 +2060,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // if this is restricted to objects rezzed by this host level can be reduced CheckThreatLevel(ThreatLevel.Low, "osDie"); - m_host.AddScriptLPS(1); UUID objUUID; if (!UUID.TryParse(objectUUID, out objUUID)) @@ -1966,7 +2109,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osMakeNotecard(string notecardName, LSL_Types.list contents) { CheckThreatLevel(ThreatLevel.High, "osMakeNotecard"); - m_host.AddScriptLPS(1); StringBuilder notecardData = new StringBuilder(); @@ -2038,6 +2180,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.Inventory.AddInventoryItemExclusive(taskItem, false); else m_host.Inventory.AddInventoryItem(taskItem, false); + m_host.ParentGroup.InvalidateDeepEffectivePerms(); return taskItem; } @@ -2151,7 +2294,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetNotecardLine(string name, int line) { CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNotecardLine"); - m_host.AddScriptLPS(1); UUID assetID = CacheNotecard(name); @@ -2179,7 +2321,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetNotecard(string name) { CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNotecard"); - m_host.AddScriptLPS(1); string text = LoadNotecard(name); @@ -2209,7 +2350,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public int osGetNumberOfNotecardLines(string name) { CheckThreatLevel(ThreatLevel.VeryHigh, "osGetNumberOfNotecardLines"); - m_host.AddScriptLPS(1); UUID assetID = CacheNotecard(name); @@ -2225,7 +2365,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osAvatarName2Key(string firstname, string lastname) { CheckThreatLevel(ThreatLevel.Low, "osAvatarName2Key"); - m_host.AddScriptLPS(1); IUserManagement userManager = World.RequestModuleInterface(); if (userManager == null) @@ -2277,7 +2416,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osKey2Name(string id) { CheckThreatLevel(ThreatLevel.Low, "osKey2Name"); - m_host.AddScriptLPS(1); UUID key = new UUID(); @@ -2387,7 +2525,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetGridNick() { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridNick"); - m_host.AddScriptLPS(1); string nick = String.Empty; IConfigSource config = m_ScriptEngine.ConfigSource; @@ -2404,7 +2541,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetGridName() { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridName"); - m_host.AddScriptLPS(1); string name = String.Empty; IConfigSource config = m_ScriptEngine.ConfigSource; @@ -2421,7 +2557,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetGridLoginURI() { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridLoginURI"); - m_host.AddScriptLPS(1); string loginURI = String.Empty; IConfigSource config = m_ScriptEngine.ConfigSource; @@ -2438,7 +2573,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetGridHomeURI() { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridHomeURI"); - m_host.AddScriptLPS(1); IConfigSource config = m_ScriptEngine.ConfigSource; string HomeURI = Util.GetConfigVarFromSections(config, "HomeURI", @@ -2460,7 +2594,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetGridGatekeeperURI() { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridGatekeeperURI"); - m_host.AddScriptLPS(1); IConfigSource config = m_ScriptEngine.ConfigSource; string gatekeeperURI = Util.GetConfigVarFromSections(config, "GatekeeperURI", @@ -2479,7 +2612,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetGridCustom(string key) { CheckThreatLevel(ThreatLevel.Moderate, "osGetGridCustom"); - m_host.AddScriptLPS(1); string retval = String.Empty; IConfigSource config = m_ScriptEngine.ConfigSource; @@ -2496,7 +2628,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osGetAvatarHomeURI(string uuid) { CheckThreatLevel(ThreatLevel.Low, "osGetAvatarHomeURI"); - m_host.AddScriptLPS(1); IUserManagement userManager = m_ScriptEngine.World.RequestModuleInterface(); string returnValue = ""; @@ -2529,7 +2660,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osFormatString(string str, LSL_List strings) { CheckThreatLevel(ThreatLevel.VeryLow, "osFormatString"); - m_host.AddScriptLPS(1); return String.Format(str, strings.Data); } @@ -2537,7 +2667,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List osMatchString(string src, string pattern, int start) { CheckThreatLevel(ThreatLevel.VeryLow, "osMatchString"); - m_host.AddScriptLPS(1); LSL_List result = new LSL_List(); @@ -2579,7 +2708,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osReplaceString(string src, string pattern, string replace, int count, int start) { CheckThreatLevel(ThreatLevel.VeryLow, "osReplaceString"); - m_host.AddScriptLPS(1); // Normalize indices (if negative). // After normlaization they may still be @@ -2604,7 +2732,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osLoadedCreationDate() { CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationDate"); - m_host.AddScriptLPS(1); return World.RegionInfo.RegionSettings.LoadedCreationDate; } @@ -2612,7 +2739,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osLoadedCreationTime() { CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationTime"); - m_host.AddScriptLPS(1); return World.RegionInfo.RegionSettings.LoadedCreationTime; } @@ -2620,7 +2746,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public string osLoadedCreationID() { CheckThreatLevel(ThreatLevel.Low, "osLoadedCreationID"); - m_host.AddScriptLPS(1); return World.RegionInfo.RegionSettings.LoadedCreationID; } @@ -2641,7 +2766,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List osGetLinkPrimitiveParams(int linknumber, LSL_List rules) { 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. @@ -2670,8 +2795,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryLow, "osForceCreateLink"); - m_host.AddScriptLPS(1); - InitLSL(); ((LSL_Api)m_LSL_Api).CreateLink(target, parent); } @@ -2680,8 +2803,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryLow, "osForceBreakLink"); - m_host.AddScriptLPS(1); - InitLSL(); ((LSL_Api)m_LSL_Api).BreakLink(linknum); } @@ -2690,16 +2811,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryLow, "osForceBreakAllLinks"); - m_host.AddScriptLPS(1); - InitLSL(); ((LSL_Api)m_LSL_Api).BreakAllLinks(); } public LSL_Integer osIsNpc(LSL_Key npc) { - CheckThreatLevel(ThreatLevel.None, "osIsNpc"); - m_host.AddScriptLPS(1); + CheckThreatLevel(); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -2716,7 +2834,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard) { CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); - m_host.AddScriptLPS(1); // have to get the npc module also here to set the default Not Owned INPCModule module = World.RequestModuleInterface(); @@ -2731,7 +2848,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osNpcCreate(string firstname, string lastname, LSL_Vector position, string notecard, int options) { CheckThreatLevel(ThreatLevel.High, "osNpcCreate"); - m_host.AddScriptLPS(1); return NpcCreate( firstname, lastname, position, notecard, @@ -2874,7 +2990,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osNpcSaveAppearance(LSL_Key npc, string notecard) { CheckThreatLevel(ThreatLevel.High, "osNpcSaveAppearance"); - m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); @@ -2896,7 +3011,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcLoadAppearance(LSL_Key npc, string notecard) { CheckThreatLevel(ThreatLevel.High, "osNpcLoadAppearance"); - m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); @@ -2928,7 +3042,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osNpcGetOwner(LSL_Key npc) { CheckThreatLevel(ThreatLevel.None, "osNpcGetOwner"); - m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); if (npcModule != null) @@ -2950,7 +3063,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector osNpcGetPos(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcGetPos"); - m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); if (npcModule != null) @@ -2974,7 +3086,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcMoveTo(LSL_Key npc, LSL_Vector pos) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveTo"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -2993,7 +3104,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcMoveToTarget(LSL_Key npc, LSL_Vector target, int options) { CheckThreatLevel(ThreatLevel.High, "osNpcMoveToTarget"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3018,7 +3128,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Rotation osNpcGetRot(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcGetRot"); - m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); if (npcModule != null) @@ -3042,7 +3151,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcSetRot(LSL_Key npc, LSL_Rotation rotation) { CheckThreatLevel(ThreatLevel.High, "osNpcSetRot"); - m_host.AddScriptLPS(1); INPCModule npcModule = World.RequestModuleInterface(); if (npcModule != null) @@ -3064,7 +3172,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcStopMoveToTarget(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcStopMoveToTarget"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3081,7 +3188,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcSetProfileAbout(LSL_Key npc, string about) { CheckThreatLevel(ThreatLevel.Low, "osNpcSetProfileAbout"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3100,7 +3206,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcSetProfileImage(LSL_Key npc, string image) { CheckThreatLevel(ThreatLevel.Low, "osNpcSetProfileImage"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3134,7 +3239,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcSay(LSL_Key npc, int channel, string message) { CheckThreatLevel(ThreatLevel.High, "osNpcSay"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3151,7 +3255,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcShout(LSL_Key npc, int channel, string message) { CheckThreatLevel(ThreatLevel.High, "osNpcShout"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3168,7 +3271,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcSit(LSL_Key npc, LSL_Key target, int options) { CheckThreatLevel(ThreatLevel.High, "osNpcSit"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3185,7 +3287,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcStand(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcStand"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3202,7 +3303,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcRemove(LSL_Key npc) { CheckThreatLevel(ThreatLevel.High, "osNpcRemove"); - m_host.AddScriptLPS(1); try { @@ -3223,7 +3323,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcPlayAnimation(LSL_Key npc, string animation) { CheckThreatLevel(ThreatLevel.High, "osNpcPlayAnimation"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3238,7 +3337,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcStopAnimation(LSL_Key npc, string animation) { CheckThreatLevel(ThreatLevel.High, "osNpcStopAnimation"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3253,7 +3351,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcWhisper(LSL_Key npc, int channel, string message) { CheckThreatLevel(ThreatLevel.High, "osNpcWhisper"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); if (module != null) @@ -3270,7 +3367,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osNpcTouch(LSL_Key npcLSL_Key, LSL_Key object_key, LSL_Integer link_num) { CheckThreatLevel(ThreatLevel.High, "osNpcTouch"); - m_host.AddScriptLPS(1); INPCModule module = World.RequestModuleInterface(); int linkNum = link_num.value; @@ -3315,7 +3411,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osOwnerSaveAppearance(string notecard) { CheckThreatLevel(ThreatLevel.High, "osOwnerSaveAppearance"); - m_host.AddScriptLPS(1); return SaveAppearanceToNotecard(m_host.OwnerID, notecard); } @@ -3323,7 +3418,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osAgentSaveAppearance(LSL_Key avatarId, string notecard) { CheckThreatLevel(ThreatLevel.VeryHigh, "osAgentSaveAppearance"); - m_host.AddScriptLPS(1); return SaveAppearanceToNotecard(avatarId, notecard); } @@ -3376,7 +3470,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osGetGender(LSL_Key rawAvatarId) { CheckThreatLevel(ThreatLevel.None, "osGetGender"); - m_host.AddScriptLPS(1); UUID avatarId; if (!UUID.TryParse(rawAvatarId, out avatarId)) @@ -3419,8 +3512,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public LSL_Key osGetMapTexture() { - CheckThreatLevel(ThreatLevel.None, "osGetMapTexture"); - m_host.AddScriptLPS(1); + CheckThreatLevel(); return m_ScriptEngine.World.RegionInfo.RegionSettings.TerrainImageID.ToString(); } @@ -3433,7 +3525,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osGetRegionMapTexture(string regionName) { CheckThreatLevel(ThreatLevel.High, "osGetRegionMapTexture"); - m_host.AddScriptLPS(1); Scene scene = m_ScriptEngine.World; UUID key = UUID.Zero; @@ -3464,7 +3555,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List osGetRegionStats() { CheckThreatLevel(ThreatLevel.Moderate, "osGetRegionStats"); - m_host.AddScriptLPS(1); + LSL_List ret = new LSL_List(); float[] stats = World.StatsReporter.LastReportedSimStats; @@ -3477,8 +3568,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector osGetRegionSize() { - CheckThreatLevel(ThreatLevel.None, "osGetRegionSize"); - m_host.AddScriptLPS(1); + CheckThreatLevel(); Scene scene = m_ScriptEngine.World; RegionInfo reg = World.RegionInfo; @@ -3490,7 +3580,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public int osGetSimulatorMemory() { CheckThreatLevel(ThreatLevel.Moderate, "osGetSimulatorMemory"); - m_host.AddScriptLPS(1); + long pws = System.Diagnostics.Process.GetCurrentProcess().WorkingSet64; if (pws > Int32.MaxValue) @@ -3504,7 +3594,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osSetSpeed(string UUID, LSL_Float SpeedModifier) { CheckThreatLevel(ThreatLevel.Moderate, "osSetSpeed"); - m_host.AddScriptLPS(1); + ScenePresence avatar = World.GetScenePresence(new UUID(UUID)); if (avatar != null) @@ -3514,7 +3604,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osKickAvatar(string FirstName, string SurName, string alert) { CheckThreatLevel(ThreatLevel.Severe, "osKickAvatar"); - m_host.AddScriptLPS(1); World.ForEachRootScenePresence(delegate(ScenePresence sp) { @@ -3533,18 +3622,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api 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; + if (presence != null) + health = presence.Health; return health; } public void osCauseDamage(string avatar, double damage) { CheckThreatLevel(ThreatLevel.High, "osCauseDamage"); - m_host.AddScriptLPS(1); UUID avatarId = new UUID(avatar); Vector3 pos = m_host.GetWorldPosition(); @@ -3572,12 +3660,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osCauseHealing(string avatar, double healing) { CheckThreatLevel(ThreatLevel.High, "osCauseHealing"); - m_host.AddScriptLPS(1); UUID avatarId = new UUID(avatar); ScenePresence presence = World.GetScenePresence(avatarId); - if (presence != null && World.ScriptDanger(m_host.LocalId, m_host.GetWorldPosition())) + if (presence != null) { float health = presence.Health; health += (float)healing; @@ -3592,12 +3679,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osSetHealth(string avatar, double health) { CheckThreatLevel(ThreatLevel.High, "osSetHealth"); - m_host.AddScriptLPS(1); UUID avatarId = new UUID(avatar); ScenePresence presence = World.GetScenePresence(avatarId); - if (presence != null && World.ScriptDanger(m_host.LocalId, m_host.GetWorldPosition())) + if (presence != null) { if (health > 100.0) health = 100.0; @@ -3611,19 +3697,17 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osSetHealRate(string avatar, double healrate) { CheckThreatLevel(ThreatLevel.High, "osSetHealRate"); - m_host.AddScriptLPS(1); UUID avatarId = new UUID(avatar); ScenePresence presence = World.GetScenePresence(avatarId); - if (presence != null && World.ScriptDanger(m_host.LocalId, m_host.GetWorldPosition())) + if (presence != null) presence.HealRate = (float)healrate; } public LSL_Float osGetHealRate(string avatar) { CheckThreatLevel(ThreatLevel.None, "osGetHealRate"); - m_host.AddScriptLPS(1); LSL_Float rate = new LSL_Float(0); ScenePresence presence = World.GetScenePresence(new UUID(avatar)); @@ -3635,18 +3719,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) { CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); - m_host.AddScriptLPS(1); - InitLSL(); + InitLSL(); return m_LSL_Api.GetPrimitiveParamsEx(prim, rules); } public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) { CheckThreatLevel(ThreatLevel.High, "osSetPrimitiveParams"); - m_host.AddScriptLPS(1); - InitLSL(); + InitLSL(); m_LSL_Api.SetPrimitiveParamsEx(prim, rules, "osSetPrimitiveParams"); } @@ -3655,8 +3737,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public void osSetProjectionParams(bool projection, LSL_Key texture, double fov, double focus, double amb) { - CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams"); - osSetProjectionParams(UUID.Zero.ToString(), projection, texture, fov, focus, amb); } @@ -3666,7 +3746,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb) { CheckThreatLevel(ThreatLevel.High, "osSetProjectionParams"); - m_host.AddScriptLPS(1); SceneObjectPart obj = null; if (prim == UUID.Zero.ToString()) @@ -3697,12 +3776,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_List osGetAvatarList() { CheckThreatLevel(ThreatLevel.None, "osGetAvatarList"); - m_host.AddScriptLPS(1); LSL_List result = new LSL_List(); World.ForEachRootScenePresence(delegate (ScenePresence avatar) { - if (avatar != null && avatar.UUID != m_host.OwnerID) + if (avatar != null && !avatar.IsDeleted && avatar.UUID != m_host.OwnerID ) + { + result.Add(new LSL_String(avatar.UUID.ToString())); + result.Add(new LSL_Vector(avatar.AbsolutePosition)); + result.Add(new LSL_String(avatar.Name)); + } + }); + + return result; + } + + public LSL_List osGetNPCList() + { + CheckThreatLevel(ThreatLevel.None, "osGetNPCList"); + + LSL_List result = new LSL_List(); + World.ForEachRootScenePresence(delegate (ScenePresence avatar) + { + // npcs are not childagents but that is now. + if (avatar != null && avatar.IsNPC && !avatar.IsDeleted && !avatar.IsChildAgent && !avatar.IsInTransit) { result.Add(new LSL_String(avatar.UUID.ToString())); result.Add(new LSL_Vector(avatar.AbsolutePosition)); @@ -3721,7 +3818,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osUnixTimeToTimestamp(long time) { CheckThreatLevel(ThreatLevel.VeryLow, "osUnixTimeToTimestamp"); - m_host.AddScriptLPS(1); long baseTicks = 621355968000000000; long tickResolution = 10000000; @@ -3738,7 +3834,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Item description public LSL_String osGetInventoryDesc(string item) { - m_host.AddScriptLPS(1); + CheckThreatLevel(); lock (m_host.TaskInventory) { @@ -3762,7 +3858,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer osInviteToGroup(LSL_Key agentId) { CheckThreatLevel(ThreatLevel.VeryLow, "osInviteToGroup"); - m_host.AddScriptLPS(1); UUID agent = new UUID(agentId); @@ -3797,7 +3892,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer osEjectFromGroup(LSL_Key agentId) { CheckThreatLevel(ThreatLevel.VeryLow, "osEjectFromGroup"); - m_host.AddScriptLPS(1); UUID agent = new UUID(agentId); @@ -3833,7 +3927,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osSetTerrainTexture"); - m_host.AddScriptLPS(1); //Check to make sure that the script's owner is the estate manager/master //World.Permissions.GenericEstatePermission( if (World.Permissions.IsGod(m_host.OwnerID)) @@ -3863,7 +3956,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osSetTerrainTextureHeight"); - m_host.AddScriptLPS(1); //Check to make sure that the script's owner is the estate manager/master //World.Permissions.GenericEstatePermission( if (World.Permissions.IsGod(m_host.OwnerID)) @@ -3884,8 +3976,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatar"); - m_host.AddScriptLPS(1); - InitLSL(); ((LSL_Api)m_LSL_Api).AttachToAvatar(attachmentPoint); } @@ -3894,8 +3984,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osForceAttachToAvatarFromInventory"); - m_host.AddScriptLPS(1); - ForceAttachToAvatarFromInventory(m_host.OwnerID, itemName, attachmentPoint); } @@ -3903,8 +3991,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.VeryHigh, "osForceAttachToOtherAvatarFromInventory"); - m_host.AddScriptLPS(1); - UUID avatarId; if (!UUID.TryParse(rawAvatarId, out avatarId)) @@ -3964,8 +4050,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.High, "osForceDetachFromAvatar"); - m_host.AddScriptLPS(1); - InitLSL(); ((LSL_Api)m_LSL_Api).DetachFromAvatar(); } @@ -3974,8 +4058,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { CheckThreatLevel(ThreatLevel.Moderate, "osGetNumberOfAttachments"); - m_host.AddScriptLPS(1); - UUID targetUUID; ScenePresence target; LSL_List resp = new LSL_List(); @@ -4009,7 +4091,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osMessageAttachments(LSL_Key avatar, string message, LSL_List attachmentPoints, int options) { CheckThreatLevel(ThreatLevel.Moderate, "osMessageAttachments"); - m_host.AddScriptLPS(1); UUID targetUUID; if(!UUID.TryParse(avatar.ToString(), out targetUUID)) @@ -4118,8 +4199,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// 1 if thing is a valid UUID, 0 otherwise public LSL_Integer osIsUUID(string thing) { - CheckThreatLevel(ThreatLevel.None, "osIsUUID"); - m_host.AddScriptLPS(1); + CheckThreatLevel(); UUID test; return UUID.TryParse(thing, out test) ? 1 : 0; @@ -4133,8 +4213,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public LSL_Float osMin(double a, double b) { - CheckThreatLevel(ThreatLevel.None, "osMin"); - m_host.AddScriptLPS(1); + CheckThreatLevel(); return Math.Min(a, b); } @@ -4147,8 +4226,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// public LSL_Float osMax(double a, double b) { - CheckThreatLevel(ThreatLevel.None, "osMax"); - m_host.AddScriptLPS(1); + CheckThreatLevel(); return Math.Max(a, b); } @@ -4156,7 +4234,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Key osGetRezzingObject() { CheckThreatLevel(ThreatLevel.None, "osGetRezzingObject"); - m_host.AddScriptLPS(1); + UUID rezID = m_host.ParentGroup.RezzerID; if(rezID == UUID.Zero || m_host.ParentGroup.Scene.GetScenePresence(rezID) != null) return new LSL_Key(UUID.Zero.ToString()); @@ -4181,7 +4259,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// 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) { @@ -4232,7 +4309,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osDropAttachment() { CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachment"); - m_host.AddScriptLPS(1); DropAttachment(true); } @@ -4240,7 +4316,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osForceDropAttachment() { CheckThreatLevel(ThreatLevel.High, "osForceDropAttachment"); - m_host.AddScriptLPS(1); DropAttachment(false); } @@ -4248,7 +4323,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) { CheckThreatLevel(ThreatLevel.Moderate, "osDropAttachmentAt"); - m_host.AddScriptLPS(1); DropAttachmentAt(true, pos, rot); } @@ -4256,7 +4330,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osForceDropAttachmentAt(LSL_Vector pos, LSL_Rotation rot) { CheckThreatLevel(ThreatLevel.High, "osForceDropAttachmentAt"); - m_host.AddScriptLPS(1); DropAttachmentAt(false, pos, rot); } @@ -4264,7 +4337,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api 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); @@ -4312,7 +4385,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Integer osRegexIsMatch(string input, string pattern) { CheckThreatLevel(ThreatLevel.Low, "osRegexIsMatch"); - m_host.AddScriptLPS(1); + try { return Regex.IsMatch(input, pattern) ? 1 : 0; @@ -4327,7 +4400,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osRequestURL(LSL_List options) { CheckThreatLevel(ThreatLevel.Moderate, "osRequestSecureURL"); - m_host.AddScriptLPS(1); Hashtable opts = new Hashtable(); for (int i = 0 ; i < options.Length ; i++) @@ -4345,7 +4417,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_String osRequestSecureURL(LSL_List options) { CheckThreatLevel(ThreatLevel.Moderate, "osRequestSecureURL"); - m_host.AddScriptLPS(1); Hashtable opts = new Hashtable(); for (int i = 0 ; i < options.Length ; i++) @@ -4362,7 +4433,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public void osCollisionSound(string impact_sound, double impact_volume) { - m_host.AddScriptLPS(1); + CheckThreatLevel(); if(impact_sound == "") { @@ -4394,7 +4465,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // still not very usefull, detector is lost on rez, restarts, etc public void osVolumeDetect(int detect) { - m_host.AddScriptLPS(1); + CheckThreatLevel(); if (m_host.ParentGroup == null || m_host.ParentGroup.IsDeleted || m_host.ParentGroup.IsAttachment) return; @@ -4402,5 +4473,315 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_host.ScriptSetVolumeDetect(detect != 0); } + /// + /// Get inertial data + /// + /// + /// + /// + /// a LSL list with contents: + /// LSL_Float mass, the total mass of a linkset + /// LSL_Vector CenterOfMass, center mass relative to root prim + /// LSL_Vector Inertia, elements of diagonal of inertia Ixx,Iyy,Izz divided by total mass + /// LSL_Vector aux, elements of upper triagle of inertia Ixy (= Iyx), Ixz (= Izx), Iyz(= Izy) divided by total mass + /// + public LSL_List osGetInertiaData() + { + CheckThreatLevel(); + + LSL_List result = new LSL_List(); + float TotalMass; + Vector3 CenterOfMass; + Vector3 Inertia; + Vector4 aux; + + SceneObjectGroup sog = m_host.ParentGroup; + if(sog== null || sog.IsDeleted) + return result; + + sog.GetInertiaData(out TotalMass, out CenterOfMass, out Inertia, out aux ); + if(TotalMass > 0) + { + float t = 1.0f/TotalMass; + Inertia.X *= t; + Inertia.Y *= t; + Inertia.Z *= t; + + aux.X *= t; + aux.Y *= t; + aux.Z *= t; + } + + result.Add(new LSL_Float(TotalMass)); + result.Add(new LSL_Vector(CenterOfMass.X, CenterOfMass.Y, CenterOfMass.Z)); + result.Add(new LSL_Vector(Inertia.X, Inertia.Y, Inertia.Z)); + result.Add(new LSL_Vector(aux.X, aux.Y, aux.Z)); + return result; + } + + /// + /// set inertial data + /// replaces the automatic calculation of mass, center of mass and inertia + /// + /// + /// total mass of linkset + /// location of center of mass relative to root prim in local coords + /// moment of inertia relative to principal axis and center of mass,Ixx, Iyy, Izz divided by mass + /// rotation of the inertia, relative to local axis + /// + /// the inertia argument is is inertia divided by mass, so corresponds only to the geometric distribution of mass and both can be changed independently. + /// + + public void osSetInertia(LSL_Float mass, LSL_Vector centerOfMass, LSL_Vector principalInertiaScaled, LSL_Rotation lslrot) + { + CheckThreatLevel(); + + SceneObjectGroup sog = m_host.ParentGroup; + if(sog== null || sog.IsDeleted) + return; + + if(mass < 0 || principalInertiaScaled.x < 0 || principalInertiaScaled.y < 0 || principalInertiaScaled.z < 0) + return; + + // need more checks + + Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z); + Vector3 Inertia; + float m = (float)mass; + + Inertia.X = m * (float)principalInertiaScaled.x; + Inertia.Y = m * (float)principalInertiaScaled.y; + Inertia.Z = m * (float)principalInertiaScaled.z; + + Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.y, (float)lslrot.s); + rot.Normalize(); + + sog.SetInertiaData(m, CenterOfMass, Inertia, rot ); + } + + /// + /// set inertial data as a sphere + /// replaces the automatic calculation of mass, center of mass and inertia + /// + /// + /// total mass of linkset + /// size of the Box + /// location of center of mass relative to root prim in local coords + /// rotation of the box, and so inertia, relative to local axis + /// + /// + public void osSetInertiaAsBox(LSL_Float mass, LSL_Vector boxSize, LSL_Vector centerOfMass, LSL_Rotation lslrot) + { + CheckThreatLevel(); + + SceneObjectGroup sog = m_host.ParentGroup; + if(sog== null || sog.IsDeleted) + return; + + if(mass < 0) + return; + + // need more checks + + Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z); + Vector3 Inertia; + float lx = (float)boxSize.x; + float ly = (float)boxSize.y; + float lz = (float)boxSize.z; + float m = (float)mass; + float t = m / 12.0f; + + Inertia.X = t * (ly*ly + lz*lz); + Inertia.Y = t * (lx*lx + lz*lz); + Inertia.Z = t * (lx*lx + ly*ly); + + Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.z, (float)lslrot.s); + rot.Normalize(); + + sog.SetInertiaData(m, CenterOfMass, Inertia, rot ); + } + + /// + /// set inertial data as a sphere + /// replaces the automatic calculation of mass, center of mass and inertia + /// + /// + /// total mass of linkset + /// radius of the sphere + /// location of center of mass relative to root prim in local coords + /// + /// + public void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, LSL_Vector centerOfMass) + { + CheckThreatLevel(); + + SceneObjectGroup sog = m_host.ParentGroup; + if(sog== null || sog.IsDeleted) + return; + + if(mass < 0) + return; + + // need more checks + + Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z); + Vector3 Inertia; + float r = (float)radius; + float m = (float)mass; + float t = 0.4f * m * r * r; + + Inertia.X = t; + Inertia.Y = t; + Inertia.Z = t; + + sog.SetInertiaData(m, CenterOfMass, Inertia, new Vector4(0f, 0f, 0f,1.0f)); + } + + /// + /// set inertial data as a cylinder + /// replaces the automatic calculation of mass, center of mass and inertia + /// + /// + /// total mass of linkset + /// radius of the cylinder + /// lenght of the cylinder + /// location of center of mass relative to root prim in local coords + /// rotation of the cylinder, and so inertia, relative to local axis + /// + /// cylinder axis aligned with Z axis. For other orientations provide the rotation. + /// + public void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, LSL_Vector centerOfMass, LSL_Rotation lslrot) + { + CheckThreatLevel(); + + SceneObjectGroup sog = m_host.ParentGroup; + if(sog== null || sog.IsDeleted) + return; + + if(mass < 0) + return; + + // need more checks + + Vector3 CenterOfMass = new Vector3((float)centerOfMass.x,(float)centerOfMass.y,(float)centerOfMass.z); + Vector3 Inertia; + float m = (float)mass; + float r = (float)radius; + r *= r; + Inertia.Z = 0.5f * m * r; + float t = (float)lenght; + t *= t; + t += 3.0f * r; + t *= 8.333333e-2f * m; + + Inertia.X = t; + Inertia.Y = t; + + Vector4 rot = new Vector4((float)lslrot.x, (float)lslrot.y, (float)lslrot.z, (float)lslrot.s); + rot.Normalize(); + + sog.SetInertiaData(m, CenterOfMass, Inertia, rot); + } + + /// + /// removes inertial data manual override + /// default automatic calculation is used again + /// + /// + public void osClearInertia() + { + CheckThreatLevel(); + + SceneObjectGroup sog = m_host.ParentGroup; + if(sog== null || sog.IsDeleted) + return; + + sog.SetInertiaData(-1, Vector3.Zero, Vector3.Zero, Vector4.Zero ); + } + + private bool checkAllowObjectTPbyLandOwner(Vector3 pos) + { + ILandObject land = World.LandChannel.GetLandObject(pos); + if(land == null) + return true; + + LandData landdata = land.LandData; + if(landdata == null) + return true; + + UUID hostOwner = m_host.OwnerID; + if(landdata.OwnerID == hostOwner) + return true; + + EstateSettings es = World.RegionInfo.EstateSettings; + if(es != null && es.IsEstateManagerOrOwner(hostOwner)) + return true; + + if(!landdata.IsGroupOwned) + return false; + + UUID landGroup = landdata.GroupID; + if(landGroup == UUID.Zero) + return false; + + if(landGroup == m_host.GroupID) + return true; + + return false; + } + + /// + /// teleports a object (full linkset) + /// + /// the id of the linkset to teleport + /// target position + /// a rotation to apply + /// several flags/param> + /// + /// only does teleport local to region + /// if object has scripts, owner must have rights to run scripts on target location + /// object owner must have rights to enter ojects on target location + /// target location parcel must have enought free prims capacity for the linkset prims + /// all avatars siting on the object must have access to target location + /// has a cool down time. retries before expire reset it + /// fail conditions are silent ignored + /// + public LSL_Integer osTeleportObject(LSL_Key objectUUID, LSL_Vector targetPos, LSL_Rotation rotation, LSL_Integer flags) + { + CheckThreatLevel(ThreatLevel.Severe, "osTeleportObject"); + + UUID objUUID; + if (!UUID.TryParse(objectUUID, out objUUID)) + { + OSSLShoutError("osTeleportObject() invalid object Key"); + return -1; + } + + SceneObjectGroup sog = World.GetSceneObjectGroup(objUUID); + if(sog== null || sog.IsDeleted || sog.inTransit) + return -1; + + if(sog.OwnerID != m_host.OwnerID) + { + Vector3 pos = sog.AbsolutePosition; + if(!checkAllowObjectTPbyLandOwner(pos)) + return -1; + } + + UUID myid = m_host.ParentGroup.UUID; + + return sog.TeleportObject(myid, targetPos, rotation, flags); + // a delay here may break vehicles + } + + public LSL_Integer osGetLinkNumber(LSL_String name) + { + CheckThreatLevel(); + + SceneObjectGroup sog = m_host.ParentGroup; + if(sog== null || sog.IsDeleted) + return -1; + return sog.GetLinkNumber(name); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs index 1808c34507..cc98bbb711 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/Plugins/SensorRepeat.cs @@ -160,7 +160,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins ts.arc = arc; ts.host = host; - ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + ts.next = DateTime.UtcNow.AddSeconds(ts.interval); AddSenseRepeater(ts); } @@ -196,14 +196,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Plugins public void CheckSenseRepeaterEvents() { // Go through all timers - foreach (SensorInfo ts in SenseRepeaters) + + List curSensors; + lock(SenseRepeatListLock) + curSensors = SenseRepeaters; + + DateTime now = DateTime.UtcNow; + foreach (SensorInfo ts in curSensors) { // Time has passed? - if (ts.next.ToUniversalTime() < DateTime.Now.ToUniversalTime()) + if (ts.next < now) { SensorSweep(ts); // set next interval - ts.next = DateTime.Now.ToUniversalTime().AddSeconds(ts.interval); + ts.next = now.AddSeconds(ts.interval); } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index bee060ad4c..8f863afe45 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -38,6 +38,7 @@ using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; + namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { /// @@ -50,7 +51,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces /// public enum ThreatLevel { - // Not documented, presumably means permanently disabled ? NoAccess = -1, /// @@ -123,6 +123,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces string osSetDynamicTextureURLBlendFace(string dynamicID, string contentType, string url, string extraParams, bool blend, int disp, int timer, int alpha, int face); string osSetDynamicTextureData(string dynamicID, string contentType, string data, string extraParams, int timer); + string osSetDynamicTextureDataFace(string dynamicID, string contentType, string data, string extraParams, int timer, int face); string osSetDynamicTextureDataBlend(string dynamicID, string contentType, string data, string extraParams, int timer, int alpha); string osSetDynamicTextureDataBlendFace(string dynamicID, string contentType, string data, string extraParams, @@ -143,8 +144,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osSetParcelSIPAddress(string SIPAddress); // Avatar Info Commands - string osGetAgentIP(string agent); LSL_List osGetAgents(); + string osGetAgentIP(string agent); // Teleport commands void osTeleportAgent(string agent, string regionName, LSL_Types.Vector3 position, LSL_Types.Vector3 lookat); @@ -222,10 +223,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces string osDrawLine(string drawList, int endX, int endY); string osDrawText(string drawList, string text); string osDrawEllipse(string drawList, int width, int height); + string osDrawFilledEllipse(string drawList, int width, int height); string osDrawRectangle(string drawList, int width, int height); string osDrawFilledRectangle(string drawList, int width, int height); string osDrawPolygon(string drawList, LSL_List x, LSL_List y); string osDrawFilledPolygon(string drawList, LSL_List x, LSL_List y); + string osDrawResetTransform(string drawList); + string osDrawRotationTransform(string drawList, LSL_Float x); + string osDrawScaleTransform(string drawList, LSL_Float x, LSL_Float y); + string osDrawTranslationTransform(string drawList, LSL_Float x, LSL_Float y); string osSetFontName(string drawList, string fontName); string osSetFontSize(string drawList, int fontSize); string osSetPenSize(string drawList, int penSize); @@ -389,6 +395,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osSetProjectionParams(LSL_Key prim, bool projection, LSL_Key texture, double fov, double focus, double amb); LSL_List osGetAvatarList(); + LSL_List osGetNPCList(); LSL_String osUnixTimeToTimestamp(long time); @@ -486,6 +493,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_String osRequestURL(LSL_List options); LSL_String osRequestSecureURL(LSL_List options); void osCollisionSound(string impact_sound, double impact_volume); + void osVolumeDetect(int detect); + + LSL_List osGetInertiaData(); + void osClearInertia(); + void osSetInertiaAsBox(LSL_Float mass, vector boxSize, vector centerOfMass, rotation rot); + void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, vector centerOfMass); + void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, vector centerOfMass,rotation lslrot); + + LSL_Integer osTeleportObject(LSL_Key objectUUID, vector targetPos, rotation targetrotation, LSL_Integer flags); + LSL_Integer osGetLinkNumber(LSL_String name); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs index 3a90c7704e..e4c1ca0a8f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Constants.cs @@ -29,6 +29,7 @@ using System; using vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; using LSLInteger = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; +using LSLString = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { @@ -696,7 +697,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int PARCEL_DETAILS_GROUP = 3; public const int PARCEL_DETAILS_AREA = 4; public const int PARCEL_DETAILS_ID = 5; - public const int PARCEL_DETAILS_SEE_AVATARS = 6; // not implemented + public const int PARCEL_DETAILS_SEE_AVATARS = 6; + public const int PARCEL_DETAILS_ANY_AVATAR_SOUNDS = 7; + public const int PARCEL_DETAILS_GROUP_SOUNDS = 8; //osSetParcelDetails public const int PARCEL_DETAILS_CLAIMDATE = 10; @@ -834,15 +837,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase public const int KFM_CMD_STOP = 1; public const int KFM_CMD_PAUSE = 2; - public const string JSON_ARRAY = "JSON_ARRAY"; - public const string JSON_OBJECT = "JSON_OBJECT"; - public const string JSON_INVALID = "JSON_INVALID"; - public const string JSON_NUMBER = "JSON_NUMBER"; - public const string JSON_STRING = "JSON_STRING"; - public const string JSON_TRUE = "JSON_TRUE"; - public const string JSON_FALSE = "JSON_FALSE"; - public const string JSON_NULL = "JSON_NULL"; - public const string JSON_APPEND = "JSON_APPEND"; + public const string JSON_INVALID = "\uFDD0"; + public const string JSON_OBJECT = "\uFDD1"; + public const string JSON_ARRAY = "\uFDD2"; + public const string JSON_NUMBER = "\uFDD3"; + public const string JSON_STRING = "\uFDD4"; + public const string JSON_NULL = "\uFDD5"; + public const string JSON_TRUE = "\uFDD6"; + public const string JSON_FALSE = "\uFDD7"; + public const string JSON_DELETE = "\uFDD8"; + public const string JSON_APPEND = "-1"; /// /// process name parameter as regex @@ -853,5 +857,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase /// process message parameter as regex /// public const int OS_LISTEN_REGEX_MESSAGE = 0x2; + + // for osTeleportObject + public const int OSTPOBJ_NONE = 0x0; + public const int OSTPOBJ_STOPATTARGET = 0x1; // stops at destination + public const int OSTPOBJ_STOPONFAIL = 0x2; // stops at jump point if tp fails + public const int OSTPOBJ_SETROT = 0x4; // the rotation is the final rotation, otherwise is a added rotation + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index 6164734789..42e7bfba84 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -153,6 +153,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osSetDynamicTextureData(dynamicID, contentType, data, extraParams, timer); } + public string osSetDynamicTextureDataFace(string dynamicID, string contentType, string data, string extraParams, + int timer, int face) + { + return m_OSSL_Functions.osSetDynamicTextureDataFace(dynamicID, contentType, data, extraParams, timer, face); + } + public string osSetDynamicTextureURLBlend(string dynamicID, string contentType, string url, string extraParams, int timer, int alpha) { @@ -271,17 +277,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase m_OSSL_Functions.osTeleportOwner(position, lookat); } - // Avatar info functions - public string osGetAgentIP(string agent) - { - return m_OSSL_Functions.osGetAgentIP(agent); - } - public LSL_List osGetAgents() { return m_OSSL_Functions.osGetAgents(); } + public string osGetAgentIP(string agent) + { + return m_OSSL_Functions.osGetAgentIP(agent); + } + // Animation Functions public void osAvatarPlayAnimation(string avatar, string animation) @@ -355,6 +360,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osDrawEllipse(drawList, width, height); } + public string osDrawFilledEllipse(string drawList, int width, int height) + { + return m_OSSL_Functions.osDrawFilledEllipse(drawList, width, height); + } + public string osDrawRectangle(string drawList, int width, int height) { return m_OSSL_Functions.osDrawRectangle(drawList, width, height); @@ -375,6 +385,26 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osDrawFilledPolygon(drawList, x, y); } + public string osDrawResetTransform(string drawList) + { + return m_OSSL_Functions.osDrawResetTransform(drawList); + } + + public string osDrawRotationTransform(string drawList, LSL_Float x) + { + return m_OSSL_Functions.osDrawRotationTransform(drawList, x); + } + + public string osDrawScaleTransform(string drawList, LSL_Float x, LSL_Float y) + { + return m_OSSL_Functions.osDrawScaleTransform(drawList, x, y); + } + + public string osDrawTranslationTransform(string drawList, LSL_Float x, LSL_Float y) + { + return m_OSSL_Functions.osDrawTranslationTransform(drawList, x, y); + } + public string osSetFontSize(string drawList, int fontSize) { return m_OSSL_Functions.osSetFontSize(drawList, fontSize); @@ -399,6 +429,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { return m_OSSL_Functions.osSetPenColor(drawList, color); } + // Deprecated public string osSetPenColour(string drawList, string colour) { @@ -1010,6 +1041,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_OSSL_Functions.osGetAvatarList(); } + public LSL_List osGetNPCList() + { + return m_OSSL_Functions.osGetNPCList(); + } + public LSL_String osUnixTimeToTimestamp(long time) { return m_OSSL_Functions.osUnixTimeToTimestamp(time); @@ -1114,5 +1150,40 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osVolumeDetect(detect); } + + public LSL_List osGetInertiaData() + { + return m_OSSL_Functions.osGetInertiaData(); + } + + public void osSetInertiaAsBox(LSL_Float mass, vector boxSize, vector centerOfMass, rotation rot) + { + m_OSSL_Functions.osSetInertiaAsBox(mass, boxSize, centerOfMass, rot); + } + + public void osSetInertiaAsSphere(LSL_Float mass, LSL_Float radius, vector centerOfMass) + { + m_OSSL_Functions.osSetInertiaAsSphere(mass, radius, centerOfMass); + } + + public void osSetInertiaAsCylinder(LSL_Float mass, LSL_Float radius, LSL_Float lenght, vector centerOfMass,rotation lslrot) + { + m_OSSL_Functions.osSetInertiaAsCylinder( mass, radius, lenght, centerOfMass, lslrot); + } + + public void osClearInertia() + { + m_OSSL_Functions.osClearInertia(); + } + + public LSL_Integer osTeleportObject(LSL_Key objectUUID, vector targetPos, rotation targetrotation, LSL_Integer flags) + { + return m_OSSL_Functions.osTeleportObject(objectUUID, targetPos, targetrotation, flags); + } + + public LSL_Integer osGetLinkNumber(LSL_String name) + { + return m_OSSL_Functions.osGetLinkNumber(name); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs index f3b8e1d382..20f9770d3c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs +++ b/OpenSim/Region/ScriptEngine/Shared/CodeTools/Compiler.cs @@ -79,12 +79,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools private List m_warnings = new List(); - // private object m_syncy = new object(); - -// private static CSharpCodeProvider CScodeProvider = new CSharpCodeProvider(); -// private static VBCodeProvider VBcodeProvider = new VBCodeProvider(); - - // private static int instanceID = new Random().Next(0, int.MaxValue); // Unique number to use on our compiled files private static UInt64 scriptCompileCounter = 0; // And a counter public IScriptEngine m_scriptEngine; @@ -251,23 +245,6 @@ namespace OpenSim.Region.ScriptEngine.Shared.CodeTools } } - ////private ICodeCompiler icc = codeProvider.CreateCompiler(); - //public string CompileFromFile(string LSOFileName) - //{ - // switch (Path.GetExtension(LSOFileName).ToLower()) - // { - // case ".txt": - // case ".lsl": - // Common.ScriptEngineBase.Shared.SendToDebug("Source code is LSL, converting to CS"); - // return CompileFromLSLText(File.ReadAllText(LSOFileName)); - // case ".cs": - // Common.ScriptEngineBase.Shared.SendToDebug("Source code is CS"); - // return CompileFromCSText(File.ReadAllText(LSOFileName)); - // default: - // throw new Exception("Unknown script type."); - // } - //} - public string GetCompilerOutput(string assetID) { return Path.Combine(ScriptEnginesPath, Path.Combine( @@ -578,8 +555,6 @@ namespace SecondLife switch (lang) { case enumCompileType.vb: -// results = VBcodeProvider.CompileAssemblyFromSource( -// parameters, Script); provider = CodeDomProvider.CreateProvider("VisualBasic"); break; case enumCompileType.cs: @@ -594,56 +569,36 @@ namespace SecondLife if(provider == null) throw new Exception("Compiler failed to load "); + bool complete = false; + bool retried = false; - bool complete = false; - bool retried = false; - - do + do + { + results = provider.CompileAssemblyFromSource( + parameters, Script); + // Deal with an occasional segv in the compiler. + // Rarely, if ever, occurs twice in succession. + // Line # == 0 and no file name are indications that + // this is a native stack trace rather than a normal + // error log. + if (results.Errors.Count > 0) + { + if (!retried && string.IsNullOrEmpty(results.Errors[0].FileName) && + results.Errors[0].Line == 0) { -// lock (CScodeProvider) -// { -// results = CScodeProvider.CompileAssemblyFromSource( -// parameters, Script); -// } - - results = provider.CompileAssemblyFromSource( - parameters, Script); - // Deal with an occasional segv in the compiler. - // Rarely, if ever, occurs twice in succession. - // Line # == 0 and no file name are indications that - // this is a native stack trace rather than a normal - // error log. - if (results.Errors.Count > 0) - { - if (!retried && string.IsNullOrEmpty(results.Errors[0].FileName) && - results.Errors[0].Line == 0) - { - // System.Console.WriteLine("retrying failed compilation"); - retried = true; - } - else - { - complete = true; - } - } - else - { - complete = true; - } - } while (!complete); -// break; -// default: -// throw new Exception("Compiler is not able to recongnize " + -// "language type \"" + lang.ToString() + "\""); -// } - -// foreach (Type type in results.CompiledAssembly.GetTypes()) -// { -// foreach (MethodInfo method in type.GetMethods(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static)) -// { -// m_log.DebugFormat("[COMPILER]: {0}.{1}", type.FullName, method.Name); -// } -// } + // System.Console.WriteLine("retrying failed compilation"); + retried = true; + } + else + { + complete = true; + } + } + else + { + complete = true; + } + } while (!complete); // // WARNINGS AND ERRORS diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index f16fd0146b..a65f71fcc3 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -28,6 +28,7 @@ using System; using System.Collections; using System.Globalization; +using System.Text; using System.Text.RegularExpressions; using OpenSim.Framework; @@ -38,7 +39,6 @@ using OMV_Quaternion = OpenMetaverse.Quaternion; namespace OpenSim.Region.ScriptEngine.Shared { - [Serializable] public partial class LSL_Types { // Types are kept is separate .dll to avoid having to add whatever .dll it is in it to script AppDomain @@ -525,7 +525,7 @@ namespace OpenSim.Region.ScriptEngine.Shared } [Serializable] - public struct list + public class list { private object[] m_data; @@ -1152,34 +1152,35 @@ namespace OpenSim.Region.ScriptEngine.Shared public string ToCSV() { - string ret = ""; - foreach (object o in this.Data) + if(m_data == null || m_data.Length == 0) + return String.Empty; + + Object o = m_data[0]; + int len = m_data.Length; + if(len == 1) + return o.ToString(); + + StringBuilder sb = new StringBuilder(1024); + sb.Append(o.ToString()); + for(int i = 1 ; i < len; i++) { - if (ret == "") - { - ret = o.ToString(); - } - else - { - ret = ret + ", " + o.ToString(); - } + sb.Append(","); + sb.Append(o.ToString()); } - return ret; + return sb.ToString(); } private string ToSoup() { - string output; - output = String.Empty; - if (Data.Length == 0) - { + if(m_data == null || m_data.Length == 0) return String.Empty; - } - foreach (object o in Data) + + StringBuilder sb = new StringBuilder(1024); + foreach (object o in m_data) { - output = output + o.ToString(); + sb.Append(o.ToString()); } - return output; + return sb.ToString(); } public static explicit operator String(list l) @@ -1369,26 +1370,33 @@ namespace OpenSim.Region.ScriptEngine.Shared public string ToPrettyString() { - string output; - if (Data.Length == 0) - { + if(m_data == null || m_data.Length == 0) return "[]"; - } - output = "["; - foreach (object o in Data) + + StringBuilder sb = new StringBuilder(1024); + int len = m_data.Length; + int last = len - 1; + object o; + + sb.Append("["); + for(int i = 0; i < len; i++ ) { + o = m_data[i]; if (o is String) { - output = output + "\"" + o + "\", "; + sb.Append("\""); + sb.Append((String)o); + sb.Append("\""); } else { - output = output + o.ToString() + ", "; + sb.Append(o.ToString()); } + if(i < last) + sb.Append(","); } - output = output.Substring(0, output.Length - 2); - output = output + "]"; - return output; + sb.Append("]"); + return sb.ToString(); } public class AlphaCompare : IComparer diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs index 4dc8fc6829..241a24d04e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiHttpTests.cs @@ -87,17 +87,21 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests uint port = 9999; MainServer.RemoveHttpServer(port); + m_engine = new MockScriptEngine(); + m_urlModule = new UrlModule(); + + IConfigSource config = new IniConfigSource(); + config.AddConfig("Network"); + config.Configs["Network"].Set("ExternalHostNameForLSL", "127.0.0.1"); + m_scene = new SceneHelpers().SetupScene(); + BaseHttpServer server = new BaseHttpServer(port, false, 0, ""); MainServer.AddHttpServer(server); MainServer.Instance = server; server.Start(); - m_engine = new MockScriptEngine(); - m_urlModule = new UrlModule(); - - m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, new IniConfigSource(), m_engine, m_urlModule); + SceneHelpers.SetupSceneModules(m_scene, config, m_engine, m_urlModule); SceneObjectGroup so = SceneHelpers.AddSceneObject(m_scene); m_scriptItem = TaskInventoryHelpers.AddScript(m_scene.AssetService, so.RootPart); diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs index d652b0d1d2..16b87b3402 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiInventoryTests.cs @@ -39,6 +39,7 @@ using OpenSim.Framework; using OpenSim.Region.CoreModules.Avatar.AvatarFactory; using OpenSim.Region.OptionalModules.World.NPC; using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Permissions; using OpenSim.Region.ScriptEngine.Shared; using OpenSim.Region.ScriptEngine.Shared.Api; using OpenSim.Region.ScriptEngine.Shared.Instance; @@ -63,12 +64,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests base.SetUp(); IConfigSource initConfigSource = new IniConfigSource(); - IConfig config = initConfigSource.AddConfig("XEngine"); + IConfig config = initConfigSource.AddConfig("Startup"); + config.Set("serverside_object_permissions", true); + config =initConfigSource.AddConfig("Permissions"); + config.Set("permissionmodules", "DefaultPermissionsModule"); + config.Set("serverside_object_permissions", true); + config.Set("propagate_permissions", true); + + config = initConfigSource.AddConfig("XEngine"); config.Set("Enabled", "true"); m_scene = new SceneHelpers().SetupScene(); - SceneHelpers.SetupSceneModules(m_scene, initConfigSource); - + SceneHelpers.SetupSceneModules(m_scene, initConfigSource, new object[] { new DefaultPermissionsModule() }); m_engine = new XEngine.XEngine(); m_engine.Initialise(initConfigSource); m_engine.AddRegion(m_scene); diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 0ccc6835c6..870957bccb 100755 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -827,6 +827,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (m_ScriptEngines.Contains(this)) m_ScriptEngines.Remove(this); } + + lock(m_Scripts) + m_ThreadPool.Shutdown(); } public object DoBackup(object o) @@ -1076,6 +1079,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine "[XEngine]: Started {0} scripts in {1}", scriptsStarted, m_Scene.Name); } } + catch (System.Threading.ThreadAbortException) { } catch (Exception e) { m_log.Error( @@ -2145,10 +2149,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine string fn = Path.GetFileName(assemName); string assem = String.Empty; + string assemNameText = assemName + ".text"; - if (File.Exists(assemName + ".text")) + if (File.Exists(assemNameText)) { - FileInfo tfi = new FileInfo(assemName + ".text"); + FileInfo tfi = new FileInfo(assemNameText); if (tfi != null) { @@ -2156,7 +2161,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine try { - using (FileStream tfs = File.Open(assemName + ".text", + using (FileStream tfs = File.Open(assemNameText, FileMode.Open, FileAccess.Read)) { tfs.Read(tdata, 0, tdata.Length); diff --git a/OpenSim/Server/Base/ServerUtils.cs b/OpenSim/Server/Base/ServerUtils.cs index b17d7ba5c1..aff6b4fc7a 100644 --- a/OpenSim/Server/Base/ServerUtils.cs +++ b/OpenSim/Server/Base/ServerUtils.cs @@ -478,17 +478,22 @@ namespace OpenSim.Server.Base XmlDocument doc = new XmlDocument(); - doc.LoadXml(data); + try + { + doc.LoadXml(data); + XmlNodeList rootL = doc.GetElementsByTagName("ServerResponse"); - XmlNodeList rootL = doc.GetElementsByTagName("ServerResponse"); + if (rootL.Count != 1) + return ret; - if (rootL.Count != 1) - return ret; - - XmlNode rootNode = rootL[0]; - - ret = ParseElement(rootNode); + XmlNode rootNode = rootL[0]; + ret = ParseElement(rootNode); + } + catch (Exception e) + { + m_log.DebugFormat("[serverUtils.ParseXmlResponse]: failed error: {0} \n --- string: {1} - ",e.Message, data); + } return ret; } diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index f60b5fb6dc..176e876af3 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -61,6 +61,10 @@ namespace OpenSim.Server.Base // private bool m_Running = true; +#if (_MONO) + private static Mono.Unix.UnixSignal[] signals; +#endif + // Handle all the automagical stuff // public ServicesServerBase(string prompt, string[] args) : base() @@ -183,6 +187,42 @@ namespace OpenSim.Server.Base RegisterCommonCommands(); RegisterCommonComponents(Config); +#if (_MONO) + Thread signal_thread = new Thread (delegate () + { + while (true) + { + // Wait for a signal to be delivered + int index = Mono.Unix.UnixSignal.WaitAny (signals, -1); + + //Mono.Unix.Native.Signum signal = signals [index].Signum; + ShutdownSpecific(); + m_Running = false; + Environment.Exit(0); + } + }); + + if(!Util.IsWindows()) + { + try + { + // linux mac os specifics + signals = new Mono.Unix.UnixSignal[] + { + new Mono.Unix.UnixSignal(Mono.Unix.Native.Signum.SIGTERM) + }; + ignal_thread.IsBackground = true; + signal_thread.Start(); + } + catch (Exception e) + { + m_log.Info("Could not set up UNIX signal handlers. SIGTERM will not"); + m_log.InfoFormat("shut down gracefully: {0}", e.Message); + m_log.Debug("Exception was: ", e); + } + } +#endif + // Allow derived classes to perform initialization that // needs to be done after the console has opened Initialise(); @@ -210,6 +250,9 @@ namespace OpenSim.Server.Base } } + MemoryWatchdog.Enabled = false; + Watchdog.Enabled = false; + WorkManager.Stop(); RemovePIDFile(); return 0; diff --git a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs index d3ea7e23da..4f03cf4a28 100644 --- a/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Authentication/AuthenticationServerPostHandler.cs @@ -82,11 +82,11 @@ namespace OpenSim.Server.Handlers.Authentication switch (p[0]) { case "plain": - StreamReader sr = new StreamReader(request); - string body = sr.ReadToEnd(); - sr.Close(); - + string body; + using(StreamReader sr = new StreamReader(request)) + body = sr.ReadToEnd(); return DoPlainMethods(body); + case "crypt": byte[] buffer = new byte[request.Length]; long length = request.Length; diff --git a/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs b/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs index a6605a113b..254b82fadd 100644 --- a/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs +++ b/OpenSim/Server/Handlers/Authentication/OpenIdServerHandler.cs @@ -222,7 +222,10 @@ For more information, see http://openid.net/. try { - NameValueCollection postQuery = HttpUtility.ParseQueryString(new StreamReader(httpRequest.InputStream).ReadToEnd()); + string forPost; + using(StreamReader sr = new StreamReader(httpRequest.InputStream)) + forPost = sr.ReadToEnd(); + NameValueCollection postQuery = HttpUtility.ParseQueryString(forPost); NameValueCollection getQuery = HttpUtility.ParseQueryString(httpRequest.Url.Query); NameValueCollection openIdQuery = (postQuery.GetValues("openid.mode") != null ? postQuery : getQuery); diff --git a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs index 69c1a896f7..b8fdacfb60 100644 --- a/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Avatar/AvatarServerPostHandler.cs @@ -60,9 +60,9 @@ namespace OpenSim.Server.Handlers.Avatar protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs b/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs index 24f63d9319..d16000d572 100644 --- a/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs +++ b/OpenSim/Server/Handlers/BakedTextures/XBakesPostHandler.cs @@ -65,10 +65,8 @@ namespace OpenSim.Server.Handlers.BakedTextures return new byte[0]; } - StreamReader sr = new StreamReader(request); - - m_BakesService.Store(p[0], sr.ReadToEnd()); - sr.Close(); + using(StreamReader sr = new StreamReader(request)) + m_BakesService.Store(p[0],sr.ReadToEnd()); return new byte[0]; } diff --git a/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs b/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs index e0c281044f..b7558ec2a9 100644 --- a/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs +++ b/OpenSim/Server/Handlers/Estate/EstateDataRobustConnector.cs @@ -282,9 +282,10 @@ namespace OpenSim.Server.Handlers // /estates/estate/?eid=int®ion=uuid if ("estate".Equals(resource)) { - StreamReader sr = new StreamReader(request); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(request)) + body = sr.ReadToEnd(); + body = body.Trim(); Dictionary requestData = ServerUtils.ParseQueryString(body); diff --git a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs index 3aab30b3c3..d6668abe13 100644 --- a/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Friends/FriendsServerPostHandler.cs @@ -61,9 +61,9 @@ namespace OpenSim.Server.Handlers.Friends protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs index f51c4ee48c..44d4654ceb 100644 --- a/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Grid/GridServerPostHandler.cs @@ -65,9 +65,9 @@ namespace OpenSim.Server.Handlers.Grid protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs index 8806c2cbbd..1f691d66b2 100644 --- a/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs +++ b/OpenSim/Server/Handlers/GridUser/GridUserServerPostHandler.cs @@ -60,9 +60,9 @@ namespace OpenSim.Server.Handlers.GridUser protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs index 8116050afe..fc1a77d0e1 100644 --- a/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Hypergrid/HGFriendsServerPostHandler.cs @@ -71,9 +71,9 @@ namespace OpenSim.Server.Handlers.Hypergrid protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs index 4400395c30..742d1a045b 100644 --- a/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs +++ b/OpenSim/Server/Handlers/Inventory/XInventoryInConnector.cs @@ -95,9 +95,9 @@ namespace OpenSim.Server.Handlers.Inventory protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); //m_log.DebugFormat("[XXX]: query String: {0}", body); diff --git a/OpenSim/Server/Handlers/Land/LandHandlers.cs b/OpenSim/Server/Handlers/Land/LandHandlers.cs index 150eaae995..d74077a365 100644 --- a/OpenSim/Server/Handlers/Land/LandHandlers.cs +++ b/OpenSim/Server/Handlers/Land/LandHandlers.cs @@ -85,6 +85,7 @@ namespace OpenSim.Server.Handlers.Land hash["SnapshotID"] = landData.SnapshotID.ToString(); hash["UserLocation"] = landData.UserLocation.ToString(); hash["RegionAccess"] = regionAccess.ToString(); + hash["Dwell"] = landData.Dwell.ToString(); } XmlRpcResponse response = new XmlRpcResponse(); diff --git a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs index 072429a8f7..4e7ab00cec 100644 --- a/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs +++ b/OpenSim/Server/Handlers/Login/LLLoginHandlers.cs @@ -64,7 +64,7 @@ namespace OpenSim.Server.Handlers.Login public XmlRpcResponse HandleXMLRPCLogin(XmlRpcRequest request, IPEndPoint remoteClient) { Hashtable requestData = (Hashtable)request.Params[0]; - if (m_Proxy && request.Params[3] != null) + if (request.Params[3] != null) { IPEndPoint ep = Util.GetClientIPFromXFF((string)request.Params[3]); if (ep != null) diff --git a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs index 7611f538dd..331dabf9a9 100644 --- a/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapAddServerConnector.cs @@ -104,9 +104,9 @@ namespace OpenSim.Server.Handlers.MapImage protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); try @@ -225,8 +225,8 @@ namespace OpenSim.Server.Handlers.MapImage private System.Net.IPAddress GetCallerIP(IOSHttpRequest request) { - if (!m_Proxy) - return request.RemoteIPEndPoint.Address; +// if (!m_Proxy) +// return request.RemoteIPEndPoint.Address; // We're behind a proxy string xff = "X-Forwarded-For"; @@ -236,7 +236,7 @@ namespace OpenSim.Server.Handlers.MapImage if (xffValue == null || (xffValue != null && xffValue == string.Empty)) { - m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header"); +// m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header"); return request.RemoteIPEndPoint.Address; } diff --git a/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs index f292b9585d..9daeb73729 100644 --- a/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs +++ b/OpenSim/Server/Handlers/Map/MapRemoveServerConnector.cs @@ -102,9 +102,9 @@ namespace OpenSim.Server.Handlers.MapImage public override byte[] Handle(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { // m_log.DebugFormat("[MAP SERVICE IMAGE HANDLER]: Received {0}", path); - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); try @@ -215,19 +215,22 @@ namespace OpenSim.Server.Handlers.MapImage private byte[] DocToBytes(XmlDocument doc) { - MemoryStream ms = new MemoryStream(); - XmlTextWriter xw = new XmlTextWriter(ms, null); - xw.Formatting = Formatting.Indented; - doc.WriteTo(xw); - xw.Flush(); - + using(MemoryStream ms = new MemoryStream()) + { + using(XmlTextWriter xw = new XmlTextWriter(ms,null)) + { + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + } return ms.ToArray(); + } } private System.Net.IPAddress GetCallerIP(IOSHttpRequest request) { - if (!m_Proxy) - return request.RemoteIPEndPoint.Address; +// if (!m_Proxy) +// return request.RemoteIPEndPoint.Address; // We're behind a proxy string xff = "X-Forwarded-For"; @@ -237,7 +240,7 @@ namespace OpenSim.Server.Handlers.MapImage if (xffValue == null || (xffValue != null && xffValue == string.Empty)) { - m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header"); +// m_log.WarnFormat("[MAP IMAGE HANDLER]: No XFF header"); return request.RemoteIPEndPoint.Address; } diff --git a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs index 4e1f72edf9..c52a1ab06b 100644 --- a/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs +++ b/OpenSim/Server/Handlers/Simulation/AgentHandlers.cs @@ -517,32 +517,30 @@ namespace OpenSim.Server.Handlers.Simulation protected string GetCallerIP(Hashtable request) { - if (!m_Proxy) - return Util.GetCallerIP(request); - - // We're behind a proxy - Hashtable headers = (Hashtable)request["headers"]; - - //// DEBUG - //foreach (object o in headers.Keys) - // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString())); - - string xff = "X-Forwarded-For"; - if (headers.ContainsKey(xff.ToLower())) - xff = xff.ToLower(); - - if (!headers.ContainsKey(xff) || headers[xff] == null) + if (request.ContainsKey("headers")) { - m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); - return Util.GetCallerIP(request); + Hashtable headers = (Hashtable)request["headers"]; + + //// DEBUG + //foreach (object o in headers.Keys) + // m_log.DebugFormat("XXX {0} = {1}", o.ToString(), (headers[o] == null? "null" : headers[o].ToString())); + + string xff = "X-Forwarded-For"; + if (!headers.ContainsKey(xff)) + xff = xff.ToLower(); + + if (!headers.ContainsKey(xff) || headers[xff] == null) + { +// m_log.WarnFormat("[AGENT HANDLER]: No XFF header"); + return Util.GetCallerIP(request); + } + +// m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); + + IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); + if (ep != null) + return ep.Address.ToString(); } - - m_log.DebugFormat("[AGENT HANDLER]: XFF is {0}", headers[xff]); - - IPEndPoint ep = Util.GetClientIPFromXFF((string)headers[xff]); - if (ep != null) - return ep.Address.ToString(); - // Oops return Util.GetCallerIP(request); } diff --git a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs index a02255f01d..bc12ef9b94 100644 --- a/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs +++ b/OpenSim/Server/Handlers/UserAccounts/UserAccountServerPostHandler.cs @@ -72,9 +72,9 @@ namespace OpenSim.Server.Handlers.UserAccounts protected override byte[] ProcessRequest(string path, Stream requestData, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) { - StreamReader sr = new StreamReader(requestData); - string body = sr.ReadToEnd(); - sr.Close(); + string body; + using(StreamReader sr = new StreamReader(requestData)) + body = sr.ReadToEnd(); body = body.Trim(); // We need to check the authorization header diff --git a/OpenSim/Server/ServerMain.cs b/OpenSim/Server/ServerMain.cs index c3430440a3..69d0b74d0d 100644 --- a/OpenSim/Server/ServerMain.cs +++ b/OpenSim/Server/ServerMain.cs @@ -31,6 +31,7 @@ using System.Reflection; using System; using System.Net; using System.Collections.Generic; +using OpenSim.Framework; using OpenSim.Framework.Servers; using OpenSim.Framework.Servers.HttpServer; using OpenSim.Server.Base; @@ -54,10 +55,12 @@ namespace OpenSim.Server public static int Main(string[] args) { - // Make sure we don't get outbound connections queueing - ServicePointManager.DefaultConnectionLimit = 50; + ServicePointManager.DefaultConnectionLimit = 64; + ServicePointManager.Expect100Continue = false; ServicePointManager.UseNagleAlgorithm = false; + try { ServicePointManager.DnsRefreshTimeout = 300000; } catch { } + m_Server = new HttpServerBase("R.O.B.U.S.T.", args); string registryLocation; @@ -158,6 +161,11 @@ namespace OpenSim.Server int res = m_Server.Run(); + if(m_Server != null) + m_Server.Shutdown(); + + Util.StopThreadPool(); + Environment.Exit(res); return 0; diff --git a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs index 3fa8b54d73..7e81be7fa0 100644 --- a/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs +++ b/OpenSim/Services/Connectors/Asset/AssetServicesConnector.cs @@ -34,7 +34,7 @@ using System.Reflection; using System.Timers; using Nini.Config; using OpenSim.Framework; -using OpenSim.Framework.Console; +using OpenSim.Framework.Monitoring; using OpenSim.Services.Interfaces; using OpenMetaverse; @@ -135,8 +135,11 @@ namespace OpenSim.Services.Connectors for (int i = 0 ; i < 2 ; i++) { - m_fetchThreads[i] = new Thread(AssetRequestProcessor); - m_fetchThreads[i].Start(); + m_fetchThreads[i] = WorkManager.StartThread(AssetRequestProcessor, + String.Format("GetTextureWorker{0}", i), + ThreadPriority.Normal, + true, + false); } } @@ -243,8 +246,12 @@ namespace OpenSim.Services.Connectors string uri = MapServer(id) + "/assets/" + id; AssetBase asset = null; + if (m_Cache != null) - asset = m_Cache.Get(id); + { + if (!m_Cache.Get(id, out asset)) + return null; + } if (asset == null || asset.Data == null || asset.Data.Length == 0) { @@ -275,17 +282,22 @@ namespace OpenSim.Services.Connectors { // m_log.DebugFormat("[ASSET SERVICE CONNECTOR]: Cache request for {0}", id); + AssetBase asset = null; if (m_Cache != null) - return m_Cache.Get(id); + { + m_Cache.Get(id, out asset); + } - return null; + return asset; } public AssetMetadata GetMetadata(string id) { if (m_Cache != null) { - AssetBase fullAsset = m_Cache.Get(id); + AssetBase fullAsset; + if (!m_Cache.Get(id, out fullAsset)) + return null; if (fullAsset != null) return fullAsset.Metadata; @@ -301,7 +313,9 @@ namespace OpenSim.Services.Connectors { if (m_Cache != null) { - AssetBase fullAsset = m_Cache.Get(id); + AssetBase fullAsset; + if (!m_Cache.Get(id, out fullAsset)) + return null; if (fullAsset != null) return fullAsset.Data; @@ -338,8 +352,8 @@ namespace OpenSim.Services.Connectors public string id; } - private OpenMetaverse.BlockingQueue m_requestQueue = - new OpenMetaverse.BlockingQueue(); + private OpenSim.Framework.BlockingQueue m_requestQueue = + new OpenSim.Framework.BlockingQueue(); private void AssetRequestProcessor() { @@ -347,8 +361,10 @@ namespace OpenSim.Services.Connectors while (true) { - r = m_requestQueue.Dequeue(); - + r = m_requestQueue.Dequeue(4500); + Watchdog.UpdateThread(); + if(r== null) + continue; string uri = r.uri; string id = r.id; @@ -389,7 +405,10 @@ namespace OpenSim.Services.Connectors AssetBase asset = null; if (m_Cache != null) - asset = m_Cache.Get(id); + { + if (!m_Cache.Get(id, out asset)) + return false; + } if (asset == null || asset.Data == null || asset.Data.Length == 0) { @@ -590,7 +609,7 @@ namespace OpenSim.Services.Connectors AssetBase asset = null; if (m_Cache != null) - asset = m_Cache.Get(id); + m_Cache.Get(id, out asset); if (asset == null) { diff --git a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs index b261675572..f2bb52aa4d 100644 --- a/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs +++ b/OpenSim/Services/Connectors/Hypergrid/UserAgentServiceConnector.cs @@ -70,9 +70,14 @@ namespace OpenSim.Services.Connectors.Hypergrid { Uri m_Uri = new Uri(m_ServerURL); IPAddress ip = Util.GetHostFromDNS(m_Uri.Host); - m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); - if (!m_ServerURL.EndsWith("/")) - m_ServerURL += "/"; + if(ip != null) + { + m_ServerURL = m_ServerURL.Replace(m_Uri.Host, ip.ToString()); + if (!m_ServerURL.EndsWith("/")) + m_ServerURL += "/"; + } + else + m_log.DebugFormat("[USER AGENT CONNECTOR]: Failed to resolv address of {0}", url); } catch (Exception e) { diff --git a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs index 047880a063..5492e83a96 100644 --- a/OpenSim/Services/Connectors/Land/LandServicesConnector.cs +++ b/OpenSim/Services/Connectors/Land/LandServicesConnector.cs @@ -117,6 +117,8 @@ namespace OpenSim.Services.Connectors landData.UserLocation = Vector3.Parse((string)hash["UserLocation"]); if (hash["RegionAccess"] != null) regionAccess = (byte)Convert.ToInt32((string)hash["RegionAccess"]); + if(hash["Dwell"] != null) + landData.Dwell = Convert.ToSingle((string)hash["Dwell"]); m_log.DebugFormat("[LAND CONNECTOR]: Got land data for parcel {0}", landData.Name); } catch (Exception e) diff --git a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs index 939059da71..5f075ace29 100644 --- a/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs +++ b/OpenSim/Services/Connectors/Neighbour/NeighbourServicesConnector.cs @@ -183,8 +183,8 @@ namespace OpenSim.Services.Connectors { using (StreamReader sr = new StreamReader(s)) { + sr.ReadToEnd(); // just try to read //reply = sr.ReadToEnd().Trim(); - sr.ReadToEnd().Trim(); //m_log.InfoFormat("[REST COMMS]: DoHelloNeighbourCall reply was {0} ", reply); } } diff --git a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs index 121e8636e4..953bc2af1b 100644 --- a/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs +++ b/OpenSim/Services/Connectors/SimianGrid/SimianAssetServiceConnector.cs @@ -136,7 +136,9 @@ namespace OpenSim.Services.Connectors.SimianGrid // Cache fetch if (m_cache != null) { - AssetBase asset = m_cache.Get(id); + AssetBase asset; + if (!m_cache.Get(id, out asset)) + return null; if (asset != null) return asset; } @@ -147,8 +149,9 @@ namespace OpenSim.Services.Connectors.SimianGrid public AssetBase GetCached(string id) { + AssetBase asset; if (m_cache != null) - return m_cache.Get(id); + m_cache.Get(id, out asset); return null; } @@ -169,7 +172,9 @@ namespace OpenSim.Services.Connectors.SimianGrid // Cache fetch if (m_cache != null) { - AssetBase asset = m_cache.Get(id); + AssetBase asset; + if (!m_cache.Get(id, out asset)) + return null; if (asset != null) return asset.Metadata; } @@ -212,7 +217,10 @@ namespace OpenSim.Services.Connectors.SimianGrid // Cache fetch if (m_cache != null) { - AssetBase asset = m_cache.Get(id); + AssetBase asset; + if (!m_cache.Get(id, out asset)) + return false; + if (asset != null) { handler(id, sender, asset); diff --git a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs index 9f4d89ab6f..a4ca2d3ecb 100644 --- a/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs +++ b/OpenSim/Services/Connectors/Simulation/SimulationServiceConnector.cs @@ -295,9 +295,6 @@ namespace OpenSim.Services.Connectors.Simulation // m_log.DebugFormat("[REMOTE SIMULATION CONNECTOR]: QueryAccess start, position={0}", position); - IPEndPoint ext = destination.ExternalEndPoint; - if (ext == null) return false; - // Eventually, we want to use a caps url instead of the agentID string uri = destination.ServerURI + AgentPath() + agentID + "/" + destination.RegionID.ToString() + "/"; diff --git a/OpenSim/Services/GridService/GridService.cs b/OpenSim/Services/GridService/GridService.cs index 6153f5ea26..a5c7d34a50 100644 --- a/OpenSim/Services/GridService/GridService.cs +++ b/OpenSim/Services/GridService/GridService.cs @@ -909,9 +909,9 @@ namespace OpenSim.Services.GridService private void OutputRegionsToConsoleSummary(List regions) { ConsoleDisplayTable dispTable = new ConsoleDisplayTable(); - dispTable.AddColumn("Name", 44); - dispTable.AddColumn("ID", 36); - dispTable.AddColumn("Position", 11); + dispTable.AddColumn("Name", ConsoleDisplayUtil.RegionNameSize); + dispTable.AddColumn("ID", ConsoleDisplayUtil.UuidSize); + dispTable.AddColumn("Position", ConsoleDisplayUtil.CoordTupleSize); dispTable.AddColumn("Size", 11); dispTable.AddColumn("Flags", 60); diff --git a/OpenSim/Services/HypergridService/GatekeeperService.cs b/OpenSim/Services/HypergridService/GatekeeperService.cs index b80700faed..5c6abd217f 100644 --- a/OpenSim/Services/HypergridService/GatekeeperService.cs +++ b/OpenSim/Services/HypergridService/GatekeeperService.cs @@ -35,8 +35,8 @@ using OpenSim.Framework; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using OpenSim.Server.Base; +using OpenSim.Services.Connectors.InstantMessage; using OpenSim.Services.Connectors.Hypergrid; - using OpenMetaverse; using Nini.Config; @@ -71,6 +71,7 @@ namespace OpenSim.Services.HypergridService private static string m_ExternalName; private static Uri m_Uri; private static GridRegion m_DefaultGatewayRegion; + private bool m_allowDuplicatePresences = false; public GatekeeperService(IConfigSource config, ISimulationService simService) { @@ -144,6 +145,12 @@ namespace OpenSim.Services.HypergridService if (m_GridService == null || m_PresenceService == null || m_SimulationService == null) throw new Exception("Unable to load a required plugin, Gatekeeper Service cannot function."); + IConfig presenceConfig = config.Configs["PresenceService"]; + if (presenceConfig != null) + { + m_allowDuplicatePresences = presenceConfig.GetBoolean("AllowDuplicatePresences", m_allowDuplicatePresences); + } + m_log.Debug("[GATEKEEPER SERVICE]: Starting..."); } } @@ -369,6 +376,38 @@ namespace OpenSim.Services.HypergridService return false; } + UUID agentID = aCircuit.AgentID; + if(agentID == new UUID("6571e388-6218-4574-87db-f9379718315e")) + { + // really? + reason = "Invalid account ID"; + return false; + } + + if(m_GridUserService != null) + { + string PrincipalIDstr = agentID.ToString(); + GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(PrincipalIDstr); + + if(!m_allowDuplicatePresences) + { + if(guinfo != null && guinfo.Online && guinfo.LastRegionID != UUID.Zero) + { + if(SendAgentGodKillToRegion(UUID.Zero, agentID, guinfo)) + { + if(account != null) + m_log.InfoFormat( + "[GATEKEEPER SERVICE]: Login failed for {0} {1}, reason: already logged in", + account.FirstName, account.LastName); + reason = "You appear to be already logged in on the destination grid " + + "Please wait a a minute or two and retry. " + + "If this takes longer than a few minutes please contact the grid owner."; + return false; + } + } + } + } + m_log.DebugFormat("[GATEKEEPER SERVICE]: User {0} is ok", aCircuit.Name); bool isFirstLogin = false; @@ -389,26 +428,6 @@ namespace OpenSim.Services.HypergridService return false; } - m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence {0} is ok", aCircuit.Name); - - // Also login foreigners with GridUser service - if (m_GridUserService != null && account == null) - { - string userId = aCircuit.AgentID.ToString(); - string first = aCircuit.firstname, last = aCircuit.lastname; - if (last.StartsWith("@")) - { - string[] parts = aCircuit.firstname.Split('.'); - if (parts.Length >= 2) - { - first = parts[0]; - last = parts[1]; - } - } - - userId += ";" + aCircuit.ServiceURLs["HomeURI"] + ";" + first + " " + last; - m_GridUserService.LoggedIn(userId); - } } // @@ -465,7 +484,33 @@ namespace OpenSim.Services.HypergridService true, aCircuit.startpos, new List(), ctx, out reason)) return false; - return m_SimulationService.CreateAgent(source, destination, aCircuit, (uint)loginFlag, ctx, out reason); + bool didit = m_SimulationService.CreateAgent(source, destination, aCircuit, (uint)loginFlag, ctx, out reason); + + if(didit) + { + m_log.DebugFormat("[GATEKEEPER SERVICE]: Login presence {0} is ok", aCircuit.Name); + + if(!isFirstLogin && m_GridUserService != null && account == null) + { + // Also login foreigners with GridUser service + string userId = aCircuit.AgentID.ToString(); + string first = aCircuit.firstname, last = aCircuit.lastname; + if (last.StartsWith("@")) + { + string[] parts = aCircuit.firstname.Split('.'); + if (parts.Length >= 2) + { + first = parts[0]; + last = parts[1]; + } + } + + userId += ";" + aCircuit.ServiceURLs["HomeURI"] + ";" + first + " " + last; + m_GridUserService.LoggedIn(userId); + } + } + + return didit; } protected bool Authenticate(AgentCircuitData aCircuit) @@ -563,6 +608,40 @@ namespace OpenSim.Services.HypergridService return exception; } + private bool SendAgentGodKillToRegion(UUID scopeID, UUID agentID , GridUserInfo guinfo) + { + UUID regionID = guinfo.LastRegionID; + GridRegion regInfo = m_GridService.GetRegionByUUID(scopeID, regionID); + if(regInfo == null) + return false; + + string regURL = regInfo.ServerURI; + if(String.IsNullOrEmpty(regURL)) + return false; + + UUID guuid = new UUID("6571e388-6218-4574-87db-f9379718315e"); + + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = UUID.Zero.Guid; + msg.fromAgentID = guuid.Guid; + msg.toAgentID = agentID.Guid; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.fromAgentName = "GRID"; + msg.message = string.Format("New login detected"); + msg.dialog = 250; // God kick + msg.fromGroup = false; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = scopeID.Guid; + msg.binaryBucket = new byte[1] {0}; + InstantMessageServiceConnector.SendInstantMessage(regURL,msg); + + m_GridUserService.LoggedOut(agentID.ToString(), + UUID.Zero, guinfo.LastRegionID, guinfo.LastPosition, guinfo.LastLookAt); + + return true; + } #endregion } } diff --git a/OpenSim/Services/HypergridService/UserAgentService.cs b/OpenSim/Services/HypergridService/UserAgentService.cs index ba3cb2f72d..6f2cdd5e99 100644 --- a/OpenSim/Services/HypergridService/UserAgentService.cs +++ b/OpenSim/Services/HypergridService/UserAgentService.cs @@ -254,7 +254,6 @@ namespace OpenSim.Services.HypergridService } } - // Take the IP address + port of the gatekeeper (reg) plus the info of finalDestination GridRegion region = new GridRegion(gatekeeper); region.ServerURI = gatekeeper.ServerURI; diff --git a/OpenSim/Services/Interfaces/IGridService.cs b/OpenSim/Services/Interfaces/IGridService.cs index 66e58702fb..ead5d3c1ae 100644 --- a/OpenSim/Services/Interfaces/IGridService.cs +++ b/OpenSim/Services/Interfaces/IGridService.cs @@ -271,31 +271,6 @@ namespace OpenSim.Services.Interfaces m_serverURI = string.Empty; } - /* - public GridRegion(int regionLocX, int regionLocY, IPEndPoint internalEndPoint, string externalUri) - { - m_regionLocX = regionLocX; - m_regionLocY = regionLocY; - RegionSizeX = (int)Constants.RegionSize; - RegionSizeY = (int)Constants.RegionSize; - - m_internalEndPoint = internalEndPoint; - m_externalHostName = externalUri; - } - - public GridRegion(int regionLocX, int regionLocY, string externalUri, uint port) - { - m_regionLocX = regionLocX; - m_regionLocY = regionLocY; - RegionSizeX = (int)Constants.RegionSize; - RegionSizeY = (int)Constants.RegionSize; - - m_externalHostName = externalUri; - - m_internalEndPoint = new IPEndPoint(IPAddress.Parse("0.0.0.0"), (int)port); - } - */ - public GridRegion(uint xcell, uint ycell) { m_regionLocX = (int)Util.RegionToWorldLoc(xcell); @@ -487,45 +462,7 @@ namespace OpenSim.Services.Interfaces /// public IPEndPoint ExternalEndPoint { - get - { - // Old one defaults to IPv6 - //return new IPEndPoint(Dns.GetHostAddresses(m_externalHostName)[0], m_internalEndPoint.Port); - - IPAddress ia = null; - // If it is already an IP, don't resolve it - just return directly - if (IPAddress.TryParse(m_externalHostName, out ia)) - return new IPEndPoint(ia, m_internalEndPoint.Port); - - // Reset for next check - ia = null; - try - { - foreach (IPAddress Adr in Dns.GetHostAddresses(m_externalHostName)) - { - if (ia == null) - ia = Adr; - - if (Adr.AddressFamily == AddressFamily.InterNetwork) - { - ia = Adr; - break; - } - } - } - catch (SocketException e) - { - /*throw new Exception( - "Unable to resolve local hostname " + m_externalHostName + " innerException of type '" + - e + "' attached to this exception", e);*/ - // Don't throw a fatal exception here, instead, return Null and handle it in the caller. - // Reason is, on systems such as OSgrid it has occured that known hostnames stop - // resolving and thus make surrounding regions crash out with this exception. - return null; - } - - return new IPEndPoint(ia, m_internalEndPoint.Port); - } + get { return Util.getEndPoint(m_externalHostName, m_internalEndPoint.Port); } } public string ExternalHostName diff --git a/OpenSim/Services/LLLoginService/LLLoginResponse.cs b/OpenSim/Services/LLLoginService/LLLoginResponse.cs index 32e14a1d0a..823fd36470 100644 --- a/OpenSim/Services/LLLoginService/LLLoginResponse.cs +++ b/OpenSim/Services/LLLoginService/LLLoginResponse.cs @@ -82,9 +82,8 @@ namespace OpenSim.Services.LLLoginService "false"); AlreadyLoggedInProblem = new LLFailedLoginResponse("presence", "You appear to be already logged in. " + - "If this is not the case please wait for your session to timeout. " + - "If this takes longer than a few minutes please contact the grid owner. " + - "Please wait 5 minutes if you are going to connect to a region nearby to the region you were at previously.", + "Please wait a a minute or two and retry. " + + "If this takes longer than a few minutes please contact the grid owner. ", "false"); InternalError = new LLFailedLoginResponse("Internal Error", "Error generating Login Response", "false"); } diff --git a/OpenSim/Services/LLLoginService/LLLoginService.cs b/OpenSim/Services/LLLoginService/LLLoginService.cs index fc45f86d45..3ccdc9c013 100644 --- a/OpenSim/Services/LLLoginService/LLLoginService.cs +++ b/OpenSim/Services/LLLoginService/LLLoginService.cs @@ -40,6 +40,7 @@ using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Console; using OpenSim.Server.Base; +using OpenSim.Services.Connectors.InstantMessage; using OpenSim.Services.Interfaces; using GridRegion = OpenSim.Services.Interfaces.GridRegion; using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; @@ -89,6 +90,7 @@ namespace OpenSim.Services.LLLoginService protected string m_DeniedClients; protected string m_MessageUrl; protected string m_DSTZone; + protected bool m_allowDuplicatePresences = false; IConfig m_LoginServerConfig; // IConfig m_ClientsConfig; @@ -140,6 +142,11 @@ namespace OpenSim.Services.LLLoginService if (groupConfig != null) m_MaxAgentGroups = groupConfig.GetInt("MaxAgentGroups", 42); + IConfig presenceConfig = config.Configs["PresenceService"]; + if (presenceConfig != null) + { + m_allowDuplicatePresences = presenceConfig.GetBoolean("AllowDuplicatePresences", m_allowDuplicatePresences); + } // Clean up some of these vars if (m_MapTileURL != String.Empty) @@ -370,6 +377,29 @@ namespace OpenSim.Services.LLLoginService return LLFailedLoginResponse.UserProblem; } + if(account.PrincipalID == new UUID("6571e388-6218-4574-87db-f9379718315e")) + { + // really? + return LLFailedLoginResponse.UserProblem; + } + + string PrincipalIDstr = account.PrincipalID.ToString(); + GridUserInfo guinfo = m_GridUserService.GetGridUserInfo(PrincipalIDstr); + + if(!m_allowDuplicatePresences) + { + if(guinfo != null && guinfo.Online && guinfo.LastRegionID != UUID.Zero) + { + if(SendAgentGodKillToRegion(scopeID, account.PrincipalID, guinfo)) + { + m_log.InfoFormat( + "[LLOGIN SERVICE]: Login failed for {0} {1}, reason: already logged in", + firstName, lastName); + return LLFailedLoginResponse.AlreadyLoggedInProblem; + } + } + } + // // Get the user's inventory // @@ -406,7 +436,7 @@ namespace OpenSim.Services.LLLoginService // if (m_PresenceService != null) { - success = m_PresenceService.LoginAgent(account.PrincipalID.ToString(), session, secureSession); + success = m_PresenceService.LoginAgent(PrincipalIDstr, session, secureSession); if (!success) { @@ -421,7 +451,6 @@ namespace OpenSim.Services.LLLoginService // Change Online status and get the home region // GridRegion home = null; - GridUserInfo guinfo = m_GridUserService.LoggedIn(account.PrincipalID.ToString()); // We are only going to complain about no home if the user actually tries to login there, to avoid // spamming the console. @@ -504,6 +533,10 @@ namespace OpenSim.Services.LLLoginService return new LLFailedLoginResponse("key", reason, "false"); } + + // only now we can assume a login + guinfo = m_GridUserService.LoggedIn(PrincipalIDstr); + // Get Friends list FriendInfo[] friendsList = new FriendInfo[0]; if (m_FriendsService != null) @@ -832,6 +865,9 @@ namespace OpenSim.Services.LLLoginService reason = string.Empty; uint circuitCode = 0; AgentCircuitData aCircuit = null; + dest = null; + + bool success = false; if (m_UserAgentService == null) { @@ -842,28 +878,14 @@ namespace OpenSim.Services.LLLoginService simConnector = m_LocalSimulationService; else if (m_RemoteSimulationService != null) simConnector = m_RemoteSimulationService; - } - else // User Agent Service is on - { - if (gatekeeper == null) // login to local grid - { - if (hostName == string.Empty) - SetHostAndPort(m_GatekeeperURL); - gatekeeper = new GridRegion(destination); - gatekeeper.ExternalHostName = hostName; - gatekeeper.HttpPort = (uint)port; - gatekeeper.ServerURI = m_GatekeeperURL; - } - m_log.Debug("[LLLOGIN SERVICE]: no gatekeeper detected..... using " + m_GatekeeperURL); - } + if(simConnector == null) + return null; - bool success = false; - - if (m_UserAgentService == null && simConnector != null) - { circuitCode = (uint)Util.RandomClass.Next(); ; - aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, clientIP.Address.ToString(), viewer, channel, mac, id0); + aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, + clientIP.Address.ToString(), viewer, channel, mac, id0); + success = LaunchAgentDirectly(simConnector, destination, aCircuit, flags, out reason); if (!success && m_GridService != null) { @@ -885,10 +907,22 @@ namespace OpenSim.Services.LLLoginService } } - if (m_UserAgentService != null) + else { + if (gatekeeper == null) // login to local grid + { + if (hostName == string.Empty) + SetHostAndPort(m_GatekeeperURL); + + gatekeeper = new GridRegion(destination); + gatekeeper.ExternalHostName = hostName; + gatekeeper.HttpPort = (uint)port; + gatekeeper.ServerURI = m_GatekeeperURL; + } circuitCode = (uint)Util.RandomClass.Next(); ; - aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, clientIP.Address.ToString(), viewer, channel, mac, id0); + aCircuit = MakeAgent(destination, account, avatar, session, secureSession, circuitCode, position, + clientIP.Address.ToString(), viewer, channel, mac, id0); + aCircuit.teleportFlags |= (uint)flags; success = LaunchAgentIndirectly(gatekeeper, destination, aCircuit, clientIP, out reason); if (!success && m_GridService != null) @@ -1080,6 +1114,41 @@ namespace OpenSim.Services.LLLoginService break; } } + + private bool SendAgentGodKillToRegion(UUID scopeID, UUID agentID , GridUserInfo guinfo) + { + UUID regionID = guinfo.LastRegionID; + GridRegion regInfo = m_GridService.GetRegionByUUID(scopeID, regionID); + if(regInfo == null) + return false; + + string regURL = regInfo.ServerURI; + if(String.IsNullOrEmpty(regURL)) + return false; + + UUID guuid = new UUID("6571e388-6218-4574-87db-f9379718315e"); + + GridInstantMessage msg = new GridInstantMessage(); + msg.imSessionID = UUID.Zero.Guid; + msg.fromAgentID = guuid.Guid; + msg.toAgentID = agentID.Guid; + msg.timestamp = (uint)Util.UnixTimeSinceEpoch(); + msg.fromAgentName = "GRID"; + msg.message = string.Format("New login detected"); + msg.dialog = 250; // God kick + msg.fromGroup = false; + msg.offline = (byte)0; + msg.ParentEstateID = 0; + msg.Position = Vector3.Zero; + msg.RegionID = scopeID.Guid; + msg.binaryBucket = new byte[1] {0}; + InstantMessageServiceConnector.SendInstantMessage(regURL,msg); + + m_GridUserService.LoggedOut(agentID.ToString(), + UUID.Zero, guinfo.LastRegionID, guinfo.LastPosition, guinfo.LastLookAt); + + return true; + } } #endregion diff --git a/OpenSim/Services/UserAccountService/UserAccountService.cs b/OpenSim/Services/UserAccountService/UserAccountService.cs index f6b003a1ad..48929ee5fd 100644 --- a/OpenSim/Services/UserAccountService/UserAccountService.cs +++ b/OpenSim/Services/UserAccountService/UserAccountService.cs @@ -43,6 +43,7 @@ namespace OpenSim.Services.UserAccountService public class UserAccountService : UserAccountServiceBase, IUserAccountService { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly UUID UUID_GRID_GOD = new UUID("6571e388-6218-4574-87db-f9379718315e"); private static UserAccountService m_RootInstance; /// @@ -85,38 +86,63 @@ namespace OpenSim.Services.UserAccountService m_CreateDefaultAvatarEntries = userConfig.GetBoolean("CreateDefaultAvatarEntries", false); - // In case there are several instances of this class in the same process, - // the console commands are only registered for the root instance - if (m_RootInstance == null && MainConsole.Instance != null) + // create a system grid god account + UserAccount ggod = GetUserAccount(UUID.Zero, UUID_GRID_GOD); + if(ggod == null) + { + UserAccountData d = new UserAccountData(); + + d.FirstName = "GRID"; + d.LastName = "SERVICES"; + d.PrincipalID = UUID_GRID_GOD; + d.ScopeID = UUID.Zero; + d.Data = new Dictionary(); + d.Data["Email"] = string.Empty; + d.Data["Created"] = Util.UnixTimeSinceEpoch().ToString(); + d.Data["UserLevel"] = "240"; + d.Data["UserFlags"] = "0"; + d.Data["ServiceURLs"] = string.Empty; + + m_Database.Store(d); + } + + if (m_RootInstance == null) { m_RootInstance = this; - MainConsole.Instance.Commands.AddCommand("Users", false, - "create user", - "create user [ [ [ [ [ []]]]]]", - "Create a new user", HandleCreateUser); - MainConsole.Instance.Commands.AddCommand("Users", false, - "reset user password", - "reset user password [ [ []]]", - "Reset a user password", HandleResetUserPassword); + // In case there are several instances of this class in the same process, + // the console commands are only registered for the root instance + if (MainConsole.Instance != null) + { + + MainConsole.Instance.Commands.AddCommand("Users", false, + "create user", + "create user [ [ [ [ [ []]]]]]", + "Create a new user", HandleCreateUser); - MainConsole.Instance.Commands.AddCommand("Users", false, - "reset user email", - "reset user email [ [ []]]", - "Reset a user email address", HandleResetUserEmail); + MainConsole.Instance.Commands.AddCommand("Users", false, + "reset user password", + "reset user password [ [ []]]", + "Reset a user password", HandleResetUserPassword); - MainConsole.Instance.Commands.AddCommand("Users", false, - "set user level", - "set user level [ [ []]]", - "Set user level. If >= 200 and 'allow_grid_gods = true' in OpenSim.ini, " - + "this account will be treated as god-moded. " - + "It will also affect the 'login level' command. ", - HandleSetUserLevel); + MainConsole.Instance.Commands.AddCommand("Users", false, + "reset user email", + "reset user email [ [ []]]", + "Reset a user email address", HandleResetUserEmail); - MainConsole.Instance.Commands.AddCommand("Users", false, - "show account", - "show account ", - "Show account details for the given user", HandleShowAccount); + MainConsole.Instance.Commands.AddCommand("Users", false, + "set user level", + "set user level [ [ []]]", + "Set user level. If >= 200 and 'allow_grid_gods = true' in OpenSim.ini, " + + "this account will be treated as god-moded. " + + "It will also affect the 'login level' command. ", + HandleSetUserLevel); + + MainConsole.Instance.Commands.AddCommand("Users", false, + "show account", + "show account ", + "Show account details for the given user", HandleShowAccount); + } } } @@ -640,9 +666,11 @@ namespace OpenSim.Services.UserAccountService m_log.DebugFormat("[USER ACCOUNT SERVICE]: Creating default appearance items for {0}", principalID); InventoryFolderBase bodyPartsFolder = m_InventoryService.GetFolderForType(principalID, FolderType.BodyPart); + // Get Current Outfit folder + InventoryFolderBase currentOutfitFolder = m_InventoryService.GetFolderForType(principalID, FolderType.CurrentOutfit); InventoryItemBase eyes = new InventoryItemBase(UUID.Random(), principalID); - eyes.AssetID = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); + eyes.AssetID = AvatarWearable.DEFAULT_EYES_ASSET; eyes.Name = "Default Eyes"; eyes.CreatorId = principalID.ToString(); eyes.AssetType = (int)AssetType.Bodypart; @@ -655,6 +683,7 @@ namespace OpenSim.Services.UserAccountService eyes.NextPermissions = (uint)PermissionMask.All; eyes.Flags = (uint)WearableType.Eyes; m_InventoryService.AddItem(eyes); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Eyes, eyes.Name, eyes.ID, principalID, currentOutfitFolder.ID); InventoryItemBase shape = new InventoryItemBase(UUID.Random(), principalID); shape.AssetID = AvatarWearable.DEFAULT_BODY_ASSET; @@ -670,6 +699,7 @@ namespace OpenSim.Services.UserAccountService shape.NextPermissions = (uint)PermissionMask.All; shape.Flags = (uint)WearableType.Shape; m_InventoryService.AddItem(shape); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Shape, shape.Name, shape.ID, principalID, currentOutfitFolder.ID); InventoryItemBase skin = new InventoryItemBase(UUID.Random(), principalID); skin.AssetID = AvatarWearable.DEFAULT_SKIN_ASSET; @@ -685,6 +715,7 @@ namespace OpenSim.Services.UserAccountService skin.NextPermissions = (uint)PermissionMask.All; skin.Flags = (uint)WearableType.Skin; m_InventoryService.AddItem(skin); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Skin, skin.Name, skin.ID, principalID, currentOutfitFolder.ID); InventoryItemBase hair = new InventoryItemBase(UUID.Random(), principalID); hair.AssetID = AvatarWearable.DEFAULT_HAIR_ASSET; @@ -700,6 +731,7 @@ namespace OpenSim.Services.UserAccountService hair.NextPermissions = (uint)PermissionMask.All; hair.Flags = (uint)WearableType.Hair; m_InventoryService.AddItem(hair); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Hair, hair.Name, hair.ID, principalID, currentOutfitFolder.ID); InventoryFolderBase clothingFolder = m_InventoryService.GetFolderForType(principalID, FolderType.Clothing); @@ -717,6 +749,7 @@ namespace OpenSim.Services.UserAccountService shirt.NextPermissions = (uint)PermissionMask.All; shirt.Flags = (uint)WearableType.Shirt; m_InventoryService.AddItem(shirt); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Shirt, shirt.Name, shirt.ID, principalID, currentOutfitFolder.ID); InventoryItemBase pants = new InventoryItemBase(UUID.Random(), principalID); pants.AssetID = AvatarWearable.DEFAULT_PANTS_ASSET; @@ -732,6 +765,7 @@ namespace OpenSim.Services.UserAccountService pants.NextPermissions = (uint)PermissionMask.All; pants.Flags = (uint)WearableType.Pants; m_InventoryService.AddItem(pants); + CreateCurrentOutfitLink((int)InventoryType.Wearable, (uint)WearableType.Pants, pants.Name, pants.ID, principalID, currentOutfitFolder.ID); if (m_AvatarService != null) { @@ -815,6 +849,8 @@ namespace OpenSim.Services.UserAccountService { // Get Clothing folder of receiver InventoryFolderBase destinationFolder = m_InventoryService.GetFolderForType(destination, FolderType.Clothing); + // Get Current Outfit folder + InventoryFolderBase currentOutfitFolder = m_InventoryService.GetFolderForType(destination, FolderType.CurrentOutfit); if (destinationFolder == null) throw new Exception("Cannot locate folder(s)"); @@ -841,6 +877,7 @@ namespace OpenSim.Services.UserAccountService for (int i = 0; i < wearables.Length; i++) { wearable = wearables[i]; + m_log.DebugFormat("[XXX]: Getting item {0} from avie {1}", wearable[0].ItemID, source); if (wearable[0].ItemID != UUID.Zero) { // Get inventory item and copy it @@ -878,6 +915,9 @@ namespace OpenSim.Services.UserAccountService AvatarWearable newWearable = new AvatarWearable(); newWearable.Wear(destinationItem.ID, wearable[0].AssetID); avatarAppearance.SetWearable(i, newWearable); + + // Add to Current Outfit + CreateCurrentOutfitLink((int)InventoryType.Wearable, item.Flags, item.Name, destinationItem.ID, destination, currentOutfitFolder.ID); } else { @@ -930,6 +970,9 @@ namespace OpenSim.Services.UserAccountService // Attach item avatarAppearance.SetAttachment(attachpoint, destinationItem.ID, destinationItem.AssetID); m_log.DebugFormat("[USER ACCOUNT SERVICE]: Attached {0}", destinationItem.ID); + + // Add to Current Outfit + CreateCurrentOutfitLink(destinationItem.InvType, item.Flags, item.Name, destinationItem.ID, destination, currentOutfitFolder.ID); } else { @@ -939,6 +982,30 @@ namespace OpenSim.Services.UserAccountService } } + protected void CreateCurrentOutfitLink(int invType, uint itemType, string name, UUID itemID, UUID userID, UUID currentOutfitFolderUUID) + { + UUID LinkInvItem = UUID.Random(); + InventoryItemBase itembase = new InventoryItemBase(LinkInvItem, userID) + { + AssetID = itemID, + AssetType = (int)AssetType.Link, + CreatorId = userID.ToString(), + InvType = invType, + Description = "", + //Folder = m_InventoryService.GetFolderForType(userID, FolderType.CurrentOutfit).ID, + Folder = currentOutfitFolderUUID, + Flags = itemType, + Name = name, + BasePermissions = (uint)PermissionMask.Copy, + CurrentPermissions = (uint)PermissionMask.Copy, + EveryOnePermissions = (uint)PermissionMask.Copy, + GroupPermissions = (uint)PermissionMask.Copy, + NextPermissions = (uint)PermissionMask.Copy + }; + + m_InventoryService.AddItem(itembase); + } + /// /// Apply next owner permissions. /// diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index fbd7e90caa..7902fb1d60 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -626,6 +626,7 @@ namespace OpenSim.Tests.Common //part.ObjectFlags |= (uint)PrimFlags.Phantom; scene.AddNewSceneObject(so, true); + so.InvalidateDeepEffectivePerms(); return so; } @@ -652,6 +653,7 @@ namespace OpenSim.Tests.Common SceneObjectGroup so = CreateSceneObject(parts, ownerId, partNamePrefix, uuidTail); scene.AddNewSceneObject(so, false); + so.InvalidateDeepEffectivePerms(); return so; } diff --git a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs index 5a46201120..e18866598c 100644 --- a/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/UserInventoryHelpers.cs @@ -129,9 +129,9 @@ namespace OpenSim.Tests.Common item.AssetType = asset.Type; item.InvType = (int)itemType; item.BasePermissions = (uint)OpenMetaverse.PermissionMask.All | - (uint)(Framework.PermissionMask.foldedMask | Framework.PermissionMask.foldedCopy | Framework.PermissionMask.foldedModify | Framework.PermissionMask.foldedTransfer); + (uint)(Framework.PermissionMask.FoldedMask | Framework.PermissionMask.FoldedCopy | Framework.PermissionMask.FoldedModify | Framework.PermissionMask.FoldedTransfer); item.CurrentPermissions = (uint)OpenMetaverse.PermissionMask.All | - (uint)(Framework.PermissionMask.foldedMask | Framework.PermissionMask.foldedCopy | Framework.PermissionMask.foldedModify | Framework.PermissionMask.foldedTransfer); + (uint)(Framework.PermissionMask.FoldedMask | Framework.PermissionMask.FoldedCopy | Framework.PermissionMask.FoldedModify | Framework.PermissionMask.FoldedTransfer); InventoryFolderBase folder = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, userId, path)[0]; @@ -371,4 +371,4 @@ namespace OpenSim.Tests.Common return InventoryArchiveUtils.FindItemsByPath(inventoryService, userId, path); } } -} \ No newline at end of file +} diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index e2f57b531b..a8359255ad 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -760,7 +760,11 @@ namespace OpenSim.Tests.Common { } - public void SendAvatarDataImmediate(ISceneEntity avatar) + public void SendEntityFullUpdateImmediate(ISceneEntity ent) + { + } + + public void SendEntityTerseUpdateImmediate(ISceneEntity ent) { } diff --git a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs index 3e00d82d9a..f2ce064dc1 100644 --- a/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs +++ b/OpenSim/Tests/Common/Mock/TestEventQueueGetModule.cs @@ -108,12 +108,12 @@ namespace OpenSim.Tests.Common AddEvent(avatarID, "Enqueue", o); return true; } - +/* public void DisableSimulator(ulong handle, UUID avatarID) { AddEvent(avatarID, "DisableSimulator", handle); } - +*/ public void EnableSimulator (ulong handle, IPEndPoint endPoint, UUID avatarID, int regionSizeX, int regionSizeY) { AddEvent(avatarID, "EnableSimulator", handle); diff --git a/OpenSim/Tests/Common/Mock/TestGroupsDataPlugin.cs b/OpenSim/Tests/Common/Mock/TestGroupsDataPlugin.cs new file mode 100644 index 0000000000..8e2d8e6c98 --- /dev/null +++ b/OpenSim/Tests/Common/Mock/TestGroupsDataPlugin.cs @@ -0,0 +1,339 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; + +using OpenMetaverse; +using OpenSim.Data; + +namespace OpenSim.Tests.Common.Mock +{ + public class TestGroupsDataPlugin : IGroupsData + { + class CompositeKey + { + private readonly string _key; + public string Key + { + get { return _key; } + } + + public CompositeKey(UUID _k1, string _k2) + { + _key = _k1.ToString() + _k2; + } + + public CompositeKey(UUID _k1, string _k2, string _k3) + { + _key = _k1.ToString() + _k2 + _k3; + } + + public override bool Equals(object obj) + { + if (obj is CompositeKey) + { + return Key == ((CompositeKey)obj).Key; + } + return false; + } + + public override int GetHashCode() + { + return base.GetHashCode(); + } + + public override string ToString() + { + return Key; + } + } + + private Dictionary m_Groups; + private Dictionary m_Membership; + private Dictionary m_Roles; + private Dictionary m_RoleMembership; + private Dictionary m_Invites; + private Dictionary m_Notices; + private Dictionary m_Principals; + + public TestGroupsDataPlugin(string connectionString, string realm) + { + m_Groups = new Dictionary(); + m_Membership = new Dictionary(); + m_Roles = new Dictionary(); + m_RoleMembership = new Dictionary(); + m_Invites = new Dictionary(); + m_Notices = new Dictionary(); + m_Principals = new Dictionary(); + } + + #region groups table + public bool StoreGroup(GroupData data) + { + return false; + } + + public GroupData RetrieveGroup(UUID groupID) + { + if (m_Groups.ContainsKey(groupID)) + return m_Groups[groupID]; + + return null; + } + + public GroupData RetrieveGroup(string name) + { + return m_Groups.Values.First(g => g.Data.ContainsKey("Name") && g.Data["Name"] == name); + } + + public GroupData[] RetrieveGroups(string pattern) + { + if (string.IsNullOrEmpty(pattern)) + pattern = "1"; + + IEnumerable groups = m_Groups.Values.Where(g => g.Data.ContainsKey("Name") && (g.Data["Name"].StartsWith(pattern) || g.Data["Name"].EndsWith(pattern))); + + return (groups != null) ? groups.ToArray() : new GroupData[0]; + } + + public bool DeleteGroup(UUID groupID) + { + return m_Groups.Remove(groupID); + } + + public int GroupsCount() + { + return m_Groups.Count; + } + #endregion + + #region membership table + public MembershipData RetrieveMember(UUID groupID, string pricipalID) + { + CompositeKey dkey = new CompositeKey(groupID, pricipalID); + if (m_Membership.ContainsKey(dkey)) + return m_Membership[dkey]; + + return null; + } + + public MembershipData[] RetrieveMembers(UUID groupID) + { + IEnumerable keys = m_Membership.Keys.Where(k => k.Key.StartsWith(groupID.ToString())); + return keys.Where(m_Membership.ContainsKey).Select(x => m_Membership[x]).ToArray(); + } + + public MembershipData[] RetrieveMemberships(string principalID) + { + IEnumerable keys = m_Membership.Keys.Where(k => k.Key.EndsWith(principalID.ToString())); + return keys.Where(m_Membership.ContainsKey).Select(x => m_Membership[x]).ToArray(); + } + + public MembershipData[] RetrievePrincipalGroupMemberships(string principalID) + { + return RetrieveMemberships(principalID); + } + + public MembershipData RetrievePrincipalGroupMembership(string principalID, UUID groupID) + { + CompositeKey dkey = new CompositeKey(groupID, principalID); + if (m_Membership.ContainsKey(dkey)) + return m_Membership[dkey]; + return null; + } + + public bool StoreMember(MembershipData data) + { + CompositeKey dkey = new CompositeKey(data.GroupID, data.PrincipalID); + m_Membership[dkey] = data; + return true; + } + + public bool DeleteMember(UUID groupID, string principalID) + { + CompositeKey dkey = new CompositeKey(groupID, principalID); + if (m_Membership.ContainsKey(dkey)) + return m_Membership.Remove(dkey); + + return false; + } + + public int MemberCount(UUID groupID) + { + return m_Membership.Count; + } + #endregion + + #region roles table + public bool StoreRole(RoleData data) + { + CompositeKey dkey = new CompositeKey(data.GroupID, data.RoleID.ToString()); + m_Roles[dkey] = data; + return true; + } + + public RoleData RetrieveRole(UUID groupID, UUID roleID) + { + CompositeKey dkey = new CompositeKey(groupID, roleID.ToString()); + if (m_Roles.ContainsKey(dkey)) + return m_Roles[dkey]; + + return null; + } + + public RoleData[] RetrieveRoles(UUID groupID) + { + IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString())); + return keys.Where(m_Roles.ContainsKey).Select(x => m_Roles[x]).ToArray(); + } + + public bool DeleteRole(UUID groupID, UUID roleID) + { + CompositeKey dkey = new CompositeKey(groupID, roleID.ToString()); + if (m_Roles.ContainsKey(dkey)) + return m_Roles.Remove(dkey); + + return false; + } + + public int RoleCount(UUID groupID) + { + return m_Roles.Count; + } + #endregion + + #region rolememberhip table + public RoleMembershipData[] RetrieveRolesMembers(UUID groupID) + { + IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString())); + return keys.Where(m_RoleMembership.ContainsKey).Select(x => m_RoleMembership[x]).ToArray(); + } + + public RoleMembershipData[] RetrieveRoleMembers(UUID groupID, UUID roleID) + { + IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString() + roleID.ToString())); + return keys.Where(m_RoleMembership.ContainsKey).Select(x => m_RoleMembership[x]).ToArray(); + } + + public RoleMembershipData[] RetrieveMemberRoles(UUID groupID, string principalID) + { + IEnumerable keys = m_Roles.Keys.Where(k => k.Key.StartsWith(groupID.ToString()) && k.Key.EndsWith(principalID)); + return keys.Where(m_RoleMembership.ContainsKey).Select(x => m_RoleMembership[x]).ToArray(); + } + + public RoleMembershipData RetrieveRoleMember(UUID groupID, UUID roleID, string principalID) + { + CompositeKey dkey = new CompositeKey(groupID, roleID.ToString(), principalID); + if (m_RoleMembership.ContainsKey(dkey)) + return m_RoleMembership[dkey]; + + return null; + } + + public int RoleMemberCount(UUID groupID, UUID roleID) + { + return m_RoleMembership.Count; + } + + public bool StoreRoleMember(RoleMembershipData data) + { + CompositeKey dkey = new CompositeKey(data.GroupID, data.RoleID.ToString(), data.PrincipalID); + m_RoleMembership[dkey] = data; + return true; + } + + public bool DeleteRoleMember(RoleMembershipData data) + { + CompositeKey dkey = new CompositeKey(data.GroupID, data.RoleID.ToString(), data.PrincipalID); + if (m_RoleMembership.ContainsKey(dkey)) + return m_RoleMembership.Remove(dkey); + + return false; + } + + public bool DeleteMemberAllRoles(UUID groupID, string principalID) + { + List keys = m_RoleMembership.Keys.Where(k => k.Key.StartsWith(groupID.ToString()) && k.Key.EndsWith(principalID)).ToList(); + foreach (CompositeKey k in keys) + m_RoleMembership.Remove(k); + return true; + } + #endregion + + #region principals table + public bool StorePrincipal(PrincipalData data) + { + m_Principals[data.PrincipalID] = data; + return true; + } + + public PrincipalData RetrievePrincipal(string principalID) + { + if (m_Principals.ContainsKey(principalID)) + return m_Principals[principalID]; + + return null; + } + + public bool DeletePrincipal(string principalID) + { + if (m_Principals.ContainsKey(principalID)) + return m_Principals.Remove(principalID); + return false; + } + #endregion + + #region invites table + public bool StoreInvitation(InvitationData data) + { + return false; + } + + public InvitationData RetrieveInvitation(UUID inviteID) + { + return null; + } + + public InvitationData RetrieveInvitation(UUID groupID, string principalID) + { + return null; + } + + public bool DeleteInvite(UUID inviteID) + { + return false; + } + + public void DeleteOldInvites() + { + } + #endregion + + #region notices table + public bool StoreNotice(NoticeData data) + { + return false; + } + + public NoticeData RetrieveNotice(UUID noticeID) + { + return null; + } + + public NoticeData[] RetrieveNotices(UUID groupID) + { + return new NoticeData[0]; + } + + public bool DeleteNotice(UUID noticeID) + { + return false; + } + + public void DeleteOldNotices() + { + } + #endregion + + } +} diff --git a/OpenSim/Tests/Common/Mock/TestLandChannel.cs b/OpenSim/Tests/Common/Mock/TestLandChannel.cs index 3d44a33352..05db03fefe 100644 --- a/OpenSim/Tests/Common/Mock/TestLandChannel.cs +++ b/OpenSim/Tests/Common/Mock/TestLandChannel.cs @@ -96,6 +96,11 @@ namespace OpenSim.Tests.Common return GetNoLand(); } + public ILandObject GetLandObject(UUID ID) + { + return GetNoLand(); + } + public ILandObject GetLandObject(float x, float y) { return GetNoLand(); @@ -104,6 +109,7 @@ namespace OpenSim.Tests.Common public bool IsLandPrimCountTainted() { return false; } public bool IsForcefulBansAllowed() { return false; } public void UpdateLandObject(int localID, LandData data) {} + public void SendParcelsOverlay(IClientAPI client) {} public void ReturnObjectsInParcel(int localID, uint returnType, UUID[] agentIDs, UUID[] taskIDs, IClientAPI remoteClient) {} public void setParcelObjectMaxOverride(overrideParcelMaxPrimCountDelegate overrideDel) {} public void setSimulatorObjectMaxOverride(overrideSimulatorMaxPrimCountDelegate overrideDel) {} diff --git a/OpenSim/Tests/Permissions/Common.cs b/OpenSim/Tests/Permissions/Common.cs new file mode 100644 index 0000000000..4ecce383e4 --- /dev/null +++ b/OpenSim/Tests/Permissions/Common.cs @@ -0,0 +1,374 @@ +/* + * 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.Threading; +using Nini.Config; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.CoreModules.World.Permissions; +using OpenSim.Region.CoreModules.Avatar.Inventory.Transfer; +using OpenSim.Region.CoreModules.Framework.InventoryAccess; +using OpenSim.Services.Interfaces; +using OpenSim.Tests.Common; +using PermissionMask = OpenSim.Framework.PermissionMask; + +namespace OpenSim.Tests.Permissions +{ + [SetUpFixture] + public class Common : OpenSimTestCase + { + public static Common TheInstance; + + public static TestScene TheScene + { + get { return TheInstance.m_Scene; } + } + + public static ScenePresence[] TheAvatars + { + get { return TheInstance.m_Avatars; } + } + + private static string Perms = "Owner: {0}; Group: {1}; Everyone: {2}; Next: {3}"; + private TestScene m_Scene; + private ScenePresence[] m_Avatars = new ScenePresence[3]; + + [SetUp] + public override void SetUp() + { + if (TheInstance == null) + TheInstance = this; + + base.SetUp(); + TestHelpers.EnableLogging(); + + IConfigSource config = new IniConfigSource(); + config.AddConfig("Messaging"); + config.Configs["Messaging"].Set("InventoryTransferModule", "InventoryTransferModule"); + + config.AddConfig("Modules"); + config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); + + config.AddConfig("InventoryService"); + config.Configs["InventoryService"].Set("LocalServiceModule", "OpenSim.Services.InventoryService.dll:XInventoryService"); + config.Configs["InventoryService"].Set("StorageProvider", "OpenSim.Tests.Common.dll:TestXInventoryDataPlugin"); + + config.AddConfig("Groups"); + config.Configs["Groups"].Set("Enabled", "true"); + config.Configs["Groups"].Set("Module", "Groups Module V2"); + config.Configs["Groups"].Set("StorageProvider", "OpenSim.Tests.Common.dll:TestGroupsDataPlugin"); + config.Configs["Groups"].Set("ServicesConnectorModule", "Groups Local Service Connector"); + config.Configs["Groups"].Set("LocalService", "local"); + + m_Scene = new SceneHelpers().SetupScene("Test", UUID.Random(), 1000, 1000, config); + // Add modules + SceneHelpers.SetupSceneModules(m_Scene, config, new DefaultPermissionsModule(), new InventoryTransferModule(), new BasicInventoryAccessModule()); + + SetUpBasicEnvironment(); + } + + /// + /// The basic environment consists of: + /// - 3 avatars: A1, A2, A3 + /// - 6 simple boxes inworld belonging to A0 and with Next Owner perms: + /// C, CT, MC, MCT, MT, T + /// - Copies of all of these boxes in A0's inventory in the Objects folder + /// - One additional box inworld and in A0's inventory which is a copy of MCT, but + /// with C removed in inventory. This one is called MCT-C + /// + private void SetUpBasicEnvironment() + { + Console.WriteLine("===> SetUpBasicEnvironment <==="); + + // Add 3 avatars + for (int i = 0; i < 3; i++) + { + UUID id = TestHelpers.ParseTail(i + 1); + + m_Avatars[i] = AddScenePresence("Bot", "Bot_" + (i+1), id); + Assert.That(m_Avatars[i], Is.Not.Null); + Assert.That(m_Avatars[i].IsChildAgent, Is.False); + Assert.That(m_Avatars[i].UUID, Is.EqualTo(id)); + Assert.That(m_Scene.GetScenePresences().Count, Is.EqualTo(i + 1)); + } + + AddA1Object("Box C", 10, PermissionMask.Copy); + AddA1Object("Box CT", 11, PermissionMask.Copy | PermissionMask.Transfer); + AddA1Object("Box MC", 12, PermissionMask.Modify | PermissionMask.Copy); + AddA1Object("Box MCT", 13, PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer); + AddA1Object("Box MT", 14, PermissionMask.Modify | PermissionMask.Transfer); + AddA1Object("Box T", 15, PermissionMask.Transfer); + + // MCT-C + AddA1Object("Box MCT-C", 16, PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer); + + Thread.Sleep(5000); + + InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(m_Scene.InventoryService, m_Avatars[0].UUID, "Objects"); + List items = m_Scene.InventoryService.GetFolderItems(m_Avatars[0].UUID, objsFolder.ID); + Assert.That(items.Count, Is.EqualTo(7)); + + RevokePermission(0, "Box MCT-C", PermissionMask.Copy); + } + + private ScenePresence AddScenePresence(string first, string last, UUID id) + { + UserAccount ua1 = UserAccountHelpers.CreateUserWithInventory(m_Scene, first, last, id, "pw"); + ScenePresence sp = SceneHelpers.AddScenePresence(m_Scene, id); + Assert.That(m_Scene.AuthenticateHandler.GetAgentCircuitData(id), Is.Not.Null); + + return sp; + } + + private void AddA1Object(string name, int suffix, PermissionMask nextOwnerPerms) + { + // Create a Box. Default permissions are just T + SceneObjectGroup box = AddSceneObject(name, suffix, 1, m_Avatars[0].UUID); + Assert.True((box.RootPart.NextOwnerMask & (int)PermissionMask.Copy) == 0); + Assert.True((box.RootPart.NextOwnerMask & (int)PermissionMask.Modify) == 0); + Assert.True((box.RootPart.NextOwnerMask & (int)PermissionMask.Transfer) != 0); + + // field = 16 is NextOwner + // set = 1 means add the permission; set = 0 means remove permission + + if ((nextOwnerPerms & PermissionMask.Copy) != 0) + m_Scene.HandleObjectPermissionsUpdate((IClientAPI)m_Avatars[0].ClientView, m_Avatars[0].UUID, + ((IClientAPI)(m_Avatars[0].ClientView)).SessionId, 16, box.LocalId, (uint)PermissionMask.Copy, 1); + + if ((nextOwnerPerms & PermissionMask.Modify) != 0) + m_Scene.HandleObjectPermissionsUpdate((IClientAPI)m_Avatars[0].ClientView, m_Avatars[0].UUID, + ((IClientAPI)(m_Avatars[0].ClientView)).SessionId, 16, box.LocalId, (uint)PermissionMask.Modify, 1); + + if ((nextOwnerPerms & PermissionMask.Transfer) == 0) + m_Scene.HandleObjectPermissionsUpdate((IClientAPI)m_Avatars[0].ClientView, m_Avatars[0].UUID, + ((IClientAPI)(m_Avatars[0].ClientView)).SessionId, 16, box.LocalId, (uint)PermissionMask.Transfer, 0); + + PrintPerms(box); + AssertPermissions(nextOwnerPerms, (PermissionMask)box.RootPart.NextOwnerMask, box.OwnerID.ToString().Substring(34) + " : " + box.Name); + + TakeCopyToInventory(0, box); + + } + + public void RevokePermission(int ownerIndex, string name, PermissionMask perm) + { + InventoryItemBase item = Common.TheInstance.GetItemFromInventory(m_Avatars[ownerIndex].UUID, "Objects", name); + Assert.That(item, Is.Not.Null); + + // Clone it, so to avoid aliasing -- just like the viewer does. + InventoryItemBase clone = Common.TheInstance.CloneInventoryItem(item); + // Revoke the permission in this copy + clone.NextPermissions &= ~(uint)perm; + Common.TheInstance.AssertPermissions((PermissionMask)clone.NextPermissions & ~perm, + (PermissionMask)clone.NextPermissions, Common.TheInstance.IdStr(clone)); + Assert.That(clone.ID == item.ID); + + // Update properties of the item in inventory. This should affect the original item above. + Common.TheScene.UpdateInventoryItemAsset(m_Avatars[ownerIndex].ControllingClient, UUID.Zero, clone.ID, clone); + + item = Common.TheInstance.GetItemFromInventory(m_Avatars[ownerIndex].UUID, "Objects", name); + Assert.That(item, Is.Not.Null); + Common.TheInstance.PrintPerms(item); + Common.TheInstance.AssertPermissions((PermissionMask)item.NextPermissions & ~perm, + (PermissionMask)item.NextPermissions, Common.TheInstance.IdStr(item)); + + } + + public void PrintPerms(SceneObjectGroup sog) + { + Console.WriteLine("SOG " + sog.Name + " (" + sog.OwnerID.ToString().Substring(34) + "): " + + String.Format(Perms, (PermissionMask)sog.EffectiveOwnerPerms, + (PermissionMask)sog.EffectiveGroupPerms, (PermissionMask)sog.EffectiveEveryOnePerms, (PermissionMask)sog.RootPart.NextOwnerMask)); + + } + + public void PrintPerms(InventoryItemBase item) + { + Console.WriteLine("Inv " + item.Name + " (" + item.Owner.ToString().Substring(34) + "): " + + String.Format(Perms, (PermissionMask)item.BasePermissions, + (PermissionMask)item.GroupPermissions, (PermissionMask)item.EveryOnePermissions, (PermissionMask)item.NextPermissions)); + + } + + public void AssertPermissions(PermissionMask desired, PermissionMask actual, string message) + { + if ((desired & PermissionMask.Copy) != 0) + Assert.True((actual & PermissionMask.Copy) != 0, message); + else + Assert.True((actual & PermissionMask.Copy) == 0, message); + + if ((desired & PermissionMask.Modify) != 0) + Assert.True((actual & PermissionMask.Modify) != 0, message); + else + Assert.True((actual & PermissionMask.Modify) == 0, message); + + if ((desired & PermissionMask.Transfer) != 0) + Assert.True((actual & PermissionMask.Transfer) != 0, message); + else + Assert.True((actual & PermissionMask.Transfer) == 0, message); + + } + + public SceneObjectGroup AddSceneObject(string name, int suffix, int partsToTestCount, UUID ownerID) + { + SceneObjectGroup so = SceneHelpers.CreateSceneObject(partsToTestCount, ownerID, name, suffix); + so.Name = name; + so.Description = name; + + Assert.That(m_Scene.AddNewSceneObject(so, false), Is.True); + SceneObjectGroup retrievedSo = m_Scene.GetSceneObjectGroup(so.UUID); + + // If the parts have the same UUID then we will consider them as one and the same + Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount)); + + return so; + } + + public void TakeCopyToInventory(int userIndex, SceneObjectGroup sog) + { + InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(m_Scene.InventoryService, m_Avatars[userIndex].UUID, "Objects"); + Assert.That(objsFolder, Is.Not.Null); + + List localIds = new List(); localIds.Add(sog.LocalId); + // This is an async operation + m_Scene.DeRezObjects((IClientAPI)m_Avatars[userIndex].ClientView, localIds, m_Avatars[userIndex].UUID, DeRezAction.TakeCopy, objsFolder.ID); + } + + public InventoryItemBase GetItemFromInventory(UUID userID, string folderName, string itemName) + { + InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(m_Scene.InventoryService, userID, folderName); + Assert.That(objsFolder, Is.Not.Null); + List items = m_Scene.InventoryService.GetFolderItems(userID, objsFolder.ID); + InventoryItemBase item = items.Find(i => i.Name == itemName); + Assert.That(item, Is.Not.Null); + + return item; + } + + public InventoryItemBase CloneInventoryItem(InventoryItemBase item) + { + InventoryItemBase clone = new InventoryItemBase(item.ID); + clone.Name = item.Name; + clone.Description = item.Description; + clone.AssetID = item.AssetID; + clone.AssetType = item.AssetType; + clone.BasePermissions = item.BasePermissions; + clone.CreatorId = item.CreatorId; + clone.CurrentPermissions = item.CurrentPermissions; + clone.EveryOnePermissions = item.EveryOnePermissions; + clone.Flags = item.Flags; + clone.Folder = item.Folder; + clone.GroupID = item.GroupID; + clone.GroupOwned = item.GroupOwned; + clone.GroupPermissions = item.GroupPermissions; + clone.InvType = item.InvType; + clone.NextPermissions = item.NextPermissions; + clone.Owner = item.Owner; + + return clone; + } + + public void DeleteObjectsFolders() + { + // Delete everything in A2 and A3's Objects folders, so we can restart + for (int i = 1; i < 3; i++) + { + InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(Common.TheScene.InventoryService, Common.TheAvatars[i].UUID, "Objects"); + Assert.That(objsFolder, Is.Not.Null); + + List items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[i].UUID, objsFolder.ID); + List ids = new List(); + foreach (InventoryItemBase it in items) + ids.Add(it.ID); + + Common.TheScene.InventoryService.DeleteItems(Common.TheAvatars[i].UUID, ids); + items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[i].UUID, objsFolder.ID); + Assert.That(items.Count, Is.EqualTo(0), "A" + (i + 1)); + } + + } + + public string IdStr(InventoryItemBase item) + { + return item.Owner.ToString().Substring(34) + " : " + item.Name; + } + + public string IdStr(SceneObjectGroup sog) + { + return sog.OwnerID.ToString().Substring(34) + " : " + sog.Name; + } + + public void GiveInventoryItem(UUID itemId, ScenePresence giverSp, ScenePresence receiverSp) + { + TestClient giverClient = (TestClient)giverSp.ControllingClient; + TestClient receiverClient = (TestClient)receiverSp.ControllingClient; + + UUID initialSessionId = TestHelpers.ParseTail(0x10); + byte[] giveImBinaryBucket = new byte[17]; + byte[] itemIdBytes = itemId.GetBytes(); + Array.Copy(itemIdBytes, 0, giveImBinaryBucket, 1, itemIdBytes.Length); + + GridInstantMessage giveIm + = new GridInstantMessage( + m_Scene, + giverSp.UUID, + giverSp.Name, + receiverSp.UUID, + (byte)InstantMessageDialog.InventoryOffered, + false, + "inventory offered msg", + initialSessionId, + false, + Vector3.Zero, + giveImBinaryBucket, + true); + + giverClient.HandleImprovedInstantMessage(giveIm); + + // These details might not all be correct. + GridInstantMessage acceptIm + = new GridInstantMessage( + m_Scene, + receiverSp.UUID, + receiverSp.Name, + giverSp.UUID, + (byte)InstantMessageDialog.InventoryAccepted, + false, + "inventory accepted msg", + initialSessionId, + false, + Vector3.Zero, + null, + true); + + receiverClient.HandleImprovedInstantMessage(acceptIm); + } + } +} diff --git a/OpenSim/Tests/Permissions/DirectTransferTests.cs b/OpenSim/Tests/Permissions/DirectTransferTests.cs new file mode 100644 index 0000000000..0f251dba43 --- /dev/null +++ b/OpenSim/Tests/Permissions/DirectTransferTests.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 NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using PermissionMask = OpenSim.Framework.PermissionMask; + +namespace OpenSim.Tests.Permissions +{ + /// + /// Basic scene object tests (create, read and delete but not update). + /// + [TestFixture] + public class DirectTransferTests + { + + [SetUp] + public void SetUp() + { + // In case we're dealing with some older version of nunit + if (Common.TheInstance == null) + { + Common.TheInstance = new Common(); + Common.TheInstance.SetUp(); + } + + Common.TheInstance.DeleteObjectsFolders(); + } + + /// + /// Test giving simple objecta with various combinations of next owner perms. + /// + [Test] + public void TestGiveBox() + { + TestHelpers.InMethod(); + + // C, CT, MC, MCT, MT, T + string[] names = new string[6] { "Box C", "Box CT", "Box MC", "Box MCT", "Box MT", "Box T" }; + PermissionMask[] perms = new PermissionMask[6] { + PermissionMask.Copy, + PermissionMask.Copy | PermissionMask.Transfer, + PermissionMask.Modify | PermissionMask.Copy, + PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer, + PermissionMask.Modify | PermissionMask.Transfer, + PermissionMask.Transfer + }; + + for (int i = 0; i < 6; i++) + TestOneBox(names[i], perms[i]); + } + + private void TestOneBox(string name, PermissionMask mask) + { + InventoryItemBase item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[0].UUID, "Objects", name); + + Common.TheInstance.GiveInventoryItem(item.ID, Common.TheAvatars[0], Common.TheAvatars[1]); + + item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", name); + + // Check the receiver + Common.TheInstance.PrintPerms(item); + Common.TheInstance.AssertPermissions(mask, (PermissionMask)item.BasePermissions, item.Owner.ToString().Substring(34) + " : " + item.Name); + + int nObjects = Common.TheScene.GetSceneObjectGroups().Count; + // Rez it and check perms in scene too + Common.TheScene.RezObject(Common.TheAvatars[1].ControllingClient, item.ID, UUID.Zero, Vector3.One, Vector3.Zero, UUID.Zero, 0, false, false, false, UUID.Zero); + Assert.That(Common.TheScene.GetSceneObjectGroups().Count, Is.EqualTo(nObjects + 1)); + + SceneObjectGroup box = Common.TheScene.GetSceneObjectGroups().Find(sog => sog.OwnerID == Common.TheAvatars[1].UUID && sog.Name == name); + Common.TheInstance.PrintPerms(box); + Assert.That(box, Is.Not.Null); + + // Check Owner permissions + Common.TheInstance.AssertPermissions(mask, (PermissionMask)box.EffectiveOwnerPerms, box.OwnerID.ToString().Substring(34) + " : " + box.Name); + + // Check Next Owner permissions + Common.TheInstance.AssertPermissions(mask, (PermissionMask)box.RootPart.NextOwnerMask, box.OwnerID.ToString().Substring(34) + " : " + box.Name); + + } + + /// + /// Test giving simple objecta with variour combinations of next owner perms. + /// + [Test] + public void TestDoubleGiveWithChange() + { + TestHelpers.InMethod(); + + string name = "Box MCT-C"; + InventoryItemBase item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[0].UUID, "Objects", name); + + // Now give the item to A2. We give the original item, not a clone. + // The giving methods are supposed to duplicate it. + Common.TheInstance.GiveInventoryItem(item.ID, Common.TheAvatars[0], Common.TheAvatars[1]); + + item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", name); + + // Check the receiver + Common.TheInstance.PrintPerms(item); + Common.TheInstance.AssertPermissions(PermissionMask.Modify | PermissionMask.Transfer, + (PermissionMask)item.BasePermissions, Common.TheInstance.IdStr(item)); + + // --------------------------- + // Second transfer + //---------------------------- + + // A2 revokes M + Common.TheInstance.RevokePermission(1, name, PermissionMask.Modify); + + item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", name); + + // Now give the item to A3. We give the original item, not a clone. + // The giving methods are supposed to duplicate it. + Common.TheInstance.GiveInventoryItem(item.ID, Common.TheAvatars[1], Common.TheAvatars[2]); + + item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[2].UUID, "Objects", name); + + // Check the receiver + Common.TheInstance.PrintPerms(item); + Common.TheInstance.AssertPermissions(PermissionMask.Transfer, + (PermissionMask)item.BasePermissions, Common.TheInstance.IdStr(item)); + + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Permissions/IndirectTransferTests.cs b/OpenSim/Tests/Permissions/IndirectTransferTests.cs new file mode 100644 index 0000000000..fb96b8b194 --- /dev/null +++ b/OpenSim/Tests/Permissions/IndirectTransferTests.cs @@ -0,0 +1,132 @@ +/* + * 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.Collections.Generic; +using System.Threading; +using NUnit.Framework; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Tests.Common; +using PermissionMask = OpenSim.Framework.PermissionMask; + +namespace OpenSim.Tests.Permissions +{ + /// + /// Basic scene object tests (create, read and delete but not update). + /// + [TestFixture] + public class IndirectTransferTests + { + + [SetUp] + public void SetUp() + { + // In case we're dealing with some older version of nunit + if (Common.TheInstance == null) + { + Common.TheInstance = new Common(); + Common.TheInstance.SetUp(); + } + Common.TheInstance.DeleteObjectsFolders(); + } + + /// + /// Test giving simple objecta with various combinations of next owner perms. + /// + [Test] + public void SimpleTakeCopy() + { + TestHelpers.InMethod(); + + // The Objects folder of A2 + InventoryFolderBase objsFolder = UserInventoryHelpers.GetInventoryFolder(Common.TheScene.InventoryService, Common.TheAvatars[1].UUID, "Objects"); + + // C, CT, MC, MCT, MT, T + string[] names = new string[6] { "Box C", "Box CT", "Box MC", "Box MCT", "Box MT", "Box T" }; + PermissionMask[] perms = new PermissionMask[6] { + PermissionMask.Copy, + PermissionMask.Copy | PermissionMask.Transfer, + PermissionMask.Modify | PermissionMask.Copy, + PermissionMask.Modify | PermissionMask.Copy | PermissionMask.Transfer, + PermissionMask.Modify | PermissionMask.Transfer, + PermissionMask.Transfer + }; + + // Try A2 takes copies of objects that cannot be copied. + for (int i = 0; i < 6; i++) + TakeOneBox(Common.TheScene.GetSceneObjectGroups(), names[i], perms[i]); + // Ad-hoc. Enough time to let the take work. + Thread.Sleep(5000); + + List items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[1].UUID, objsFolder.ID); + Assert.That(items.Count, Is.EqualTo(0)); + + // A1 makes the objects copyable + for (int i = 0; i < 6; i++) + MakeCopyable(Common.TheScene.GetSceneObjectGroups(), names[i]); + + // Try A2 takes copies of objects that can be copied. + for (int i = 0; i < 6; i++) + TakeOneBox(Common.TheScene.GetSceneObjectGroups(), names[i], perms[i]); + // Ad-hoc. Enough time to let the take work. + Thread.Sleep(5000); + + items = Common.TheScene.InventoryService.GetFolderItems(Common.TheAvatars[1].UUID, objsFolder.ID); + Assert.That(items.Count, Is.EqualTo(6)); + + for (int i = 0; i < 6; i++) + { + InventoryItemBase item = Common.TheInstance.GetItemFromInventory(Common.TheAvatars[1].UUID, "Objects", names[i]); + Assert.That(item, Is.Not.Null); + Common.TheInstance.AssertPermissions(perms[i], (PermissionMask)item.BasePermissions, Common.TheInstance.IdStr(item)); + } + } + + private void TakeOneBox(List objs, string name, PermissionMask mask) + { + // Find the object inworld + SceneObjectGroup box = objs.Find(sog => sog.Name == name && sog.OwnerID == Common.TheAvatars[0].UUID); + Assert.That(box, Is.Not.Null, name); + + // A2's inventory (index 1) + Common.TheInstance.TakeCopyToInventory(1, box); + } + + private void MakeCopyable(List objs, string name) + { + SceneObjectGroup box = objs.Find(sog => sog.Name == name && sog.OwnerID == Common.TheAvatars[0].UUID); + Assert.That(box, Is.Not.Null, name); + + // field = 8 is Everyone + // set = 1 means add the permission; set = 0 means remove permission + Common.TheScene.HandleObjectPermissionsUpdate((IClientAPI)Common.TheAvatars[0].ClientView, Common.TheAvatars[0].UUID, + Common.TheAvatars[0].ControllingClient.SessionId, 8, box.LocalId, (uint)PermissionMask.Copy, 1); + Common.TheInstance.PrintPerms(box); + } + } +} \ No newline at end of file diff --git a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs index 5e6a63891a..e9767f3e84 100644 --- a/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs +++ b/OpenSim/Tests/Stress/VectorRenderModuleStressTests.cs @@ -118,8 +118,7 @@ namespace OpenSim.Tests.Stress so.UUID, m_tests.Vrm.GetContentType(), string.Format("PenColour BLACK; MoveTo 40,220; FontSize 32; Text {0};", text), - "", - 0); + ""); Assert.That(originalTextureID, Is.Not.EqualTo(so.RootPart.Shape.Textures.GetFace(0).TextureID)); diff --git a/bin/Mono.Posix.dll b/bin/Mono.Posix.dll deleted file mode 100755 index 97ec8bf3f2..0000000000 Binary files a/bin/Mono.Posix.dll and /dev/null differ diff --git a/bin/MySql.Data.dll b/bin/MySql.Data.dll index 992aa5621c..c9f344a56c 100755 Binary files a/bin/MySql.Data.dll and b/bin/MySql.Data.dll differ diff --git a/bin/Newtonsoft.Json.dll b/bin/Newtonsoft.Json.dll new file mode 100644 index 0000000000..5931de1693 Binary files /dev/null and b/bin/Newtonsoft.Json.dll differ diff --git a/bin/Newtonsoft.Json.xml b/bin/Newtonsoft.Json.xml new file mode 100644 index 0000000000..2a75b4481a --- /dev/null +++ b/bin/Newtonsoft.Json.xml @@ -0,0 +1,8626 @@ + + + + Newtonsoft.Json + + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. + + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. + + + + + Initializes a new instance of the class with the specified . + + + + + Reads the next JSON token from the stream. + + true if the next token was read successfully; false if there are no more tokens to read. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A or a null reference if the next JSON token is null. This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Skips the children of the current token. + + + + + Sets the current token. + + The new token. + + + + Sets the current token and value. + + The new token. + The value. + + + + Sets the state based on current token type. + + + + + Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources. + + + + + Releases unmanaged and - optionally - managed resources + + true to release both managed and unmanaged resources; false to release only unmanaged resources. + + + + Changes the to Closed. + + + + + Gets the current reader state. + + The current reader state. + + + + Gets or sets a value indicating whether the underlying stream or + should be closed when the reader is closed. + + + true to close the underlying stream or when + the reader is closed; otherwise false. The default is true. + + + + + Gets or sets a value indicating whether multiple pieces of JSON content can + be read from a continuous stream without erroring. + + + true to support reading multiple pieces of JSON content; otherwise false. The default is false. + + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + Get or set how time zones are handling when reading JSON. + + + + + Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + + + + + Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Get or set how custom date formatted strings are parsed when reading JSON. + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + + + + + Gets the type of the current JSON token. + + + + + Gets the text value of the current JSON token. + + + + + Gets The Common Language Runtime (CLR) type for the current JSON token. + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Gets the path of the current JSON token. + + + + + Gets or sets the culture used when reading JSON. Defaults to . + + + + + Specifies the state of the reader. + + + + + The Read method has not been called. + + + + + The end of the file has been reached successfully. + + + + + Reader is at a property. + + + + + Reader is at the start of an object. + + + + + Reader is in an object. + + + + + Reader is at the start of an array. + + + + + Reader is in an array. + + + + + The Close method has been called. + + + + + Reader has just read a value. + + + + + Reader is at the start of a constructor. + + + + + Reader in a constructor. + + + + + An error occurred that prevents the read operation from continuing. + + + + + The end of the file has been reached successfully. + + + + + Initializes a new instance of the class. + + The stream. + + + + Initializes a new instance of the class. + + The reader. + + + + Initializes a new instance of the class. + + The stream. + if set to true the root object will be read as a JSON array. + The used when reading values from BSON. + + + + Initializes a new instance of the class. + + The reader. + if set to true the root object will be read as a JSON array. + The used when reading values from BSON. + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. This method will return null at the end of an array. + + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + + A . This method will return null at the end of an array. + + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Changes the to Closed. + + + + + Gets or sets a value indicating whether binary data reading should compatible with incorrect Json.NET 3.5 written binary. + + + true if binary data reading will be compatible with incorrect Json.NET 3.5 written binary; otherwise, false. + + + + + Gets or sets a value indicating whether the root object will be read as a JSON array. + + + true if the root object will be read as a JSON array; otherwise, false. + + + + + Gets or sets the used when reading values from BSON. + + The used when reading values from BSON. + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating JSON data. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. + + + + + Creates an instance of the JsonWriter class. + + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Closes this stream and the underlying stream. + + + + + Writes the beginning of a Json object. + + + + + Writes the end of a Json object. + + + + + Writes the beginning of a Json array. + + + + + Writes the end of an array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end constructor. + + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + + + + Writes the end of the current Json object or array. + + + + + Writes the current token and its children. + + The to read the token from. + + + + Writes the current token. + + The to read the token from. + A flag indicating whether the current token's children should be written. + + + + Writes the specified end token. + + The end token to write. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON without changing the writer's state. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes out the given white space. + + The string of white space characters. + + + + Sets the state of the JsonWriter, + + The JsonToken being written. + The value being written. + + + + Gets or sets a value indicating whether the underlying stream or + should be closed when the writer is closed. + + + true to close the underlying stream or when + the writer is closed; otherwise false. The default is true. + + + + + Gets the top. + + The top. + + + + Gets the state of the writer. + + + + + Gets the path of the writer. + + + + + Indicates how JSON text output is formatted. + + + + + Get or set how dates are written to JSON text. + + + + + Get or set how time zones are handling when writing JSON text. + + + + + Get or set how strings are escaped when writing JSON text. + + + + + Get or set how special floating point numbers, e.g. , + and , + are written to JSON text. + + + + + Get or set how and values are formatting when writing JSON text. + + + + + Gets or sets the culture used when writing JSON. Defaults to . + + + + + Initializes a new instance of the class. + + The stream. + + + + Initializes a new instance of the class. + + The writer. + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Writes the end. + + The token. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes raw JSON where a value is expected and updates the writer's state. + + The raw JSON to write. + + + + Writes the beginning of a Json array. + + + + + Writes the beginning of a Json object. + + + + + Writes the property name of a name/value pair on a Json object. + + The name of the property. + + + + Closes this stream and the underlying stream. + + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value that represents a BSON object id. + + The Object ID value to write. + + + + Writes a BSON regex. + + The regex pattern. + The regex options. + + + + Gets or sets the used when writing values to BSON. + When set to no conversion will occur. + + The used when writing values to BSON. + + + + Represents a BSON Oid (object id). + + + + + Initializes a new instance of the class. + + The Oid value. + + + + Gets or sets the value of the Oid. + + The value of the Oid. + + + + Converts a binary value to and from a base 64 string value. + + + + + Converts an object to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets the of the JSON produced by the JsonConverter. + + The of the JSON produced by the JsonConverter. + + + + Gets a value indicating whether this can read JSON. + + true if this can read JSON; otherwise, false. + + + + Gets a value indicating whether this can write JSON. + + true if this can write JSON; otherwise, false. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Create a custom object + + The object type to convert. + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Creates an object which will then be populated by the serializer. + + Type of the object. + The created object. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can write JSON. + + + true if this can write JSON; otherwise, false. + + + + + Provides a base class for converting a to and from JSON. + + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a F# discriminated union type to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an Entity Framework EntityKey to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an ExpandoObject to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets a value indicating whether this can write JSON. + + + true if this can write JSON; otherwise, false. + + + + + Converts a to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON and BSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts a to and from JSON and BSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Converts an to and from its name string value. + + + + + Initializes a new instance of the class. + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Gets or sets a value indicating whether the written enum text should be camel case. + + true if the written enum text will be camel case; otherwise, false. + + + + Gets or sets a value indicating whether integer values are allowed. + + true if integers are allowed; otherwise, false. + + + + Specifies how constructors are used when initializing objects during deserialization by the . + + + + + First attempt to use the public default constructor, then fall back to single paramatized constructor, then the non-public default constructor. + + + + + Json.NET will use a non-public default constructor before falling back to a paramatized constructor. + + + + + Converts a to and from a string (e.g. "1.2.3.4"). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Determines whether this instance can convert the specified object type. + + Type of the object. + + true if this instance can convert the specified object type; otherwise, false. + + + + + Specifies float format handling options when writing special floating point numbers, e.g. , + and with . + + + + + Write special floating point values as strings in JSON, e.g. "NaN", "Infinity", "-Infinity". + + + + + Write special floating point values as symbols in JSON, e.g. NaN, Infinity, -Infinity. + Note that this will produce non-valid JSON. + + + + + Write special floating point values as the property's default value in JSON, e.g. 0.0 for a property, null for a property. + + + + + Specifies how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Floating point numbers are parsed to . + + + + + Floating point numbers are parsed to . + + + + + Instructs the how to serialize the collection. + + + + + Instructs the how to serialize the object. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Gets or sets the id. + + The id. + + + + Gets or sets the title. + + The title. + + + + Gets or sets the description. + + The description. + + + + Gets the collection's items converter. + + The collection's items converter. + + + + The parameter list to use when constructing the JsonConverter described by ItemConverterType. + If null, the default constructor is used. + When non-null, there must be a constructor defined in the JsonConverter that exactly matches the number, + order, and type of these parameters. + + + [JsonContainer(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] + + + + + Gets or sets a value that indicates whether to preserve object references. + + + true to keep object reference; otherwise, false. The default is false. + + + + + Gets or sets a value that indicates whether to preserve collection's items references. + + + true to keep collection's items object references; otherwise, false. The default is false. + + + + + Gets or sets the reference loop handling used when serializing the collection's items. + + The reference loop handling. + + + + Gets or sets the type name handling used when serializing the collection's items. + + The type name handling. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + The exception thrown when an error occurs during Json serialization or deserialization. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Specifies how dates are formatted when writing JSON text. + + + + + Dates are written in the ISO 8601 format, e.g. "2012-03-21T05:40Z". + + + + + Dates are written in the Microsoft JSON format, e.g. "\/Date(1198908717056)\/". + + + + + Specifies how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON text. + + + + + Date formatted strings are not parsed to a date type and are read as strings. + + + + + Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to . + + + + + Date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed to . + + + + + Specifies how to treat the time value when converting between string and . + + + + + Treat as local time. If the object represents a Coordinated Universal Time (UTC), it is converted to the local time. + + + + + Treat as a UTC. If the object represents a local time, it is converted to a UTC. + + + + + Treat as a local time if a is being converted to a string. + If a string is being converted to , convert to a local time if a time zone is specified. + + + + + Time zone information should be preserved when converting. + + + + + Specifies formatting options for the . + + + + + No special formatting is applied. This is the default. + + + + + Causes child objects to be indented according to the and settings. + + + + + Instructs the to use the specified constructor when deserializing that object. + + + + + Instructs the to deserialize properties with no matching class member into the specified collection + and write values during serialization. + + + + + Initializes a new instance of the class. + + + + + Gets or sets a value that indicates whether to write extension data when serializing the object. + + + true to write extension data when serializing the object; otherwise, false. The default is true. + + + + + Gets or sets a value that indicates whether to read extension data when deserializing the object. + + + true to read extension data when deserializing the object; otherwise, false. The default is true. + + + + + Specifies the settings used when merging JSON. + + + + + Gets or sets the method used when merging JSON arrays. + + The method used when merging JSON arrays. + + + + Specifies how JSON arrays are merged together. + + + + Concatenate arrays. + + + Union arrays, skipping items that already exist. + + + Replace all array items. + + + Merge array items together, matched by index. + + + + Specifies metadata property handling options for the . + + + + + Read metadata properties located at the start of a JSON object. + + + + + Read metadata properties located anywhere in a JSON object. Note that this setting will impact performance. + + + + + Do not try to read metadata properties. + + + + + Represents a trace writer that writes to the application's instances. + + + + + Represents a trace writer. + + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of Info will exclude Verbose messages and include Info, + Warning and Error messages. + + The that will be used to filter the trace messages passed to the writer. + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of Info will exclude Verbose messages and include Info, + Warning and Error messages. + + + The that will be used to filter the trace messages passed to the writer. + + + + + Get and set values for a using dynamic methods. + + + + + Provides methods to get and set values. + + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Contract details for a used by the . + + + + + Contract details for a used by the . + + + + + Gets the underlying type for the contract. + + The underlying type for the contract. + + + + Gets or sets the type created during deserialization. + + The type created during deserialization. + + + + Gets or sets whether this type contract is serialized as a reference. + + Whether this type contract is serialized as a reference. + + + + Gets or sets the default for this contract. + + The converter. + + + + Gets or sets all methods called immediately after deserialization of the object. + + The methods called immediately after deserialization of the object. + + + + Gets or sets all methods called during deserialization of the object. + + The methods called during deserialization of the object. + + + + Gets or sets all methods called after serialization of the object graph. + + The methods called after serialization of the object graph. + + + + Gets or sets all methods called before serialization of the object. + + The methods called before serialization of the object. + + + + Gets or sets all method called when an error is thrown during the serialization of the object. + + The methods called when an error is thrown during the serialization of the object. + + + + Gets or sets the method called immediately after deserialization of the object. + + The method called immediately after deserialization of the object. + + + + Gets or sets the method called during deserialization of the object. + + The method called during deserialization of the object. + + + + Gets or sets the method called after serialization of the object graph. + + The method called after serialization of the object graph. + + + + Gets or sets the method called before serialization of the object. + + The method called before serialization of the object. + + + + Gets or sets the method called when an error is thrown during the serialization of the object. + + The method called when an error is thrown during the serialization of the object. + + + + Gets or sets the default creator method used to create the object. + + The default creator method used to create the object. + + + + Gets or sets a value indicating whether the default creator is non public. + + true if the default object creator is non-public; otherwise, false. + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Gets or sets the default collection items . + + The converter. + + + + Gets or sets a value indicating whether the collection items preserve object references. + + true if collection items preserve object references; otherwise, false. + + + + Gets or sets the collection item reference loop handling. + + The reference loop handling. + + + + Gets or sets the collection item type name handling. + + The type name handling. + + + + Represents a trace writer that writes to memory. When the trace message limit is + reached then old trace messages will be removed as new messages are added. + + + + + Initializes a new instance of the class. + + + + + Writes the specified trace level, message and optional exception. + + The at which to write this trace. + The trace message. + The trace exception. This parameter is optional. + + + + Returns an enumeration of the most recent trace messages. + + An enumeration of the most recent trace messages. + + + + Returns a of the most recent trace messages. + + + A of the most recent trace messages. + + + + + Gets the that will be used to filter the trace messages passed to the writer. + For example a filter level of Info will exclude Verbose messages and include Info, + Warning and Error messages. + + + The that will be used to filter the trace messages passed to the writer. + + + + + Provides an interface to enable a class to return line and position information. + + + + + Gets a value indicating whether the class can return line information. + + + true if LineNumber and LinePosition can be provided; otherwise, false. + + + + + Gets the current line number. + + The current line number or 0 if no line information is available (for example, HasLineInfo returns false). + + + + Gets the current line position. + + The current line position or 0 if no line information is available (for example, HasLineInfo returns false). + + + + Specifies how strings are escaped when writing JSON text. + + + + + Only control characters (e.g. newline) are escaped. + + + + + All non-ASCII and control characters (e.g. newline) are escaped. + + + + + HTML (<, >, &, ', ") and control characters (e.g. newline) are escaped. + + + + + Represents a raw JSON string. + + + + + Represents a value in JSON (string, integer, date, etc). + + + + + Represents an abstract JSON token. + + + + + Represents a collection of objects. + + The type of token + + + + Gets the with the specified key. + + + + + + Compares the values of two tokens, including the values of all descendant tokens. + + The first to compare. + The second to compare. + true if the tokens are equal; otherwise false. + + + + Adds the specified content immediately after this token. + + A content object that contains simple content or a collection of content objects to be added after this token. + + + + Adds the specified content immediately before this token. + + A content object that contains simple content or a collection of content objects to be added before this token. + + + + Returns a collection of the ancestor tokens of this token. + + A collection of the ancestor tokens of this token. + + + + Returns a collection of the sibling tokens after this token, in document order. + + A collection of the sibling tokens after this tokens, in document order. + + + + Returns a collection of the sibling tokens before this token, in document order. + + A collection of the sibling tokens before this token, in document order. + + + + Gets the with the specified key converted to the specified type. + + The type to convert the token to. + The token key. + The converted token value. + + + + Returns a collection of the child tokens of this token, in document order. + + An of containing the child tokens of this , in document order. + + + + Returns a collection of the child tokens of this token, in document order, filtered by the specified type. + + The type to filter the child tokens on. + A containing the child tokens of this , in document order. + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + A containing the child values of this , in document order. + + + + Removes this token from its parent. + + + + + Replaces this token with the specified token. + + The value. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Returns the indented JSON for this token. + + + The indented JSON for this token. + + + + + Returns the JSON for this token using the given formatting and converters. + + Indicates how the output is formatted. + A collection of which will be used when writing the token. + The JSON for this token using the given formatting and converters. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an explicit conversion from to . + + The value. + The result of the conversion. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Performs an implicit conversion from to . + + The value to create a from. + The initialized with the specified value. + + + + Creates an for this token. + + An that can be used to read this token and its descendants. + + + + Creates a from an object. + + The object that will be used to create . + A with the value of the specified object + + + + Creates a from an object using the specified . + + The object that will be used to create . + The that will be used when reading the object. + A with the value of the specified object + + + + Creates the specified .NET type from the . + + The object type that the token will be deserialized to. + The new object created from the JSON value. + + + + Creates the specified .NET type from the . + + The object type that the token will be deserialized to. + The new object created from the JSON value. + + + + Creates the specified .NET type from the using the specified . + + The object type that the token will be deserialized to. + The that will be used when creating the object. + The new object created from the JSON value. + + + + Creates the specified .NET type from the using the specified . + + The object type that the token will be deserialized to. + The that will be used when creating the object. + The new object created from the JSON value. + + + + Creates a from a . + + An positioned at the token to read into this . + + An that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + Creates a from a . + + An positioned at the token to read into this . + + An that contains the token and its descendant tokens + that were read from the reader. The runtime type of the token is determined + by the token type of the first token encountered in the reader. + + + + + Selects a using a JPath expression. Selects the token that matches the object path. + + + A that contains a JPath expression. + + A , or null. + + + + Selects a using a JPath expression. Selects the token that matches the object path. + + + A that contains a JPath expression. + + A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. + A . + + + + Selects a collection of elements using a JPath expression. + + + A that contains a JPath expression. + + An that contains the selected elements. + + + + Selects a collection of elements using a JPath expression. + + + A that contains a JPath expression. + + A flag to indicate whether an error should be thrown if no tokens are found when evaluating part of the expression. + An that contains the selected elements. + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Creates a new instance of the . All child tokens are recursively cloned. + + A new instance of the . + + + + Gets a comparer that can compare two tokens for value equality. + + A that can compare two nodes for value equality. + + + + Gets or sets the parent. + + The parent. + + + + Gets the root of this . + + The root of this . + + + + Gets the node type for this . + + The type. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Gets the next sibling token of this node. + + The that contains the next sibling token. + + + + Gets the previous sibling token of this node. + + The that contains the previous sibling token. + + + + Gets the path of the JSON token. + + + + + Gets the with the specified key. + + The with the specified key. + + + + Get the first child token of this token. + + A containing the first child token of the . + + + + Get the last child token of this token. + + A containing the last child token of the . + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Initializes a new instance of the class with the given value. + + The value. + + + + Creates a comment with the given value. + + The value. + A comment with the given value. + + + + Creates a string with the given value. + + The value. + A string with the given value. + + + + Creates a null value. + + A null value. + + + + Creates a null value. + + A null value. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Indicates whether the current object is equal to another object of the same type. + + + true if the current object is equal to the parameter; otherwise, false. + + An object to compare with this object. + + + + Determines whether the specified is equal to the current . + + The to compare with the current . + + true if the specified is equal to the current ; otherwise, false. + + + The parameter is null. + + + + + Serves as a hash function for a particular type. + + + A hash code for the current . + + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format provider. + + A that represents this instance. + + + + + Returns a that represents this instance. + + The format. + The format provider. + + A that represents this instance. + + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object. + + An object to compare with this instance. + + A 32-bit signed integer that indicates the relative order of the objects being compared. The return value has these meanings: + Value + Meaning + Less than zero + This instance is less than . + Zero + This instance is equal to . + Greater than zero + This instance is greater than . + + + is not the same type as this instance. + + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Gets the node type for this . + + The type. + + + + Gets or sets the underlying token value. + + The underlying token value. + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class. + + The raw json. + + + + Creates an instance of with the content of the reader's current token. + + The reader. + An instance of with the content of the reader's current token. + + + + Indicating whether a property is required. + + + + + The property is not required. The default state. + + + + + The property must be defined in JSON but can be a null value. + + + + + The property must be defined in JSON and cannot be a null value. + + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Gets the object's properties. + + The object's properties. + + + + Gets or sets the property name resolver. + + The property name resolver. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Gets or sets the ISerializable object constructor. + + The ISerializable object constructor. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Get and set values for a using dynamic methods. + + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + Provides data for the Error event. + + + + + Initializes a new instance of the class. + + The current object. + The error context. + + + + Gets the current object the error event is being raised against. + + The current object the error event is being raised against. + + + + Gets the error context. + + The error context. + + + + Represents a view of a . + + + + + Initializes a new instance of the class. + + The name. + + + + When overridden in a derived class, returns whether resetting an object changes its value. + + + true if resetting the component changes its value; otherwise, false. + + The component to test for reset capability. + + + + + When overridden in a derived class, gets the current value of the property on a component. + + + The value of a property for a given component. + + The component with the property for which to retrieve the value. + + + + + When overridden in a derived class, resets the value for this property of the component to the default value. + + The component with the property value that is to be reset to the default value. + + + + + When overridden in a derived class, sets the value of the component to a different value. + + The component with the property value that is to be set. + The new value. + + + + + When overridden in a derived class, determines a value indicating whether the value of this property needs to be persisted. + + + true if the property should be persisted; otherwise, false. + + The component with the property to be examined for persistence. + + + + + When overridden in a derived class, gets the type of the component this property is bound to. + + + A that represents the type of component this property is bound to. When the or methods are invoked, the object specified might be an instance of this type. + + + + + When overridden in a derived class, gets a value indicating whether this property is read-only. + + + true if the property is read-only; otherwise, false. + + + + + When overridden in a derived class, gets the type of the property. + + + A that represents the type of the property. + + + + + Gets the hash code for the name of the member. + + + + The hash code for the name of the member. + + + + + Used to resolve references when serializing and deserializing JSON by the . + + + + + Resolves a reference to its object. + + The serialization context. + The reference to resolve. + The object that + + + + Gets the reference for the sepecified object. + + The serialization context. + The object to get a reference for. + The reference to the object. + + + + Determines whether the specified object is referenced. + + The serialization context. + The object to test for a reference. + + true if the specified object is referenced; otherwise, false. + + + + + Adds a reference to the specified object. + + The serialization context. + The reference. + The object to reference. + + + + Specifies reference handling options for the . + Note that references cannot be preserved when a value is set via a non-default constructor such as types that implement ISerializable. + + + + + + + + Do not preserve references when serializing types. + + + + + Preserve references when serializing into a JSON object structure. + + + + + Preserve references when serializing into a JSON array structure. + + + + + Preserve references when serializing. + + + + + Instructs the how to serialize the collection. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with a flag indicating whether the array can contain null items + + A flag indicating whether the array can contain null items. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Gets or sets a value indicating whether null items are allowed in the collection. + + true if null items are allowed in the collection; otherwise, false. + + + + Specifies default value handling options for the . + + + + + + + + + Include members where the member value is the same as the member's default value when serializing objects. + Included members are written to JSON. Has no effect when deserializing. + + + + + Ignore members where the member value is the same as the member's default value when serializing objects + so that is is not written to JSON. + This option will ignore all default values (e.g. null for objects and nullable types; 0 for integers, + decimals and floating point numbers; and false for booleans). The default value ignored can be changed by + placing the on the property. + + + + + Members with a default value but no JSON will be set to their default value when deserializing. + + + + + Ignore members where the member value is the same as the member's default value when serializing objects + and sets members to their default value when deserializing. + + + + + Instructs the to use the specified when serializing the member or class. + + + + + Initializes a new instance of the class. + + Type of the converter. + + + + Initializes a new instance of the class. + + Type of the converter. + Parameter list to use when constructing the JsonConverter. Can be null. + + + + Gets the type of the converter. + + The type of the converter. + + + + The parameter list to use when constructing the JsonConverter described by ConverterType. + If null, the default constructor is used. + + + + + Instructs the how to serialize the object. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified member serialization. + + The member serialization. + + + + Initializes a new instance of the class with the specified container Id. + + The container Id. + + + + Gets or sets the member serialization. + + The member serialization. + + + + Gets or sets a value that indicates whether the object's properties are required. + + + A value indicating whether the object's properties are required. + + + + + Specifies the settings on a object. + + + + + Initializes a new instance of the class. + + + + + Gets or sets how reference loops (e.g. a class referencing itself) is handled. + + Reference loop handling. + + + + Gets or sets how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + + Missing member handling. + + + + Gets or sets how objects are created during deserialization. + + The object creation handling. + + + + Gets or sets how null values are handled during serialization and deserialization. + + Null value handling. + + + + Gets or sets how null default are handled during serialization and deserialization. + + The default value handling. + + + + Gets or sets a collection that will be used during serialization. + + The converters. + + + + Gets or sets how object references are preserved by the serializer. + + The preserve references handling. + + + + Gets or sets how type name writing and reading is handled by the serializer. + + The type name handling. + + + + Gets or sets how metadata properties are used during deserialization. + + The metadata properties handling. + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + + The type name assembly format. + + + + Gets or sets how constructors are used during deserialization. + + The constructor handling. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + The contract resolver. + + + + Gets or sets the used by the serializer when resolving references. + + The reference resolver. + + + + Gets or sets the used by the serializer when writing trace messages. + + The trace writer. + + + + Gets or sets the used by the serializer when resolving type names. + + The binder. + + + + Gets or sets the error handler called during serialization and deserialization. + + The error handler called during serialization and deserialization. + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Get or set how and values are formatting when writing JSON text. + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + + + + + Indicates how JSON text output is formatted. + + + + + Get or set how dates are written to JSON text. + + + + + Get or set how time zones are handling during serialization and deserialization. + + + + + Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + + + + + Get or set how special floating point numbers, e.g. , + and , + are written as JSON. + + + + + Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Get or set how strings are escaped when writing JSON text. + + + + + Gets or sets the culture used when reading JSON. Defaults to . + + + + + Gets a value indicating whether there will be a check for additional content after deserializing an object. + + + true if there will be a check for additional content after deserializing an object; otherwise, false. + + + + + Represents a reader that provides validation. + + + + + Initializes a new instance of the class that + validates the content returned from the given . + + The to read from while validating. + + + + Reads the next JSON token from the stream as a . + + A . + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. + + + + + Reads the next JSON token from the stream as a . + + A . + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Sets an event handler for receiving schema validation errors. + + + + + Gets the text value of the current JSON token. + + + + + + Gets the depth of the current token in the JSON document. + + The depth of the current token in the JSON document. + + + + Gets the path of the current JSON token. + + + + + Gets the quotation mark character used to enclose the value of a string. + + + + + + Gets the type of the current JSON token. + + + + + + Gets the Common Language Runtime (CLR) type for the current JSON token. + + + + + + Gets or sets the schema. + + The schema. + + + + Gets the used to construct this . + + The specified in the constructor. + + + + Compares tokens to determine whether they are equal. + + + + + Determines whether the specified objects are equal. + + The first object of type to compare. + The second object of type to compare. + + true if the specified objects are equal; otherwise, false. + + + + + Returns a hash code for the specified object. + + The for which a hash code is to be returned. + A hash code for the specified object. + The type of is a reference type and is null. + + + + Specifies the member serialization options for the . + + + + + All public members are serialized by default. Members can be excluded using or . + This is the default member serialization mode. + + + + + Only members must be marked with or are serialized. + This member serialization mode can also be set by marking the class with . + + + + + All public and private fields are serialized. Members can be excluded using or . + This member serialization mode can also be set by marking the class with + and setting IgnoreSerializableAttribute on to false. + + + + + Specifies how object creation is handled by the . + + + + + Reuse existing objects, create new objects when needed. + + + + + Only reuse existing objects. + + + + + Always create new objects. + + + + + Converts a to and from the ISO 8601 date format (e.g. 2008-04-12T12:53Z). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Gets or sets the date time styles used when converting a date to and from JSON. + + The date time styles used when converting a date to and from JSON. + + + + Gets or sets the date time format used when converting a date to and from JSON. + + The date time format used when converting a date to and from JSON. + + + + Gets or sets the culture used when converting a date to and from JSON. + + The culture used when converting a date to and from JSON. + + + + Converts a to and from a JavaScript date constructor (e.g. new Date(52231943)). + + + + + Writes the JSON representation of the object. + + The to write to. + The value. + The calling serializer. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing property value of the JSON that is being converted. + The calling serializer. + The object value. + + + + Converts XML to and from JSON. + + + + + Writes the JSON representation of the object. + + The to write to. + The calling serializer. + The value. + + + + Reads the JSON representation of the object. + + The to read from. + Type of the object. + The existing value of object being read. + The calling serializer. + The object value. + + + + Checks if the attributeName is a namespace attribute. + + Attribute name to test. + The attribute name prefix if it has one, otherwise an empty string. + True if attribute name is for a namespace attribute, otherwise false. + + + + Determines whether this instance can convert the specified value type. + + Type of the value. + + true if this instance can convert the specified value type; otherwise, false. + + + + + Gets or sets the name of the root element to insert when deserializing to XML if the JSON structure has produces multiple root elements. + + The name of the deserialize root element. + + + + Gets or sets a flag to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + true if the array attibute is written to the XML; otherwise, false. + + + + Gets or sets a value indicating whether to write the root JSON object. + + true if the JSON root object is omitted; otherwise, false. + + + + Represents a reader that provides fast, non-cached, forward-only access to JSON text data. + + + + + Initializes a new instance of the class with the specified . + + The TextReader containing the XML data to read. + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. This method will return null at the end of an array. + + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Changes the state to closed. + + + + + Gets a value indicating whether the class can return line information. + + + true if LineNumber and LinePosition can be provided; otherwise, false. + + + + + Gets the current line number. + + + The current line number or 0 if no line information is available (for example, HasLineInfo returns false). + + + + + Gets the current line position. + + + The current line position or 0 if no line information is available (for example, HasLineInfo returns false). + + + + + Instructs the to always serialize the member with the specified name. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class with the specified name. + + Name of the property. + + + + Gets or sets the converter used when serializing the property's collection items. + + The collection's items converter. + + + + The parameter list to use when constructing the JsonConverter described by ItemConverterType. + If null, the default constructor is used. + When non-null, there must be a constructor defined in the JsonConverter that exactly matches the number, + order, and type of these parameters. + + + [JsonProperty(ItemConverterType = typeof(MyContainerConverter), ItemConverterParameters = new object[] { 123, "Four" })] + + + + + Gets or sets the null value handling used when serializing this property. + + The null value handling. + + + + Gets or sets the default value handling used when serializing this property. + + The default value handling. + + + + Gets or sets the reference loop handling used when serializing this property. + + The reference loop handling. + + + + Gets or sets the object creation handling used when deserializing this property. + + The object creation handling. + + + + Gets or sets the type name handling used when serializing this property. + + The type name handling. + + + + Gets or sets whether this property's value is serialized as a reference. + + Whether this property's value is serialized as a reference. + + + + Gets or sets the order of serialization and deserialization of a member. + + The numeric order of serialization or deserialization. + + + + Gets or sets a value indicating whether this property is required. + + + A value indicating whether this property is required. + + + + + Gets or sets the name of the property. + + The name of the property. + + + + Gets or sets the the reference loop handling used when serializing the property's collection items. + + The collection's items reference loop handling. + + + + Gets or sets the the type name handling used when serializing the property's collection items. + + The collection's items type name handling. + + + + Gets or sets whether this property's collection items are serialized as a reference. + + Whether this property's collection items are serialized as a reference. + + + + Instructs the not to serialize the public field or public read/write property value. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. + + + + + Creates an instance of the JsonWriter class using the specified . + + The TextWriter to write to. + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Closes this stream and the underlying stream. + + + + + Writes the beginning of a Json object. + + + + + Writes the beginning of a Json array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the specified end token. + + The end token to write. + + + + Writes the property name of a name/value pair on a Json object. + + The name of the property. + + + + Writes the property name of a name/value pair on a JSON object. + + The name of the property. + A flag to indicate whether the text should be escaped when it is written as a JSON property name. + + + + Writes indent characters. + + + + + Writes the JSON value delimiter. + + + + + Writes an indent space. + + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes out the given white space. + + The string of white space characters. + + + + Gets or sets how many IndentChars to write for each level in the hierarchy when is set to Formatting.Indented. + + + + + Gets or sets which character to use to quote attribute values. + + + + + Gets or sets which character to use for indenting when is set to Formatting.Indented. + + + + + Gets or sets a value indicating whether object names will be surrounded with quotes. + + + + + The exception thrown when an error occurs while reading Json text. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + The exception thrown when an error occurs while reading Json text. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Represents a collection of . + + + + + Provides methods for converting between common language runtime types and JSON types. + + + + + + + + Represents JavaScript's boolean value true as a string. This field is read-only. + + + + + Represents JavaScript's boolean value false as a string. This field is read-only. + + + + + Represents JavaScript's null as a string. This field is read-only. + + + + + Represents JavaScript's undefined as a string. This field is read-only. + + + + + Represents JavaScript's positive infinity as a string. This field is read-only. + + + + + Represents JavaScript's negative infinity as a string. This field is read-only. + + + + + Represents JavaScript's NaN as a string. This field is read-only. + + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation using the specified. + + The value to convert. + The format the date will be converted to. + The time zone handling when the date is converted to a string. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation using the specified. + + The value to convert. + The format the date will be converted to. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + The string delimiter character. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + The string delimiter character. + The string escape handling. + A JSON string representation of the . + + + + Converts the to its JSON string representation. + + The value to convert. + A JSON string representation of the . + + + + Serializes the specified object to a JSON string. + + The object to serialize. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using formatting. + + The object to serialize. + Indicates how the output is formatted. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a collection of . + + The object to serialize. + A collection converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using formatting and a collection of . + + The object to serialize. + Indicates how the output is formatted. + A collection converters used while serializing. + A JSON string representation of the object. + + + + Serializes the specified object to a JSON string using . + + The object to serialize. + The used to serialize the object. + If this is null, default serialization settings will be used. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a type, formatting and . + + The object to serialize. + The used to serialize the object. + If this is null, default serialization settings will be used. + + The type of the value being serialized. + This parameter is used when is Auto to write out the type name if the type of the value does not match. + Specifing the type is optional. + + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using formatting and . + + The object to serialize. + Indicates how the output is formatted. + The used to serialize the object. + If this is null, default serialization settings will be used. + + A JSON string representation of the object. + + + + + Serializes the specified object to a JSON string using a type, formatting and . + + The object to serialize. + Indicates how the output is formatted. + The used to serialize the object. + If this is null, default serialization settings will be used. + + The type of the value being serialized. + This parameter is used when is Auto to write out the type name if the type of the value does not match. + Specifing the type is optional. + + + A JSON string representation of the object. + + + + + Asynchronously serializes the specified object to a JSON string. + Serialization will happen on a new thread. + + The object to serialize. + + A task that represents the asynchronous serialize operation. The value of the TResult parameter contains a JSON string representation of the object. + + + + + Asynchronously serializes the specified object to a JSON string using formatting. + Serialization will happen on a new thread. + + The object to serialize. + Indicates how the output is formatted. + + A task that represents the asynchronous serialize operation. The value of the TResult parameter contains a JSON string representation of the object. + + + + + Asynchronously serializes the specified object to a JSON string using formatting and a collection of . + Serialization will happen on a new thread. + + The object to serialize. + Indicates how the output is formatted. + The used to serialize the object. + If this is null, default serialization settings will be used. + + A task that represents the asynchronous serialize operation. The value of the TResult parameter contains a JSON string representation of the object. + + + + + Deserializes the JSON to a .NET object. + + The JSON to deserialize. + The deserialized object from the JSON string. + + + + Deserializes the JSON to a .NET object using . + + The JSON to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type. + + The JSON to deserialize. + The of object being deserialized. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type. + + The type of the object to deserialize to. + The JSON to deserialize. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the given anonymous type. + + + The anonymous type to deserialize to. This can't be specified + traditionally and must be infered from the anonymous type passed + as a parameter. + + The JSON to deserialize. + The anonymous type object. + The deserialized anonymous type from the JSON string. + + + + Deserializes the JSON to the given anonymous type using . + + + The anonymous type to deserialize to. This can't be specified + traditionally and must be infered from the anonymous type passed + as a parameter. + + The JSON to deserialize. + The anonymous type object. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized anonymous type from the JSON string. + + + + Deserializes the JSON to the specified .NET type using a collection of . + + The type of the object to deserialize to. + The JSON to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using . + + The type of the object to deserialize to. + The object to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using a collection of . + + The JSON to deserialize. + The type of the object to deserialize. + Converters to use while deserializing. + The deserialized object from the JSON string. + + + + Deserializes the JSON to the specified .NET type using . + + The JSON to deserialize. + The type of the object to deserialize to. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + The deserialized object from the JSON string. + + + + Asynchronously deserializes the JSON to the specified .NET type. + Deserialization will happen on a new thread. + + The type of the object to deserialize to. + The JSON to deserialize. + + A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string. + + + + + Asynchronously deserializes the JSON to the specified .NET type using . + Deserialization will happen on a new thread. + + The type of the object to deserialize to. + The JSON to deserialize. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + + A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string. + + + + + Asynchronously deserializes the JSON to the specified .NET type. + Deserialization will happen on a new thread. + + The JSON to deserialize. + + A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string. + + + + + Asynchronously deserializes the JSON to the specified .NET type using . + Deserialization will happen on a new thread. + + The JSON to deserialize. + The type of the object to deserialize to. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + + A task that represents the asynchronous deserialize operation. The value of the TResult parameter contains the deserialized object from the JSON string. + + + + + Populates the object with values from the JSON string. + + The JSON to populate values from. + The target object to populate values onto. + + + + Populates the object with values from the JSON string using . + + The JSON to populate values from. + The target object to populate values onto. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + + + + Asynchronously populates the object with values from the JSON string using . + + The JSON to populate values from. + The target object to populate values onto. + + The used to deserialize the object. + If this is null, default serialization settings will be used. + + + A task that represents the asynchronous populate operation. + + + + + Serializes the XML node to a JSON string. + + The node to serialize. + A JSON string of the XmlNode. + + + + Serializes the XML node to a JSON string using formatting. + + The node to serialize. + Indicates how the output is formatted. + A JSON string of the XmlNode. + + + + Serializes the XML node to a JSON string using formatting and omits the root object if is true. + + The node to serialize. + Indicates how the output is formatted. + Omits writing the root object. + A JSON string of the XmlNode. + + + + Deserializes the XmlNode from a JSON string. + + The JSON string. + The deserialized XmlNode + + + + Deserializes the XmlNode from a JSON string nested in a root elment specified by . + + The JSON string. + The name of the root element to append when deserializing. + The deserialized XmlNode + + + + Deserializes the XmlNode from a JSON string nested in a root elment specified by + and writes a .NET array attribute for collections. + + The JSON string. + The name of the root element to append when deserializing. + + A flag to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + The deserialized XmlNode + + + + Serializes the to a JSON string. + + The node to convert to JSON. + A JSON string of the XNode. + + + + Serializes the to a JSON string using formatting. + + The node to convert to JSON. + Indicates how the output is formatted. + A JSON string of the XNode. + + + + Serializes the to a JSON string using formatting and omits the root object if is true. + + The node to serialize. + Indicates how the output is formatted. + Omits writing the root object. + A JSON string of the XNode. + + + + Deserializes the from a JSON string. + + The JSON string. + The deserialized XNode + + + + Deserializes the from a JSON string nested in a root elment specified by . + + The JSON string. + The name of the root element to append when deserializing. + The deserialized XNode + + + + Deserializes the from a JSON string nested in a root elment specified by + and writes a .NET array attribute for collections. + + The JSON string. + The name of the root element to append when deserializing. + + A flag to indicate whether to write the Json.NET array attribute. + This attribute helps preserve arrays when converting the written XML back to JSON. + + The deserialized XNode + + + + Gets or sets a function that creates default . + Default settings are automatically used by serialization methods on , + and and on . + To serialize without using any default settings create a with + . + + + + + The exception thrown when an error occurs during Json serialization or deserialization. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Serializes and deserializes objects into and from the JSON format. + The enables you to control how objects are encoded into JSON. + + + + + Initializes a new instance of the class. + + + + + Creates a new instance. + The will not use default settings. + + + A new instance. + The will not use default settings. + + + + + Creates a new instance using the specified . + The will not use default settings. + + The settings to be applied to the . + + A new instance using the specified . + The will not use default settings. + + + + + Creates a new instance. + The will use default settings. + + + A new instance. + The will use default settings. + + + + + Creates a new instance using the specified . + The will use default settings. + + The settings to be applied to the . + + A new instance using the specified . + The will use default settings. + + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to reader values from. + The target object to populate values onto. + + + + Populates the JSON values onto the target object. + + The that contains the JSON structure to reader values from. + The target object to populate values onto. + + + + Deserializes the Json structure contained by the specified . + + The that contains the JSON structure to deserialize. + The being deserialized. + + + + Deserializes the Json structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Deserializes the Json structure contained by the specified + into an instance of the specified type. + + The containing the object. + The type of the object to deserialize. + The instance of being deserialized. + + + + Deserializes the Json structure contained by the specified + into an instance of the specified type. + + The containing the object. + The of object being deserialized. + The instance of being deserialized. + + + + Serializes the specified and writes the Json structure + to a Stream using the specified . + + The used to write the Json structure. + The to serialize. + + + + Serializes the specified and writes the Json structure + to a Stream using the specified . + + The used to write the Json structure. + The to serialize. + + The type of the value being serialized. + This parameter is used when is Auto to write out the type name if the type of the value does not match. + Specifing the type is optional. + + + + + Serializes the specified and writes the Json structure + to a Stream using the specified . + + The used to write the Json structure. + The to serialize. + + The type of the value being serialized. + This parameter is used when is Auto to write out the type name if the type of the value does not match. + Specifing the type is optional. + + + + + Serializes the specified and writes the Json structure + to a Stream using the specified . + + The used to write the Json structure. + The to serialize. + + + + Occurs when the errors during serialization and deserialization. + + + + + Gets or sets the used by the serializer when resolving references. + + + + + Gets or sets the used by the serializer when resolving type names. + + + + + Gets or sets the used by the serializer when writing trace messages. + + The trace writer. + + + + Gets or sets how type name writing and reading is handled by the serializer. + + + + + Gets or sets how a type name assembly is written and resolved by the serializer. + + The type name assembly format. + + + + Gets or sets how object references are preserved by the serializer. + + + + + Get or set how reference loops (e.g. a class referencing itself) is handled. + + + + + Get or set how missing members (e.g. JSON contains a property that isn't a member on the object) are handled during deserialization. + + + + + Get or set how null values are handled during serialization and deserialization. + + + + + Get or set how null default are handled during serialization and deserialization. + + + + + Gets or sets how objects are created during deserialization. + + The object creation handling. + + + + Gets or sets how constructors are used during deserialization. + + The constructor handling. + + + + Gets or sets how metadata properties are used during deserialization. + + The metadata properties handling. + + + + Gets a collection that will be used during serialization. + + Collection that will be used during serialization. + + + + Gets or sets the contract resolver used by the serializer when + serializing .NET objects to JSON and vice versa. + + + + + Gets or sets the used by the serializer when invoking serialization callback methods. + + The context. + + + + Indicates how JSON text output is formatted. + + + + + Get or set how dates are written to JSON text. + + + + + Get or set how time zones are handling during serialization and deserialization. + + + + + Get or set how date formatted strings, e.g. "\/Date(1198908717056)\/" and "2012-03-21T05:40Z", are parsed when reading JSON. + + + + + Get or set how floating point numbers, e.g. 1.0 and 9.9, are parsed when reading JSON text. + + + + + Get or set how special floating point numbers, e.g. , + and , + are written as JSON text. + + + + + Get or set how strings are escaped when writing JSON text. + + + + + Get or set how and values are formatting when writing JSON text. + + + + + Gets or sets the culture used when reading JSON. Defaults to . + + + + + Gets or sets the maximum depth allowed when reading JSON. Reading past this depth will throw a . + + + + + Gets a value indicating whether there will be a check for additional JSON content after deserializing an object. + + + true if there will be a check for additional JSON content after deserializing an object; otherwise, false. + + + + + Contains the LINQ to JSON extension methods. + + + + + Returns a collection of tokens that contains the ancestors of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the ancestors of every node in the source collection. + + + + Returns a collection of tokens that contains the descendants of every token in the source collection. + + The type of the objects in source, constrained to . + An of that contains the source collection. + An of that contains the descendants of every node in the source collection. + + + + Returns a collection of child properties of every object in the source collection. + + An of that contains the source collection. + An of that contains the properties of every object in the source collection. + + + + Returns a collection of child values of every object in the source collection with the given key. + + An of that contains the source collection. + The token key. + An of that contains the values of every node in the source collection with the given key. + + + + Returns a collection of child values of every object in the source collection. + + An of that contains the source collection. + An of that contains the values of every node in the source collection. + + + + Returns a collection of converted child values of every object in the source collection with the given key. + + The type to convert the values to. + An of that contains the source collection. + The token key. + An that contains the converted values of every node in the source collection with the given key. + + + + Returns a collection of converted child values of every object in the source collection. + + The type to convert the values to. + An of that contains the source collection. + An that contains the converted values of every node in the source collection. + + + + Converts the value. + + The type to convert the value to. + A cast as a of . + A converted value. + + + + Converts the value. + + The source collection type. + The type to convert the value to. + A cast as a of . + A converted value. + + + + Returns a collection of child tokens of every array in the source collection. + + The source collection type. + An of that contains the source collection. + An of that contains the values of every node in the source collection. + + + + Returns a collection of converted child tokens of every array in the source collection. + + An of that contains the source collection. + The type to convert the values to. + The source collection type. + An that contains the converted values of every node in the source collection. + + + + Returns the input typed as . + + An of that contains the source collection. + The input typed as . + + + + Returns the input typed as . + + The source collection type. + An of that contains the source collection. + The input typed as . + + + + Represents a JSON constructor. + + + + + Represents a token that can contain other tokens. + + + + + Raises the event. + + The instance containing the event data. + + + + Raises the event. + + The instance containing the event data. + + + + Raises the event. + + The instance containing the event data. + + + + Returns a collection of the child tokens of this token, in document order. + + + An of containing the child tokens of this , in document order. + + + + + Returns a collection of the child values of this token, in document order. + + The type to convert the values to. + + A containing the child values of this , in document order. + + + + + Returns a collection of the descendant tokens for this token in document order. + + An containing the descendant tokens of the . + + + + Adds the specified content as children of this . + + The content to be added. + + + + Adds the specified content as the first children of this . + + The content to be added. + + + + Creates an that can be used to add tokens to the . + + An that is ready to have content written to it. + + + + Replaces the children nodes of this token with the specified content. + + The content. + + + + Removes the child nodes from this token. + + + + + Merge the specified content into this . + + The content to be merged. + + + + Merge the specified content into this using . + + The content to be merged. + The used to merge the content. + + + + Occurs when the list changes or an item in the list changes. + + + + + Occurs before an item is added to the collection. + + + + + Occurs when the items list of the collection has changed, or the collection is reset. + + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets a value indicating whether this token has child tokens. + + + true if this token has child values; otherwise, false. + + + + + Get the first child token of this token. + + + A containing the first child token of the . + + + + + Get the last child token of this token. + + + A containing the last child token of the . + + + + + Gets the count of child JSON tokens. + + The count of child JSON tokens + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name and content. + + The constructor name. + The contents of the constructor. + + + + Initializes a new instance of the class with the specified name. + + The constructor name. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets or sets the name of this constructor. + + The constructor name. + + + + Gets the node type for this . + + The type. + + + + Gets the with the specified key. + + The with the specified key. + + + + Represents a collection of objects. + + The type of token + + + + An empty collection of objects. + + + + + Initializes a new instance of the struct. + + The enumerable. + + + + Returns an enumerator that iterates through the collection. + + + A that can be used to iterate through the collection. + + + + + Returns an enumerator that iterates through a collection. + + + An object that can be used to iterate through the collection. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Determines whether the specified is equal to this instance. + + The to compare with this instance. + + true if the specified is equal to this instance; otherwise, false. + + + + + Returns a hash code for this instance. + + + A hash code for this instance, suitable for use in hashing algorithms and data structures like a hash table. + + + + + Gets the with the specified key. + + + + + + Represents a JSON object. + + + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Initializes a new instance of the class with the specified content. + + The contents of the object. + + + + Gets an of this object's properties. + + An of this object's properties. + + + + Gets a the specified name. + + The property name. + A with the specified name or null. + + + + Gets an of this object's property values. + + An of this object's property values. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Gets the with the specified property name. + + Name of the property. + The with the specified property name. + + + + Gets the with the specified property name. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + Name of the property. + One of the enumeration values that specifies how the strings will be compared. + The with the specified property name. + + + + Tries to get the with the specified property name. + The exact property name will be searched for first and if no matching property is found then + the will be used to match a property. + + Name of the property. + The value. + One of the enumeration values that specifies how the strings will be compared. + true if a value was successfully retrieved; otherwise, false. + + + + Adds the specified property name. + + Name of the property. + The value. + + + + Removes the property with the specified name. + + Name of the property. + true if item was successfully removed; otherwise, false. + + + + Tries the get value. + + Name of the property. + The value. + true if a value was successfully retrieved; otherwise, false. + + + + Returns an enumerator that iterates through the collection. + + + A that can be used to iterate through the collection. + + + + + Raises the event with the provided arguments. + + Name of the property. + + + + Raises the event with the provided arguments. + + Name of the property. + + + + Returns the properties for this instance of a component. + + + A that represents the properties for this component instance. + + + + + Returns the properties for this instance of a component using the attribute array as a filter. + + An array of type that is used as a filter. + + A that represents the filtered properties for this component instance. + + + + + Returns a collection of custom attributes for this instance of a component. + + + An containing the attributes for this object. + + + + + Returns the class name of this instance of a component. + + + The class name of the object, or null if the class does not have a name. + + + + + Returns the name of this instance of a component. + + + The name of the object, or null if the object does not have a name. + + + + + Returns a type converter for this instance of a component. + + + A that is the converter for this object, or null if there is no for this object. + + + + + Returns the default event for this instance of a component. + + + An that represents the default event for this object, or null if this object does not have events. + + + + + Returns the default property for this instance of a component. + + + A that represents the default property for this object, or null if this object does not have properties. + + + + + Returns an editor of the specified type for this instance of a component. + + A that represents the editor for this object. + + An of the specified type that is the editor for this object, or null if the editor cannot be found. + + + + + Returns the events for this instance of a component using the specified attribute array as a filter. + + An array of type that is used as a filter. + + An that represents the filtered events for this component instance. + + + + + Returns the events for this instance of a component. + + + An that represents the events for this component instance. + + + + + Returns an object that contains the property described by the specified property descriptor. + + A that represents the property whose owner is to be found. + + An that represents the owner of the specified property. + + + + + Returns the responsible for binding operations performed on this object. + + The expression tree representation of the runtime value. + + The to bind this object. + + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Occurs when a property value changes. + + + + + Occurs when a property value is changing. + + + + + Gets the node type for this . + + The type. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the with the specified property name. + + + + + + Represents a JSON array. + + + + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Initializes a new instance of the class with the specified content. + + The contents of the array. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Load a from a string that contains JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + + + + Creates a from an object. + + The object that will be used to create . + A with the values of the specified object + + + + Creates a from an object. + + The object that will be used to create . + The that will be used to read the object. + A with the values of the specified object + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Determines the index of a specific item in the . + + The object to locate in the . + + The index of if found in the list; otherwise, -1. + + + + + Inserts an item to the at the specified index. + + The zero-based index at which should be inserted. + The object to insert into the . + + is not a valid index in the . + The is read-only. + + + + Removes the item at the specified index. + + The zero-based index of the item to remove. + + is not a valid index in the . + The is read-only. + + + + Returns an enumerator that iterates through the collection. + + + A that can be used to iterate through the collection. + + + + + Adds an item to the . + + The object to add to the . + The is read-only. + + + + Removes all items from the . + + The is read-only. + + + + Determines whether the contains a specific value. + + The object to locate in the . + + true if is found in the ; otherwise, false. + + + + + Copies to. + + The array. + Index of the array. + + + + Removes the first occurrence of a specific object from the . + + The object to remove from the . + + true if was successfully removed from the ; otherwise, false. This method also returns false if is not found in the original . + + The is read-only. + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets the node type for this . + + The type. + + + + Gets the with the specified key. + + The with the specified key. + + + + Gets or sets the at the specified index. + + + + + + Gets a value indicating whether the is read-only. + + true if the is read-only; otherwise, false. + + + + Represents a reader that provides fast, non-cached, forward-only access to serialized Json data. + + + + + Initializes a new instance of the class. + + The token to read from. + + + + Reads the next JSON token from the stream as a . + + + A or a null reference if the next JSON token is null. This method will return null at the end of an array. + + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream as a . + + A . This method will return null at the end of an array. + + + + Reads the next JSON token from the stream. + + + true if the next token was read successfully; false if there are no more tokens to read. + + + + + Gets the path of the current JSON token. + + + + + Represents a writer that provides a fast, non-cached, forward-only way of generating Json data. + + + + + Initializes a new instance of the class writing to the given . + + The container being written to. + + + + Initializes a new instance of the class. + + + + + Flushes whatever is in the buffer to the underlying streams and also flushes the underlying stream. + + + + + Closes this stream and the underlying stream. + + + + + Writes the beginning of a Json object. + + + + + Writes the beginning of a Json array. + + + + + Writes the start of a constructor with the given name. + + The name of the constructor. + + + + Writes the end. + + The token. + + + + Writes the property name of a name/value pair on a Json object. + + The name of the property. + + + + Writes a value. + An error will raised if the value cannot be written as a single JSON token. + + The value to write. + + + + Writes a null value. + + + + + Writes an undefined value. + + + + + Writes raw JSON. + + The raw JSON to write. + + + + Writes out a comment /*...*/ containing the specified text. + + Text to place inside the comment. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Writes a value. + + The value to write. + + + + Gets the token being writen. + + The token being writen. + + + + Represents a JSON property. + + + + + Initializes a new instance of the class from another object. + + A object to copy from. + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Initializes a new instance of the class. + + The property name. + The property content. + + + + Writes this token to a . + + A into which this method will write. + A collection of which will be used when writing the token. + + + + Loads an from a . + + A that will be read for the content of the . + A that contains the JSON that was read from the specified . + + + + Gets the container's children tokens. + + The container's children tokens. + + + + Gets the property name. + + The property name. + + + + Gets or sets the property value. + + The property value. + + + + Gets the node type for this . + + The type. + + + + Specifies the type of token. + + + + + No token type has been set. + + + + + A JSON object. + + + + + A JSON array. + + + + + A JSON constructor. + + + + + A JSON object property. + + + + + A comment. + + + + + An integer value. + + + + + A float value. + + + + + A string value. + + + + + A boolean value. + + + + + A null value. + + + + + An undefined value. + + + + + A date value. + + + + + A raw JSON value. + + + + + A collection of bytes value. + + + + + A Guid value. + + + + + A Uri value. + + + + + A TimeSpan value. + + + + + Contains the JSON schema extension methods. + + + + + Determines whether the is valid. + + The source to test. + The schema to test with. + + true if the specified is valid; otherwise, false. + + + + + Determines whether the is valid. + + The source to test. + The schema to test with. + When this method returns, contains any error messages generated while validating. + + true if the specified is valid; otherwise, false. + + + + + Validates the specified . + + The source to test. + The schema to test with. + + + + Validates the specified . + + The source to test. + The schema to test with. + The validation event handler. + + + + Returns detailed information about the schema exception. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class + with a specified error message. + + The error message that explains the reason for the exception. + + + + Initializes a new instance of the class + with a specified error message and a reference to the inner exception that is the cause of this exception. + + The error message that explains the reason for the exception. + The exception that is the cause of the current exception, or a null reference (Nothing in Visual Basic) if no inner exception is specified. + + + + Initializes a new instance of the class. + + The that holds the serialized object data about the exception being thrown. + The that contains contextual information about the source or destination. + The parameter is null. + The class name is null or is zero (0). + + + + Gets the line number indicating where the error occurred. + + The line number indicating where the error occurred. + + + + Gets the line position indicating where the error occurred. + + The line position indicating where the error occurred. + + + + Gets the path to the JSON where the error occurred. + + The path to the JSON where the error occurred. + + + + Resolves from an id. + + + + + Initializes a new instance of the class. + + + + + Gets a for the specified reference. + + The id. + A for the specified reference. + + + + Gets or sets the loaded schemas. + + The loaded schemas. + + + + Specifies undefined schema Id handling options for the . + + + + + Do not infer a schema Id. + + + + + Use the .NET type name as the schema Id. + + + + + Use the assembly qualified .NET type name as the schema Id. + + + + + Returns detailed information related to the . + + + + + Gets the associated with the validation error. + + The JsonSchemaException associated with the validation error. + + + + Gets the path of the JSON location where the validation error occurred. + + The path of the JSON location where the validation error occurred. + + + + Gets the text description corresponding to the validation error. + + The text description. + + + + Represents the callback method that will handle JSON schema validation events and the . + + + + + Resolves member mappings for a type, camel casing property names. + + + + + Used by to resolves a for a given . + + + + + Used by to resolves a for a given . + + + + + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + + If set to true the will use a cached shared with other resolvers of the same type. + Sharing the cache will significantly improve performance with multiple resolver instances because expensive reflection will only + happen once. This setting can cause unexpected behavior if different instances of the resolver are suppose to produce different + results. When set to false it is highly recommended to reuse instances with the . + + + + + Resolves the contract for a given type. + + The type to resolve a contract for. + The contract for a given type. + + + + Gets the serializable members for the type. + + The type to get serializable members for. + The serializable members for the type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates the constructor parameters. + + The constructor to create properties for. + The type's member properties. + Properties for the given . + + + + Creates a for the given . + + The matching member property. + The constructor parameter. + A created for the given . + + + + Resolves the default for the contract. + + Type of the object. + The contract's default . + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Creates a for the given type. + + Type of the object. + A for the given type. + + + + Determines which contract type is created for the given type. + + Type of the object. + A for the given type. + + + + Creates properties for the given . + + The type to create properties for. + /// The member serialization mode for the type. + Properties for the given . + + + + Creates the used by the serializer to get and set values from a member. + + The member. + The used by the serializer to get and set values from a member. + + + + Creates a for the given . + + The member's parent . + The member to create a for. + A created for the given . + + + + Resolves the name of the property. + + Name of the property. + Name of the property. + + + + Gets the resolved name of the property. + + Name of the property. + Name of the property. + + + + Gets a value indicating whether members are being get and set using dynamic code generation. + This value is determined by the runtime permissions available. + + + true if using dynamic code generation; otherwise, false. + + + + + Gets or sets the default members search flags. + + The default members search flags. + + + + Gets or sets a value indicating whether compiler generated members should be serialized. + + + true if serialized compiler generated members; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore the interface when serializing and deserializing types. + + + true if the interface will be ignored when serializing and deserializing types; otherwise, false. + + + + + Gets or sets a value indicating whether to ignore the attribute when serializing and deserializing types. + + + true if the attribute will be ignored when serializing and deserializing types; otherwise, false. + + + + + Initializes a new instance of the class. + + + + + Resolves the name of the property. + + Name of the property. + The property name camel cased. + + + + The default serialization binder used when resolving and loading classes from type names. + + + + + When overridden in a derived class, controls the binding of a serialized object to a type. + + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + The type of the object the formatter creates a new instance of. + + + + + When overridden in a derived class, controls the binding of a serialized object to a type. + + The type of the object the formatter creates a new instance of. + Specifies the name of the serialized object. + Specifies the name of the serialized object. + + + + Provides information surrounding an error. + + + + + Gets the error. + + The error. + + + + Gets the original object that caused the error. + + The original object that caused the error. + + + + Gets the member that caused the error. + + The member that caused the error. + + + + Gets the path of the JSON location where the error occurred. + + The path of the JSON location where the error occurred. + + + + Gets or sets a value indicating whether this is handled. + + true if handled; otherwise, false. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Gets the of the collection items. + + The of the collection items. + + + + Gets a value indicating whether the collection type is a multidimensional array. + + true if the collection type is a multidimensional array; otherwise, false. + + + + Handles serialization callback events. + + The object that raised the callback event. + The streaming context. + + + + Handles serialization error callback events. + + The object that raised the callback event. + The streaming context. + The error context. + + + + Sets extension data for an object during deserialization. + + The object to set extension data on. + The extension data key. + The extension data value. + + + + Gets extension data for an object during serialization. + + The object to set extension data on. + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Gets or sets the property name resolver. + + The property name resolver. + + + + Gets the of the dictionary keys. + + The of the dictionary keys. + + + + Gets the of the dictionary values. + + The of the dictionary values. + + + + Maps a JSON property to a .NET member or constructor parameter. + + + + + Returns a that represents this instance. + + + A that represents this instance. + + + + + Gets or sets the name of the property. + + The name of the property. + + + + Gets or sets the type that declared this property. + + The type that declared this property. + + + + Gets or sets the order of serialization and deserialization of a member. + + The numeric order of serialization or deserialization. + + + + Gets or sets the name of the underlying member or parameter. + + The name of the underlying member or parameter. + + + + Gets the that will get and set the during serialization. + + The that will get and set the during serialization. + + + + Gets or sets the type of the property. + + The type of the property. + + + + Gets or sets the for the property. + If set this converter takes presidence over the contract converter for the property type. + + The converter. + + + + Gets or sets the member converter. + + The member converter. + + + + Gets or sets a value indicating whether this is ignored. + + true if ignored; otherwise, false. + + + + Gets or sets a value indicating whether this is readable. + + true if readable; otherwise, false. + + + + Gets or sets a value indicating whether this is writable. + + true if writable; otherwise, false. + + + + Gets or sets a value indicating whether this has a member attribute. + + true if has a member attribute; otherwise, false. + + + + Gets the default value. + + The default value. + + + + Gets or sets a value indicating whether this is required. + + A value indicating whether this is required. + + + + Gets or sets a value indicating whether this property preserves object references. + + + true if this instance is reference; otherwise, false. + + + + + Gets or sets the property null value handling. + + The null value handling. + + + + Gets or sets the property default value handling. + + The default value handling. + + + + Gets or sets the property reference loop handling. + + The reference loop handling. + + + + Gets or sets the property object creation handling. + + The object creation handling. + + + + Gets or sets or sets the type name handling. + + The type name handling. + + + + Gets or sets a predicate used to determine whether the property should be serialize. + + A predicate used to determine whether the property should be serialize. + + + + Gets or sets a predicate used to determine whether the property should be serialized. + + A predicate used to determine whether the property should be serialized. + + + + Gets or sets an action used to set whether the property has been deserialized. + + An action used to set whether the property has been deserialized. + + + + Gets or sets the converter used when serializing the property's collection items. + + The collection's items converter. + + + + Gets or sets whether this property's collection items are serialized as a reference. + + Whether this property's collection items are serialized as a reference. + + + + Gets or sets the the type name handling used when serializing the property's collection items. + + The collection's items type name handling. + + + + Gets or sets the the reference loop handling used when serializing the property's collection items. + + The collection's items reference loop handling. + + + + A collection of objects. + + + + + Initializes a new instance of the class. + + The type. + + + + When implemented in a derived class, extracts the key from the specified element. + + The element from which to extract the key. + The key for the specified element. + + + + Adds a object. + + The property to add to the collection. + + + + Gets the closest matching object. + First attempts to get an exact case match of propertyName and then + a case insensitive match. + + Name of the property. + A matching property if found. + + + + Gets a property by property name. + + The name of the property to get. + Type property name string comparison. + A matching property if found. + + + + Specifies missing member handling options for the . + + + + + Ignore a missing member and do not attempt to deserialize it. + + + + + Throw a when a missing member is encountered during deserialization. + + + + + Specifies null value handling options for the . + + + + + + + + + Include null values when serializing and deserializing objects. + + + + + Ignore null values when serializing and deserializing objects. + + + + + Specifies reference loop handling options for the . + + + + + Throw a when a loop is encountered. + + + + + Ignore loop references and do not serialize. + + + + + Serialize loop references. + + + + + An in-memory representation of a JSON Schema. + + + + + Initializes a new instance of the class. + + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The object representing the JSON Schema. + + + + Reads a from the specified . + + The containing the JSON Schema to read. + The to use when resolving schema references. + The object representing the JSON Schema. + + + + Load a from a string that contains schema JSON. + + A that contains JSON. + A populated from the string that contains JSON. + + + + Parses the specified json. + + The json. + The resolver. + A populated from the string that contains JSON. + + + + Writes this schema to a . + + A into which this method will write. + + + + Writes this schema to a using the specified . + + A into which this method will write. + The resolver used. + + + + Returns a that represents the current . + + + A that represents the current . + + + + + Gets or sets the id. + + + + + Gets or sets the title. + + + + + Gets or sets whether the object is required. + + + + + Gets or sets whether the object is read only. + + + + + Gets or sets whether the object is visible to users. + + + + + Gets or sets whether the object is transient. + + + + + Gets or sets the description of the object. + + + + + Gets or sets the types of values allowed by the object. + + The type. + + + + Gets or sets the pattern. + + The pattern. + + + + Gets or sets the minimum length. + + The minimum length. + + + + Gets or sets the maximum length. + + The maximum length. + + + + Gets or sets a number that the value should be divisble by. + + A number that the value should be divisble by. + + + + Gets or sets the minimum. + + The minimum. + + + + Gets or sets the maximum. + + The maximum. + + + + Gets or sets a flag indicating whether the value can not equal the number defined by the "minimum" attribute. + + A flag indicating whether the value can not equal the number defined by the "minimum" attribute. + + + + Gets or sets a flag indicating whether the value can not equal the number defined by the "maximum" attribute. + + A flag indicating whether the value can not equal the number defined by the "maximum" attribute. + + + + Gets or sets the minimum number of items. + + The minimum number of items. + + + + Gets or sets the maximum number of items. + + The maximum number of items. + + + + Gets or sets the of items. + + The of items. + + + + Gets or sets a value indicating whether items in an array are validated using the instance at their array position from . + + + true if items are validated using their array position; otherwise, false. + + + + + Gets or sets the of additional items. + + The of additional items. + + + + Gets or sets a value indicating whether additional items are allowed. + + + true if additional items are allowed; otherwise, false. + + + + + Gets or sets whether the array items must be unique. + + + + + Gets or sets the of properties. + + The of properties. + + + + Gets or sets the of additional properties. + + The of additional properties. + + + + Gets or sets the pattern properties. + + The pattern properties. + + + + Gets or sets a value indicating whether additional properties are allowed. + + + true if additional properties are allowed; otherwise, false. + + + + + Gets or sets the required property if this property is present. + + The required property if this property is present. + + + + Gets or sets the a collection of valid enum values allowed. + + A collection of valid enum values allowed. + + + + Gets or sets disallowed types. + + The disallow types. + + + + Gets or sets the default value. + + The default value. + + + + Gets or sets the collection of that this schema extends. + + The collection of that this schema extends. + + + + Gets or sets the format. + + The format. + + + + Generates a from a specified . + + + + + Generate a from the specified type. + + The type to generate a from. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + Generate a from the specified type. + + The type to generate a from. + The used to resolve schema references. + Specify whether the generated root will be nullable. + A generated from the specified type. + + + + Gets or sets how undefined schemas are handled by the serializer. + + + + + Gets or sets the contract resolver. + + The contract resolver. + + + + The value types allowed by the . + + + + + No type specified. + + + + + String type. + + + + + Float type. + + + + + Integer type. + + + + + Boolean type. + + + + + Object type. + + + + + Array type. + + + + + Null type. + + + + + Any type. + + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Gets or sets the object member serialization. + + The member object serialization. + + + + Gets or sets a value that indicates whether the object's properties are required. + + + A value indicating whether the object's properties are required. + + + + + Gets the object's properties. + + The object's properties. + + + + Gets the constructor parameters required for any non-default constructor + + + + + Gets a collection of instances that define the parameters used with . + + + + + Gets or sets the override constructor used to create the object. + This is set when a constructor is marked up using the + JsonConstructor attribute. + + The override constructor. + + + + Gets or sets the parametrized constructor used to create the object. + + The parametrized constructor. + + + + Gets or sets the function used to create the object. When set this function will override . + This function is called with a collection of arguments which are defined by the collection. + + The function used to create the object. + + + + Gets or sets the extension data setter. + + + + + Gets or sets the extension data getter. + + + + + Contract details for a used by the . + + + + + Initializes a new instance of the class. + + The underlying type for the contract. + + + + Lookup and create an instance of the JsonConverter type described by the argument. + + The JsonConverter type to create. + Optional arguments to pass to an initializing constructor of the JsonConverter. + If null, the default constructor is used. + + + + Create a factory function that can be used to create instances of a JsonConverter described by the + argument type. The returned function can then be used to either invoke the converter's default ctor, or any + parameterized constructors by way of an object array. + + + + + Get and set values for a using reflection. + + + + + Initializes a new instance of the class. + + The member info. + + + + Sets the value. + + The target to set the value on. + The value to set on the target. + + + + Gets the value. + + The target to get the value from. + The value. + + + + When applied to a method, specifies that the method is called when an error occurs serializing an object. + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic that returns a result + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic, but uses one of the arguments for + the result. + + + + + Helper method for generating a MetaObject which calls a + specific method on Dynamic, but uses one of the arguments for + the result. + + + + + Returns a Restrictions object which includes our current restrictions merged + with a restriction limiting our type + + + + + Represents a method that constructs an object. + + The object type to create. + + + + Specifies type name handling options for the . + + + + + Do not include the .NET type name when serializing types. + + + + + Include the .NET type name when serializing into a JSON object structure. + + + + + Include the .NET type name when serializing into a JSON array structure. + + + + + Always include the .NET type name when serializing. + + + + + Include the .NET type name when the type of the object being serialized is not the same as its declared type. + + + + + Converts the value to the specified type. If the value is unable to be converted, the + value is checked whether it assignable to the specified type. + + The value to convert. + The culture to use when converting. + The type to convert or cast the value to. + + The converted type. If conversion was unsuccessful, the initial value + is returned if assignable to the target type. + + + + + Gets a dictionary of the names and values of an Enum type. + + + + + + Gets a dictionary of the names and values of an Enum type. + + The enum type to get names and values for. + + + + + Specifies the type of Json token. + + + + + This is returned by the if a method has not been called. + + + + + An object start token. + + + + + An array start token. + + + + + A constructor start token. + + + + + An object property name. + + + + + A comment. + + + + + Raw JSON. + + + + + An integer. + + + + + A float. + + + + + A string. + + + + + A boolean. + + + + + A null token. + + + + + An undefined token. + + + + + An object end token. + + + + + An array end token. + + + + + A constructor end token. + + + + + A Date. + + + + + Byte data. + + + + + Builds a string. Unlike StringBuilder this class lets you reuse it's internal buffer. + + + + + Determines whether the collection is null or empty. + + The collection. + + true if the collection is null or empty; otherwise, false. + + + + + Adds the elements of the specified collection to the specified generic IList. + + The list to add to. + The collection of elements to add. + + + + Returns the index of the first occurrence in a sequence by using a specified IEqualityComparer. + + The type of the elements of source. + A sequence in which to locate a value. + The object to locate in the sequence + An equality comparer to compare values. + The zero-based index of the first occurrence of value within the entire sequence, if found; otherwise, –1. + + + + Gets the type of the typed collection's items. + + The type. + The type of the typed collection's items. + + + + Gets the member's underlying type. + + The member. + The underlying type of the member. + + + + Determines whether the member is an indexed property. + + The member. + + true if the member is an indexed property; otherwise, false. + + + + + Determines whether the property is an indexed property. + + The property. + + true if the property is an indexed property; otherwise, false. + + + + + Gets the member's value on the object. + + The member. + The target object. + The member's value on the object. + + + + Sets the member's value on the target object. + + The member. + The target. + The value. + + + + Determines whether the specified MemberInfo can be read. + + The MemberInfo to determine whether can be read. + /// if set to true then allow the member to be gotten non-publicly. + + true if the specified MemberInfo can be read; otherwise, false. + + + + + Determines whether the specified MemberInfo can be set. + + The MemberInfo to determine whether can be set. + if set to true then allow the member to be set non-publicly. + if set to true then allow the member to be set if read-only. + + true if the specified MemberInfo can be set; otherwise, false. + + + + + Determines whether the string is all white space. Empty string will return false. + + The string to test whether it is all white space. + + true if the string is all white space; otherwise, false. + + + + + Nulls an empty string. + + The string. + Null if the string was null, otherwise the string unchanged. + + + + Specifies the state of the . + + + + + An exception has been thrown, which has left the in an invalid state. + You may call the method to put the in the Closed state. + Any other method calls results in an being thrown. + + + + + The method has been called. + + + + + An object is being written. + + + + + A array is being written. + + + + + A constructor is being written. + + + + + A property is being written. + + + + + A write method has not been called. + + + + diff --git a/bin/Npgsql.dll b/bin/Npgsql.dll old mode 100755 new mode 100644 index 24ca4bde64..693cccb425 Binary files a/bin/Npgsql.dll and b/bin/Npgsql.dll differ diff --git a/bin/Npgsql.xml b/bin/Npgsql.xml index a51252d119..81334301da 100644 --- a/bin/Npgsql.xml +++ b/bin/Npgsql.xml @@ -4,1379 +4,6 @@ Npgsql - - - This class represents a parameter to a command that will be sent to server - - - - - Initializes a new instance of the NpgsqlParameter class. - - - - - Initializes a new instance of the NpgsqlParameter - class with the parameter m_Name and a value of the new NpgsqlParameter. - - The m_Name of the parameter to map. - An Object that is the value of the NpgsqlParameter. - -

When you specify an Object - in the value parameter, the DbType is - inferred from the .NET Framework type of the Object.

-

When using this constructor, you must be aware of a possible misuse of the constructor which takes a DbType parameter. - This happens when calling this constructor passing an int 0 and the compiler thinks you are passing a value of DbType. - Use Convert.ToInt32(value) for example to have compiler calling the correct constructor.

-
-
- - - Initializes a new instance of the NpgsqlParameter - class with the parameter m_Name and the data type. - - The m_Name of the parameter to map. - One of the DbType values. - - - - Initializes a new instance of the NpgsqlParameter - class with the parameter m_Name, the DbType, and the size. - - The m_Name of the parameter to map. - One of the DbType values. - The length of the parameter. - - - - Initializes a new instance of the NpgsqlParameter - class with the parameter m_Name, the DbType, the size, - and the source column m_Name. - - The m_Name of the parameter to map. - One of the DbType values. - The length of the parameter. - The m_Name of the source column. - - - - Initializes a new instance of the NpgsqlParameter - class with the parameter m_Name, the DbType, the size, - the source column m_Name, a ParameterDirection, - the precision of the parameter, the scale of the parameter, a - DataRowVersion to use, and the - value of the parameter. - - The m_Name of the parameter to map. - One of the DbType values. - The length of the parameter. - The m_Name of the source column. - One of the ParameterDirection values. - true if the value of the field can be null, otherwise false. - The total number of digits to the left and right of the decimal point to which - Value is resolved. - The total number of decimal places to which - Value is resolved. - One of the DataRowVersion values. - An Object that is the value - of the NpgsqlParameter. - - - - Creates a new NpgsqlParameter that - is a copy of the current instance. - - A new NpgsqlParameter that is a copy of this instance. - - - - Gets or sets the maximum number of digits used to represent the - Value property. - - The maximum number of digits used to represent the - Value property. - The default value is 0, which indicates that the data provider - sets the precision for Value. - - - - Gets or sets the number of decimal places to which - Value is resolved. - - The number of decimal places to which - Value is resolved. The default is 0. - - - - Gets or sets the maximum size, in bytes, of the data within the column. - - The maximum size, in bytes, of the data within the column. - The default value is inferred from the parameter value. - - - - Gets or sets the DbType of the parameter. - - One of the DbType values. The default is String. - - - - Gets or sets the DbType of the parameter. - - One of the DbType values. The default is String. - - - - Gets or sets a value indicating whether the parameter is input-only, - output-only, bidirectional, or a stored procedure return value parameter. - - One of the ParameterDirection - values. The default is Input. - - - - Gets or sets a value indicating whether the parameter accepts null values. - - true if null values are accepted; otherwise, false. The default is false. - - - - Gets or sets the m_Name of the NpgsqlParameter. - - The m_Name of the NpgsqlParameter. - The default is an empty string. - - - - The m_Name scrubbed of any optional marker - - - - - Gets or sets the m_Name of the source column that is mapped to the - DataSet and used for loading or - returning the Value. - - The m_Name of the source column that is mapped to the - DataSet. The default is an empty string. - - - - Gets or sets the DataRowVersion - to use when loading Value. - - One of the DataRowVersion values. - The default is Current. - - - - Gets or sets the value of the parameter. - - An Object that is the value of the parameter. - The default value is null. - - - - Gets or sets the value of the parameter. - - An Object that is the value of the parameter. - The default value is null. - - - - This class represents the Parse message sent to PostgreSQL - server. - - - - - - For classes representing messages sent from the client to the server. - - - - - Writes given objects into a stream for PostgreSQL COPY in default copy format (not CSV or BINARY). - - - - - Return an exact copy of this NpgsqlConnectionString. - - - - - This function will set value for known key, both private member and base[key]. - - - - - - - The function will modify private member only, not base[key]. - - - - - - - Clear the member and assign them to the default value. - - - - - Compatibilty version. When possible, behaviour caused by breaking changes will be preserved - if this version is less than that where the breaking change was introduced. - - - - - Case insensative accessor for indivual connection string values. - - - - - Common base class for all derived MD5 implementations. - - - - - Called from constructor of derived class. - - - - - Finalizer for HashAlgorithm - - - - - Computes the entire hash of all the bytes in the byte array. - - - - - When overridden in a derived class, drives the hashing function. - - - - - - - - When overridden in a derived class, this pads and hashes whatever data might be left in the buffers and then returns the hash created. - - - - - When overridden in a derived class, initializes the object to prepare for hashing. - - - - - Used for stream chaining. Computes hash as data passes through it. - - The buffer from which to grab the data to be copied. - The offset into the input buffer to start reading at. - The number of bytes to be copied. - The buffer to write the copied data to. - At what point in the outputBuffer to write the data at. - - - - Used for stream chaining. Computes hash as data passes through it. Finishes off the hash. - - The buffer from which to grab the data to be copied. - The offset into the input buffer to start reading at. - The number of bytes to be copied. - - - - Get whether or not the hash can transform multiple blocks at a time. - Note: MUST be overriden if descendant can transform multiple block - on a single call! - - - - - Gets the previously computed hash. - - - - - Returns the size in bits of the hash. - - - - - Must be overriden if not 1 - - - - - Must be overriden if not 1 - - - - - Called from constructor of derived class. - - - - - Creates the default derived class. - - - - - Given a join expression and a projection, fetch all columns in the projection - that reference columns in the join. - - - - - Given an InputExpression append all from names (including nested joins) to the list. - - - - - Get new ColumnExpression that will be used in projection that had it's existing columns moved. - These should be simple references to the inner column - - - - - Every property accessed in the list of columns must be adjusted for a new scope - - - - - This class provides many util methods to handle - reading and writing of PostgreSQL protocol messages. - - - - - This method takes a ProtocolVersion and returns an integer - version number that the Postgres backend will recognize in a - startup packet. - - - - - This method takes a version string as returned by SELECT VERSION() and returns - a valid version string ("7.2.2" for example). - This is only needed when running protocol version 2. - This does not do any validity checks. - - - - - This method gets a C NULL terminated string from the network stream. - It keeps reading a byte in each time until a NULL byte is returned. - It returns the resultant string of bytes read. - This string is sent from backend. - - - - - Reads requested number of bytes from stream with retries until Stream.Read returns 0 or count is reached. - - Stream to read - byte buffer to fill - starting position to fill the buffer - number of bytes to read - The number of bytes read. May be less than count if no more bytes are available. - - - - This method writes a C NULL terminated string to the network stream. - It appends a NULL terminator to the end of the String. - - - This method writes a C NULL terminated string to the network stream. - It appends a NULL terminator to the end of the String. - - - - - This method writes a set of bytes to the stream. It also enables logging of them. - - - - - This method writes a C NULL terminated string limited in length to the - backend server. - It pads the string with null bytes to the size specified. - - - - - Write a 32-bit integer to the given stream in the correct byte order. - - - - - Read a 32-bit integer from the given stream in the correct byte order. - - - - - Write a 16-bit integer to the given stream in the correct byte order. - - - - - Read a 16-bit integer from the given stream in the correct byte order. - - - - - Represent the frontend/backend protocol version. - - - - - Represent the backend server version. - As this class offers no functionality beyond that offered by it has been - deprecated in favour of that class. - - - - - - Returns the string representation of this version in three place dot notation (Major.Minor.Patch). - - - - - Server version major number. - - - - - Server version minor number. - - - - - Server version patch level number. - - - - - Represents a PostgreSQL COPY TO STDOUT operation with a corresponding SQL statement - to execute against a PostgreSQL database - and an associated stream used to write results to (if provided by user) - or for reading the results (when generated by driver). - Eg. new NpgsqlCopyOut("COPY (SELECT * FROM mytable) TO STDOUT", connection, streamToWrite).Start(); - - - - - Creates NpgsqlCommand to run given query upon Start(), after which CopyStream provides data from database as requested in the query. - - - - - Given command is run upon Start(), after which CopyStream provides data from database as requested in the query. - - - - - Given command is executed upon Start() and all requested copy data is written to toStream immediately. - - - - - Returns true if this operation is currently active and field at given location is in binary format. - - - - - Command specified upon creation is executed as a non-query. - If CopyStream is set upon creation, all copy data from server will be written to it, and operation will be finished immediately. - Otherwise the CopyStream member can be used for reading copy data from server until no more data is available. - - - - - Flush generated CopyStream at once. Effectively reads and discard all the rest of copy data from server. - - - - - Returns true if the connection is currently reserved for this operation. - - - - - The stream provided by user or generated upon Start() - - - - - The Command used to execute this copy operation. - - - - - Returns true if this operation is currently active and in binary format. - - - - - Returns number of fields if this operation is currently active, otherwise -1 - - - - - Faster alternative to using the generated CopyStream. - - - - - This class manages all connector objects, pooled AND non-pooled. - - - - Unique static instance of the connector pool - mamager. - - - Map of index to unused pooled connectors, avaliable to the - next RequestConnector() call. - This hashmap will be indexed by connection string. - This key will hold a list of queues of pooled connectors available to be used. - - - Timer for tracking unused connections in pools. - - - - Searches the shared and pooled connector lists for a - matching connector object or creates a new one. - - The NpgsqlConnection that is requesting - the connector. Its ConnectionString will be used to search the - pool for available connectors. - A connector object. - - - - Find a pooled connector. Handle locking and timeout here. - - - - - Find a pooled connector. Handle shared/non-shared here. - - - - - Releases a connector, possibly back to the pool for future use. - - - Pooled connectors will be put back into the pool if there is room. - Shared connectors should just have their use count decremented - since they always stay in the shared pool. - - The connector to release. - - - - Release a pooled connector. Handle locking here. - - - - - Release a pooled connector. Handle shared/non-shared here. - - - - - Create a connector without any pooling functionality. - - - - - Find an available pooled connector in the non-shared pool, or create - a new one if none found. - - - - - This method is only called when NpgsqlConnection.Dispose(false) is called which means a - finalization. This also means, an NpgsqlConnection was leak. We clear pool count so that - client doesn't end running out of connections from pool. When the connection is finalized, its underlying - socket is closed. - - - - - Close the connector. - - - Connector to release - - - - Put a pooled connector into the pool queue. - - Connector to pool - - - - A queue with an extra Int32 for keeping track of busy connections. - - - - - Connections available to the end user - - - - - Connections currently in use - - - - - This class represents a BackEndKeyData message received - from PostgreSQL - - - - - Used when a connection is closed - - - - - Summary description for NpgsqlQuery - - - - - Represents the method that handles the Notice events. - - A NpgsqlNoticeEventArgs that contains the event data. - - - - Represents the method that handles the Notification events. - - The source of the event. - A NpgsqlNotificationEventArgs that contains the event data. - - - - This class represents a connection to a - PostgreSQL server. - - - - - Initializes a new instance of the - NpgsqlConnection class. - - - - - Initializes a new instance of the - NpgsqlConnection class - and sets the ConnectionString. - - The connection used to open the PostgreSQL database. - - - - Begins a database transaction with the specified isolation level. - - The isolation level under which the transaction should run. - An DbTransaction - object representing the new transaction. - - Currently the IsolationLevel ReadCommitted and Serializable are supported by the PostgreSQL backend. - There's no support for nested transactions. - - - - - Begins a database transaction. - - A NpgsqlTransaction - object representing the new transaction. - - Currently there's no support for nested transactions. - - - - - Begins a database transaction with the specified isolation level. - - The isolation level under which the transaction should run. - A NpgsqlTransaction - object representing the new transaction. - - Currently the IsolationLevel ReadCommitted and Serializable are supported by the PostgreSQL backend. - There's no support for nested transactions. - - - - - Opens a database connection with the property settings specified by the - ConnectionString. - - - - - This method changes the current database by disconnecting from the actual - database and connecting to the specified. - - The name of the database to use in place of the current database. - - - - Releases the connection to the database. If the connection is pooled, it will be - made available for re-use. If it is non-pooled, the actual connection will be shutdown. - - - - - Creates and returns a DbCommand - object associated with the IDbConnection. - - A DbCommand object. - - - - Creates and returns a NpgsqlCommand - object associated with the NpgsqlConnection. - - A NpgsqlCommand object. - - - - Releases all resources used by the - NpgsqlConnection. - - true when called from Dispose(); - false when being called from the finalizer. - - - - Create a new connection based on this one. - - A new NpgsqlConnection object. - - - - Create a new connection based on this one. - - A new NpgsqlConnection object. - - - - Default SSL CertificateSelectionCallback implementation. - - - - - Default SSL CertificateValidationCallback implementation. - - - - - Default SSL PrivateKeySelectionCallback implementation. - - - - - Default SSL ProvideClientCertificatesCallback implementation. - - - - - Write each key/value pair in the connection string to the log. - - - - - Returns the supported collections - - - - - Returns the schema collection specified by the collection name. - - The collection name. - The collection specified. - - - - Returns the schema collection specified by the collection name filtered by the restrictions. - - The collection name. - - The restriction values to filter the results. A description of the restrictions is contained - in the Restrictions collection. - - The collection specified. - - - - Occurs on NoticeResponses from the PostgreSQL backend. - - - - - Occurs on NotificationResponses from the PostgreSQL backend. - - - - - Called to provide client certificates for SSL handshake. - - - - - Mono.Security.Protocol.Tls.CertificateSelectionCallback delegate. - - - - - Mono.Security.Protocol.Tls.CertificateValidationCallback delegate. - - - - - Mono.Security.Protocol.Tls.PrivateKeySelectionCallback delegate. - - - - - Gets or sets the string used to connect to a PostgreSQL database. - Valid values are: -
    -
  • - Server: Address/Name of Postgresql Server; -
  • -
  • - Port: Port to connect to; -
  • -
  • - Protocol: Protocol version to use, instead of automatic; Integer 2 or 3; -
  • -
  • - Database: Database name. Defaults to user name if not specified; -
  • -
  • - User Id: User name; -
  • -
  • - Password: Password for clear text authentication; -
  • -
  • - SSL: True or False. Controls whether to attempt a secure connection. Default = False; -
  • -
  • - Pooling: True or False. Controls whether connection pooling is used. Default = True; -
  • -
  • - MinPoolSize: Min size of connection pool; -
  • -
  • - MaxPoolSize: Max size of connection pool; -
  • -
  • - Timeout: Time to wait for connection open in seconds. Default is 15. -
  • -
  • - CommandTimeout: Time to wait for command to finish execution before throw an exception. In seconds. Default is 20. -
  • -
  • - Sslmode: Mode for ssl connection control. Can be Prefer, Require, Allow or Disable. Default is Disable. Check user manual for explanation of values. -
  • -
  • - ConnectionLifeTime: Time to wait before closing unused connections in the pool in seconds. Default is 15. -
  • -
  • - SyncNotification: Specifies if Npgsql should use synchronous notifications. -
  • -
  • - SearchPath: Changes search path to specified and public schemas. -
  • -
-
- The connection string that includes the server name, - the database name, and other parameters needed to establish - the initial connection. The default value is an empty string. - -
- - - Backend server host name. - - - - - Backend server port. - - - - - If true, the connection will attempt to use SSL. - - - - - Gets the time to wait while trying to establish a connection - before terminating the attempt and generating an error. - - The time (in seconds) to wait for a connection to open. The default value is 15 seconds. - - - - Gets the time to wait while trying to execute a command - before terminating the attempt and generating an error. - - The time (in seconds) to wait for a command to complete. The default value is 20 seconds. - - - - Gets the time to wait before closing unused connections in the pool if the count - of all connections exeeds MinPoolSize. - - - If connection pool contains unused connections for ConnectionLifeTime seconds, - the half of them will be closed. If there will be unused connections in a second - later then again the half of them will be closed and so on. - This strategy provide smooth change of connection count in the pool. - - The time (in seconds) to wait. The default value is 15 seconds. - - - - Gets the name of the current database or the database to be used after a connection is opened. - - The name of the current database or the name of the database to be - used after a connection is opened. The default value is the empty string. - - - - Whether datareaders are loaded in their entirety (for compatibility with earlier code). - - - - - Gets the database server name. - - - - - Gets flag indicating if we are using Synchronous notification or not. - The default value is false. - - - - - Gets the current state of the connection. - - A bitwise combination of the ConnectionState values. The default is Closed. - - - - Gets whether the current state of the connection is Open or Closed - - ConnectionState.Open or ConnectionState.Closed - - - - Version of the PostgreSQL backend. - This can only be called when there is an active connection. - - - - - Protocol version in use. - This can only be called when there is an active connection. - - - - - Process id of backend server. - This can only be called when there is an active connection. - - - - - The connector object connected to the backend. - - - - - Gets the NpgsqlConnectionStringBuilder containing the parsed connection string values. - - - - - User name. - - - - - Password. - - - - - Determine if connection pooling will be used for this connection. - - - - - This class represents the CancelRequest message sent to PostgreSQL - server. - - - - - - - - - - - - - - - - - - - A time period expressed in 100ns units. - - - A time period expressed in a - - - Number of 100ns units. - - - Number of seconds. - - - Number of milliseconds. - - - Number of milliseconds. - - - Number of milliseconds. - - - A d with the given number of ticks. - - - A d with the given number of microseconds. - - - A d with the given number of milliseconds. - - - A d with the given number of seconds. - - - A d with the given number of minutes. - - - A d with the given number of hours. - - - A d with the given number of days. - - - A d with the given number of months. - - - An whose values are the sums of the two instances. - - - An whose values are the differences of the two instances. - - - An whose value is the negated value of this instance. - - - An whose value is the absolute value of this instance. - - - - An based on this one, but with any days converted to multiples of ±24hours. - - - - An based on this one, but with any months converted to multiples of ±30days. - - - - An based on this one, but with any months converted to multiples of ±30days and then any days converted to multiples of ±24hours; - - - - An eqivalent, canonical, . - - - An equivalent . - - - - - - An signed integer. - - - - The argument is not an . - - - The string was not in a format that could be parsed to produce an . - - - true if the parsing succeeded, false otherwise. - - - The representation. - - - An whose values are the sum of the arguments. - - - An whose values are the difference of the arguments - - - true if the two arguments are exactly the same, false otherwise. - - - false if the two arguments are exactly the same, true otherwise. - - - true if the first is less than second, false otherwise. - - - true if the first is less than or equivalent to second, false otherwise. - - - true if the first is greater than second, false otherwise. - - - true if the first is greater than or equivalent to the second, false otherwise. - - - The argument. - - - The negation of the argument. - - - - - - - - - - - - - - - - - - - - This time, normalised - - - - - - - - - This time, normalised - - - An integer which is 0 if they are equal, < 0 if this is the smaller and > 0 if this is the larger. - - - - - - - - - A class to handle everything associated with SSPI authentication - - - - - Simplified SecBufferDesc struct with only one SecBuffer - - - - - This class represents the Parse message sent to PostgreSQL - server. - - - - - - EventArgs class to send Notice parameters, which are just NpgsqlError's in a lighter context. - - - - - Notice information. - - - - - This class represents the ErrorResponse and NoticeResponse - message sent from PostgreSQL server. - - - - - Return a string representation of this error object. - - - - - Severity code. All versions. - - - - - Error code. PostgreSQL 7.4 and up. - - - - - Terse error message. All versions. - - - - - Detailed error message. PostgreSQL 7.4 and up. - - - - - Suggestion to help resolve the error. PostgreSQL 7.4 and up. - - - - - Position (one based) within the query string where the error was encounterd. PostgreSQL 7.4 and up. - - - - - Position (one based) within the query string where the error was encounterd. This position refers to an internal command executed for example inside a PL/pgSQL function. PostgreSQL 7.4 and up. - - - - - Internal query string where the error was encounterd. This position refers to an internal command executed for example inside a PL/pgSQL function. PostgreSQL 7.4 and up. - - - - - Trace back information. PostgreSQL 7.4 and up. - - - - - Source file (in backend) reporting the error. PostgreSQL 7.4 and up. - - - - - Source file line number (in backend) reporting the error. PostgreSQL 7.4 and up. - - - - - Source routine (in backend) reporting the error. PostgreSQL 7.4 and up. - - - - - String containing the sql sent which produced this error. - - - - - Backend protocol version in use. - - - - - Represents an ongoing COPY TO STDOUT operation. - Provides methods to read data from server or end the operation. - - - - This class represents the base class for the state pattern design pattern - implementation. - - - - - - This method is used by the states to change the state of the context. - - - - - This method is responsible to handle all protocol messages sent from the backend. - It holds all the logic to do it. - To exchange data, it uses a Mediator object from which it reads/writes information - to handle backend requests. - - - - - - This method is responsible to handle all protocol messages sent from the backend. - It holds all the logic to do it. - To exchange data, it uses a Mediator object from which it reads/writes information - to handle backend requests. - - - - - - Called from NpgsqlState.ProcessBackendResponses upon CopyOutResponse. - If CopyStream is already set, it is used to write data received from server, after which the copy ends. - Otherwise CopyStream is set to a readable NpgsqlCopyOutStream that receives data from server. - - - - - Called from NpgsqlOutStream.Read to read copy data from server. - - - - - Copy format information returned from server. - - Handles serialisation of .NET array or IEnumeration to pg format. @@ -1394,11 +21,22 @@ The that would be used to serialise the element type. - + Serialise the enumeration or array. + + + Convert a System.Array to PG binary format. + Write the array header and prepare to write array data to the stream. + + + + + Append all array data to the binary stream. + + Handles parsing of pg arrays into .NET arrays. @@ -1434,9 +72,9 @@ for the element type. - + - Creates an array from pg representation. + Creates an array from pg text representation. @@ -1448,1692 +86,33 @@ Creates an n-dimensional array from an ArrayList of ArrayLists or - a 1-dimensional array from something else. + a 1-dimensional array from something else. to convert + Type of the elements in the list produced. + + + Creates an n-dimensional System.Array from PG binary representation. + This function reads the array header and sets up an n-dimensional System.Array object to hold its data. + PopulateArrayFromBinaryArray() is then called to carry out array population. + + + + + Recursively populates an array from PB binary data representation. + + - - Takes an array of ints and treats them like the limits of a set of counters. - Retains a matching set of ints that is set to all zeros on the first ++ - On a ++ it increments the "right-most" int. If that int reaches it's - limit it is set to zero and the one before it is incremented, and so on. - - Making this a more general purpose class is pretty straight-forward, but we'll just put what we need here. - - - - This class represents the ParameterStatus message sent from PostgreSQL - server. - + Takes an array of ints and treats them like the limits of a set of counters. + Retains a matching set of ints that is set to all zeros on the first ++ + On a ++ it increments the "right-most" int. If that int reaches it's + limit it is set to zero and the one before it is incremented, and so on. - - - - This class is responsible for serving as bridge between the backend - protocol handling and the core classes. It is used as the mediator for - exchanging data generated/sent from/to backend. + Making this a more general purpose class is pretty straight-forward, but we'll just put what we need here. - - - - - This class is responsible to create database commands for automatic insert, update and delete operations. - - - - - - This method is reponsible to derive the command parameter list with values obtained from function definition. - It clears the Parameters collection of command. Also, if there is any parameter type which is not supported by Npgsql, an InvalidOperationException will be thrown. - Parameters name will be parameter1, parameter2, ... - For while, only parameter name and NpgsqlDbType are obtained. - - NpgsqlCommand whose function parameters will be obtained. - - - - Represents a completed response message. - - - - - - Marker interface which identifies a class which may take possession of a stream for the duration of - it's lifetime (possibly temporarily giving that possession to another class for part of that time. - - It inherits from IDisposable, since any such class must make sure it leaves the stream in a valid state. - - The most important such class is that compiler-generated from ProcessBackendResponsesEnum. Of course - we can't make that inherit from this interface, alas. - - - - - The exception that is thrown when the PostgreSQL backend reports errors. - - - - - Construct a backend error exception based on a list of one or more - backend errors. The basic Exception.Message will be built from the - first (usually the only) error in the list. - - - - - Format a .NET style exception string. - Include all errors in the list, including any hints. - - - - - Append a line to the given Stream, first checking for zero-length. - - - - - Provide access to the entire list of errors provided by the PostgreSQL backend. - - - - - Severity code. All versions. - - - - - Error code. PostgreSQL 7.4 and up. - - - - - Basic error message. All versions. - - - - - Detailed error message. PostgreSQL 7.4 and up. - - - - - Suggestion to help resolve the error. PostgreSQL 7.4 and up. - - - - - Position (one based) within the query string where the error was encounterd. PostgreSQL 7.4 and up. - - - - - Trace back information. PostgreSQL 7.4 and up. - - - - - Source file (in backend) reporting the error. PostgreSQL 7.4 and up. - - - - - Source file line number (in backend) reporting the error. PostgreSQL 7.4 and up. - - - - - Source routine (in backend) reporting the error. PostgreSQL 7.4 and up. - - - - - String containing the sql sent which produced this error. - - - - - Returns the entire list of errors provided by the PostgreSQL backend. - - - - - The level of verbosity of the NpgsqlEventLog - - - - - Don't log at all - - - - - Only log the most common issues - - - - - Log everything - - - - - This class handles all the Npgsql event and debug logging - - - - - Writes a string to the Npgsql event log if msglevel is bigger then NpgsqlEventLog.Level - - - This method is obsolete and should no longer be used. - It is likely to be removed in future versions of Npgsql - - The message to write to the event log - The minimum LogLevel for which this message should be logged. - - - - Writes a string to the Npgsql event log if msglevel is bigger then NpgsqlEventLog.Level - - The ResourceManager to get the localized resources - The name of the resource that should be fetched by the ResourceManager - The minimum LogLevel for which this message should be logged. - The additional parameters that shall be included into the log-message (must be compatible with the string in the resource): - - - - Writes the default log-message for the action of calling the Get-part of an Indexer to the log file. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Indexer - The parameter given to the Indexer - - - - Writes the default log-message for the action of calling the Set-part of an Indexer to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Indexer - The parameter given to the Indexer - The value the Indexer is set to - - - - Writes the default log-message for the action of calling the Get-part of a Property to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Property - The name of the Property - - - - Writes the default log-message for the action of calling the Set-part of a Property to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Property - The name of the Property - The value the Property is set to - - - - Writes the default log-message for the action of calling a Method without Arguments to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Method - The name of the Method - - - - Writes the default log-message for the action of calling a Method with one Argument to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Method - The name of the Method - The value of the Argument of the Method - - - - Writes the default log-message for the action of calling a Method with two Arguments to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Method - The name of the Method - The value of the first Argument of the Method - The value of the second Argument of the Method - - - - Writes the default log-message for the action of calling a Method with three Arguments to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Method - The name of the Method - The value of the first Argument of the Method - The value of the second Argument of the Method - The value of the third Argument of the Method - - - - Writes the default log-message for the action of calling a Method with more than three Arguments to the logfile. - - The minimum LogLevel for which this message should be logged. - The name of the class that contains the Method - The name of the Method - A Object-Array with zero or more Ojects that are Arguments of the Method. - - - - Sets/Returns the level of information to log to the logfile. - - The current LogLevel - - - - Sets/Returns the filename to use for logging. - - The filename of the current Log file. - - - - Sets/Returns whether Log messages should be echoed to the console - - true if Log messages are echoed to the console, otherwise false - - - - This class represents the Parse message sent to PostgreSQL - server. - - - - - - Represents a PostgreSQL COPY FROM STDIN operation with a corresponding SQL statement - to execute against a PostgreSQL database - and an associated stream used to read data from (if provided by user) - or for writing it (when generated by driver). - Eg. new NpgsqlCopyIn("COPY mytable FROM STDIN", connection, streamToRead).Start(); - - - - - Creates NpgsqlCommand to run given query upon Start(). Data for the requested COPY IN operation can then be written to CopyData stream followed by a call to End() or Cancel(). - - - - - Given command is run upon Start(). Data for the requested COPY IN operation can then be written to CopyData stream followed by a call to End() or Cancel(). - - - - - Given command is executed upon Start() and all data from fromStream is passed to it as copy data. - - - - - Returns true if this operation is currently active and field at given location is in binary format. - - - - - Command specified upon creation is executed as a non-query. - If CopyStream is set upon creation, it will be flushed to server as copy data, and operation will be finished immediately. - Otherwise the CopyStream member can be used for writing copy data to server and operation finished with a call to End() or Cancel(). - - - - - Called after writing all data to CopyStream to successfully complete this copy operation. - - - - - Withdraws an already started copy operation. The operation will fail with given error message. - Will do nothing if current operation is not active. - - - - - Returns true if the connection is currently reserved for this operation. - - - - - The stream provided by user or generated upon Start(). - User may provide a stream to constructor; it is used to pass to server all data read from it. - Otherwise, call to Start() sets this to a writable NpgsqlCopyInStream that passes all data written to it to server. - In latter case this is only available while the copy operation is active and null otherwise. - - - - - Returns true if this operation is currently active and in binary format. - - - - - Returns number of fields expected on each input row if this operation is currently active, otherwise -1 - - - - - The Command used to execute this copy operation. - - - - - Set before a COPY IN query to define size of internal buffer for reading from given CopyStream. - - - - - Represents information about COPY operation data transfer format as returned by server. - - - - - Only created when a CopyInResponse or CopyOutResponse is received by NpgsqlState.ProcessBackendResponses() - - - - - Returns true if this operation is currently active and field at given location is in binary format. - - - - - Returns true if this operation is currently active and in binary format. - - - - - Returns number of fields if this operation is currently active, otherwise -1 - - - - - - - - - Provide event handlers to convert all native supported basic data types from their backend - text representation to a .NET object. - - - - - Binary data. - - - - - Convert a postgresql boolean to a System.Boolean. - - - - - Convert a postgresql bit to a System.Boolean. - - - - - Convert a postgresql datetime to a System.DateTime. - - - - - Convert a postgresql date to a System.DateTime. - - - - - Convert a postgresql time to a System.DateTime. - - - - - Convert a postgresql money to a System.Decimal. - - - - - Provide event handlers to convert the basic native supported data types from - native form to backend representation. - - - - - Binary data. - - - - - Convert to a postgresql boolean. - - - - - Convert to a postgresql bit. - - - - - Convert to a postgresql timestamp. - - - - - Convert to a postgresql date. - - - - - Convert to a postgresql time. - - - - - Convert to a postgres money. - - - - - Convert to a postgres double with maximum precision. - - - - - Provide event handlers to convert extended native supported data types from their backend - text representation to a .NET object. - - - - - Convert a postgresql point to a System.NpgsqlPoint. - - - - - Convert a postgresql point to a System.RectangleF. - - - - - LDeg. - - - - - Path. - - - - - Polygon. - - - - - Circle. - - - - - Inet. - - - - - MAC Address. - - - - - interval - - - - - Provide event handlers to convert extended native supported data types from - native form to backend representation. - - - - - Point. - - - - - Box. - - - - - LSeg. - - - - - Open path. - - - - - Polygon. - - - - - Convert to a postgres MAC Address. - - - - - Circle. - - - - - Convert to a postgres inet. - - - - - Convert to a postgres interval - - - - - EventArgs class to send Notification parameters. - - - - - Process ID of the PostgreSQL backend that sent this notification. - - - - - Condition that triggered that notification. - - - - - Additional Information From Notifiying Process (for future use, currently postgres always sets this to an empty string) - - - - - Resolve a host name or IP address. - This is needed because if you call Dns.Resolve() with an IP address, it will attempt - to resolve it as a host name, when it should just convert it to an IP address. - - - - - - This class represents a RowDescription message sent from - the PostgreSQL. - - - - - - This struct represents the internal data of the RowDescription message. - - - - - This class represents the Parse message sent to PostgreSQL - server. - - - - - - A factory to create instances of various Npgsql objects. - - - - - Creates an NpgsqlCommand object. - - - - - This class represents the Parse message sent to PostgreSQL - server. - - - - - - Represents the method that handles the RowUpdated events. - - The source of the event. - A NpgsqlRowUpdatedEventArgs that contains the event data. - - - - Represents the method that handles the RowUpdating events. - - The source of the event. - A NpgsqlRowUpdatingEventArgs that contains the event data. - - - - This class represents an adapter from many commands: select, update, insert and delete to fill Datasets. - - - - - Stream for reading data from a table or select on a PostgreSQL version 7.4 or newer database during an active COPY TO STDOUT operation. - Passes data exactly as provided by the server. - - - - - Created only by NpgsqlCopyOutState.StartCopy() - - - - - Discards copy data as long as server pushes it. Returns after operation is finished. - Does nothing if this stream is not the active copy operation reader. - - - - - Not writable. - - - - - Not flushable. - - - - - Copies data read from server to given byte buffer. - Since server returns data row by row, length will differ each time, but it is only zero once the operation ends. - Can be mixed with calls to the more efficient NpgsqlCopyOutStream.Read() : byte[] though that would not make much sense. - - - - - Not seekable - - - - - Not supported - - - - - Returns a whole row of data from server without extra work. - If standard Stream.Read(...) has been called before, it's internal buffers remains are returned. - - - - - True while this stream can be used to read copy data from server - - - - - True - - - - - False - - - - - False - - - - - Number of bytes read so far - - - - - Number of bytes read so far; can not be set. - - - - - This class represents the Bind message sent to PostgreSQL - server. - - - - - - Summary description for LargeObjectManager. - - - - - Represents a transaction to be made in a PostgreSQL database. This class cannot be inherited. - - - - - Commits the database transaction. - - - - - Rolls back a transaction from a pending state. - - - - - Rolls back a transaction from a pending savepoint state. - - - - - Creates a transaction save point. - - - - - Cancel the transaction without telling the backend about it. This is - used to make the transaction go away when closing a connection. - - - - - Gets the NpgsqlConnection - object associated with the transaction, or a null reference if the - transaction is no longer valid. - - The NpgsqlConnection - object associated with the transaction. - - - - Specifies the IsolationLevel for this transaction. - - The IsolationLevel for this transaction. - The default is ReadCommitted. - - - - This class represents a StartupPacket message of PostgreSQL - protocol. - - - - - - Provides a means of reading a forward-only stream of rows from a PostgreSQL backend. This class cannot be inherited. - - - - - Return the data type name of the column at index . - - - - - Return the data type of the column at index . - - - - - Return the Npgsql specific data type of the column at requested ordinal. - - column position - Appropriate Npgsql type for column. - - - - Return the column name of the column at index . - - - - - Return the data type OID of the column at index . - - FIXME: Why this method returns String? - - - - Return the column name of the column named . - - - - - Return the data DbType of the column at index . - - - - - Return the data NpgsqlDbType of the column at index . - - - - - Get the value of a column as a . - If the differences between and - in handling of days and months is not important to your application, use - instead. - - Index of the field to find. - value of the field. - - - - Gets the value of a column converted to a Guid. - - - - - Gets the value of a column as Int16. - - - - - Gets the value of a column as Int32. - - - - - Gets the value of a column as Int64. - - - - - Gets the value of a column as Single. - - - - - Gets the value of a column as Double. - - - - - Gets the value of a column as String. - - - - - Gets the value of a column as Decimal. - - - - - Gets the value of a column as TimeSpan. - - - - - Copy values from each column in the current row into . - - The number of column values copied. - - - - Copy values from each column in the current row into . - - An array appropriately sized to store values from all columns. - The number of column values copied. - - - - Gets the value of a column as Boolean. - - - - - Gets the value of a column as Byte. Not implemented. - - - - - Gets the value of a column as Char. - - - - - Gets the value of a column as DateTime. - - - - - Returns a System.Data.DataTable that describes the column metadata of the DataReader. - - - - - This methods parses the command text and tries to get the tablename - from it. - - - - - Is raised whenever Close() is called. - - - - - Gets the number of columns in the current row. - - - - - Gets the value of a column in its native format. - - - - - Gets the value of a column in its native format. - - - - - Gets a value indicating the depth of nesting for the current row. Always returns zero. - - - - - Gets a value indicating whether the data reader is closed. - - - - - Contains the column names as the keys - - - - - Contains all unique columns - - - - - This is the primary implementation of NpgsqlDataReader. It is the one used in normal cases (where the - preload-reader option is not set in the connection string to resolve some potential backwards-compatibility - issues), the only implementation used internally, and in cases where CachingDataReader is used, it is still - used to do the actual "leg-work" of turning a response stream from the server into a datareader-style - object - with CachingDataReader then filling it's cache from here. - - - - - Iterate through the objects returned through from the server. - If it's a CompletedResponse the rowsaffected count is updated appropriately, - and we iterate again, otherwise we return it (perhaps updating our cache of pending - rows if appropriate). - - The next we will deal with. - - - - Advances the data reader to the next result, when multiple result sets were returned by the PostgreSQL backend. - - True if the reader was advanced, otherwise false. - - - - Releases the resources used by the NpgsqlCommand. - - - - - Closes the data reader object. - - - - - Advances the data reader to the next result, when multiple result sets were returned by the PostgreSQL backend. - - True if the reader was advanced, otherwise false. - - - - Advances the data reader to the next row. - - True if the reader was advanced, otherwise false. - - - - Return the value of the column at index . - - - - - Gets raw data from a column. - - - - - Gets raw data from a column. - - - - - Report whether the value in a column is DBNull. - - - - - Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. - - - - - Indicates if NpgsqlDatareader has rows to be read. - - - - - Provides an implementation of NpgsqlDataReader in which all data is pre-loaded into memory. - This operates by first creating a ForwardsOnlyDataReader as usual, and then loading all of it's - Rows into memory. There is a general principle that when there is a trade-off between a class design that - is more efficient and/or scalable on the one hand and one that is less efficient but has more functionality - (in this case the internal-only functionality of caching results) that one can build the less efficent class - from the most efficient without significant extra loss in efficiency, but not the other way around. The relationship - between ForwardsOnlyDataReader and CachingDataReader is an example of this). - Since the interface presented to the user is still forwards-only, queues are used to - store this information, so that dequeueing as we go we give the garbage collector the best opportunity - possible to reclaim any memory that is no longer in use. - ForwardsOnlyDataReader being used to actually - obtain the information from the server means that the "leg-work" is still only done (and need only be - maintained) in one place. - This class exists to allow for certain potential backwards-compatibility issues to be resolved - with little effort on the part of affected users. It is considerably less efficient than ForwardsOnlyDataReader - and hence never used internally. - - - - - Represents the method that allows the application to provide a certificate collection to be used for SSL clien authentication - - A X509CertificateCollection to be filled with one or more client certificates. - - - - !!! Helper class, for compilation only. - Connector implements the logic for the Connection Objects to - access the physical connection to the database, and isolate - the application developer from connection pooling internals. - - - - - Constructor. - - Controls whether the connector can be shared. - - - - This method checks if the connector is still ok. - We try to send a simple query text, select 1 as ConnectionTest; - - - - - This method is responsible for releasing all resources associated with this Connector. - - - - - This method is responsible to release all portals used by this Connector. - - - - - Default SSL CertificateSelectionCallback implementation. - - - - - Default SSL CertificateValidationCallback implementation. - - - - - Default SSL PrivateKeySelectionCallback implementation. - - - - - Default SSL ProvideClientCertificatesCallback implementation. - - - - - This method is required to set all the version dependent features flags. - SupportsPrepare means the server can use prepared query plans (7.3+) - - - - - Opens the physical connection to the server. - - Usually called by the RequestConnector - Method of the connection pool manager. - - - - Closes the physical connection to the server. - - - - - Returns next portal index. - - - - - Returns next plan index. - - - - - Occurs on NoticeResponses from the PostgreSQL backend. - - - - - Occurs on NotificationResponses from the PostgreSQL backend. - - - - - Called to provide client certificates for SSL handshake. - - - - - Mono.Security.Protocol.Tls.CertificateSelectionCallback delegate. - - - - - Mono.Security.Protocol.Tls.CertificateValidationCallback delegate. - - - - - Mono.Security.Protocol.Tls.PrivateKeySelectionCallback delegate. - - - - - Gets the current state of the connection. - - - - - Return Connection String. - - - - - Version of backend server this connector is connected to. - - - - - Backend protocol version in use by this connector. - - - - - The physical connection stream to the backend. - - - - - The physical connection socket to the backend. - - - - - Reports if this connector is fully connected. - - - - - The connection mediator. - - - - - Report if the connection is in a transaction. - - - - - Report whether the current connection can support prepare functionality. - - - - - This class contains helper methods for type conversion between - the .Net type system and postgresql. - - - - - A cache of basic datatype mappings keyed by server version. This way we don't - have to load the basic type mappings for every connection. - - - - - Find a NpgsqlNativeTypeInfo in the default types map that can handle objects - of the given NpgsqlDbType. - - - - - Find a NpgsqlNativeTypeInfo in the default types map that can handle objects - of the given NpgsqlDbType. - - - - - Find a NpgsqlNativeTypeInfo in the default types map that can handle objects - of the given DbType. - - - - - Find a NpgsqlNativeTypeInfo in the default types map that can handle objects - of the given System.Type. - - - - - This method is responsible to convert the string received from the backend - to the corresponding NpgsqlType. - The given TypeInfo is called upon to do the conversion. - If no TypeInfo object is provided, no conversion is performed. - - - - - Create the one and only native to backend type map. - This map is used when formatting native data - types to backend representations. - - - - - This method creates (or retrieves from cache) a mapping between type and OID - of all natively supported postgresql data types. - This is needed as from one version to another, this mapping can be changed and - so we avoid hardcoding them. - - NpgsqlTypeMapping containing all known data types. The mapping must be - cloned before it is modified because it is cached; changes made by one connection may - effect another connection. - - - - Attempt to map types by issuing a query against pg_type. - This function takes a list of NpgsqlTypeInfo and attempts to resolve the OID field - of each by querying pg_type. If the mapping is found, the type info object is - updated (OID) and added to the provided NpgsqlTypeMapping object. - - NpgsqlConnector to send query through. - Mapping object to add types too. - List of types that need to have OID's mapped. - - - - Delegate called to convert the given backend data to its native representation. - - - - - Delegate called to convert the given native data to its backand representation. - - - - - Represents a backend data type. - This class can be called upon to convert a backend field representation to a native object. - - - - - Construct a new NpgsqlTypeInfo with the given attributes and conversion handlers. - - Type OID provided by the backend server. - Type name provided by the backend server. - NpgsqlDbType - System type to convert fields of this type to. - Data conversion handler. - - - - Perform a data conversion from a backend representation to - a native object. - - Data sent from the backend. - Type modifier field sent from the backend. - - - - Type OID provided by the backend server. - - - - - Type name provided by the backend server. - - - - - NpgsqlDbType. - - - - - NpgsqlDbType. - - - - - Provider type to convert fields of this type to. - - - - - System type to convert fields of this type to. - - - - - Represents a backend data type. - This class can be called upon to convert a native object to its backend field representation, - - - - - Returns an NpgsqlNativeTypeInfo for an array where the elements are of the type - described by the NpgsqlNativeTypeInfo supplied. - - - - - Construct a new NpgsqlTypeInfo with the given attributes and conversion handlers. - - Type name provided by the backend server. - NpgsqlDbType - Data conversion handler. - - - - Perform a data conversion from a native object to - a backend representation. - DBNull and null values are handled differently depending if a plain query is used - When - - Native .NET object to be converted. - Flag indicating if the conversion has to be done for - plain queries or extended queries - - - - Type name provided by the backend server. - - - - - NpgsqlDbType. - - - - - DbType. - - - - - Apply quoting. - - - - - Use parameter size information. - - - - - Provide mapping between type OID, type name, and a NpgsqlBackendTypeInfo object that represents it. - - - - - Construct an empty mapping. - - - - - Copy constuctor. - - - - - Add the given NpgsqlBackendTypeInfo to this mapping. - - - - - Add a new NpgsqlBackendTypeInfo with the given attributes and conversion handlers to this mapping. - - Type OID provided by the backend server. - Type name provided by the backend server. - NpgsqlDbType - System type to convert fields of this type to. - Data conversion handler. - - - - Make a shallow copy of this type mapping. - - - - - Determine if a NpgsqlBackendTypeInfo with the given backend type OID exists in this mapping. - - - - - Determine if a NpgsqlBackendTypeInfo with the given backend type name exists in this mapping. - - - - - Get the number of type infos held. - - - - - Retrieve the NpgsqlBackendTypeInfo with the given backend type OID, or null if none found. - - - - - Retrieve the NpgsqlBackendTypeInfo with the given backend type name, or null if none found. - - - - - Provide mapping between type Type, NpgsqlDbType and a NpgsqlNativeTypeInfo object that represents it. - - - - - Add the given NpgsqlNativeTypeInfo to this mapping. - - - - - Add a new NpgsqlNativeTypeInfo with the given attributes and conversion handlers to this mapping. - - Type name provided by the backend server. - NpgsqlDbType - Data conversion handler. - - - - Retrieve the NpgsqlNativeTypeInfo with the given NpgsqlDbType. - - - - - Retrieve the NpgsqlNativeTypeInfo with the given DbType. - - - - - Retrieve the NpgsqlNativeTypeInfo with the given Type. - - - - - Determine if a NpgsqlNativeTypeInfo with the given backend type name exists in this mapping. - - - - - Determine if a NpgsqlNativeTypeInfo with the given NpgsqlDbType exists in this mapping. - - - - - Determine if a NpgsqlNativeTypeInfo with the given Type name exists in this mapping. - - - - - Get the number of type infos held. - - - - - Implements for version 3 of the protocol. - - - - - Reads a row, field by field, allowing a DataRow to be built appropriately. - - - - - Reads part of a field, as needed (for - and - - - - - Adds further functionality to stream that is dependant upon the type of data read. - - - - - Completes the implementation of Streamer for char data. - - - - - Completes the implementation of Streamer for byte data. - - - - - Implements for version 2 of the protocol. - - - - - Encapsulates the null mapping bytes sent at the start of a version 2 - datarow message, and the process of identifying the nullity of the data - at a particular index - - - - - Provides the underlying mechanism for reading schema information. - - - - - Creates an NpgsqlSchema that can read schema information from the database. - - An open database connection for reading metadata. - - - - Returns the MetaDataCollections that lists all possible collections. - - The MetaDataCollections - - - - Returns the Restrictions that contains the meaning and position of the values in the restrictions array. - - The Restrictions - - - - Returns the Databases that contains a list of all accessable databases. - - The restrictions to filter the collection. - The Databases - - - - Returns the Tables that contains table and view names and the database and schema they come from. - - The restrictions to filter the collection. - The Tables - - - - Returns the Columns that contains information about columns in tables. - - The restrictions to filter the collection. - The Columns. - - - - Returns the Views that contains view names and the database and schema they come from. - - The restrictions to filter the collection. - The Views - - - - Returns the Users containing user names and the sysid of those users. - - The restrictions to filter the collection. - The Users. - - - - This is the abstract base class for NpgsqlAsciiRow and NpgsqlBinaryRow. - @@ -3166,7 +145,7 @@ Creats a bitstring from a string. The string to copy from. - + @@ -3322,7 +301,7 @@ The object to compare with. If the object is null then this string is considered greater. If the object is another BitString - then they are compared as in the explicit comparison for BitStrings + then they are compared as in the explicit comparison for BitStrings in any other case a is thrown. @@ -3534,6 +513,1605 @@ Retrieves the value of the bit at the given index.
+ + + Represents the PostgreSQL interval datatype. + PostgreSQL differs from .NET in how it's interval type doesn't assume 24 hours in a day + (to deal with 23- and 25-hour days caused by daylight savings adjustments) and has a concept + of months that doesn't exist in .NET's class. (Neither datatype + has any concessions for leap-seconds). + For most uses just casting to and from TimeSpan will work correctly — in particular, + the results of subtracting one or the PostgreSQL date, time and + timestamp types from another should be the same whether you do so in .NET or PostgreSQL — + but if the handling of days and months in PostgreSQL is important to your application then you + should use this class instead of . + If you don't know whether these differences are important to your application, they + probably arent! Just use and do not use this class directly ☺ + To avoid forcing unnecessary provider-specific concerns on users who need not be concerned + with them a call to on a field containing an + value will return a rather than an + . If you need the extra functionality of + then use . + + + + + + + + + + Represents the number of ticks (100ns periods) in one microsecond. This field is constant. + + + + + Represents the number of ticks (100ns periods) in one millisecond. This field is constant. + + + + + Represents the number of ticks (100ns periods) in one second. This field is constant. + + + + + Represents the number of ticks (100ns periods) in one minute. This field is constant. + + + + + Represents the number of ticks (100ns periods) in one hour. This field is constant. + + + + + Represents the number of ticks (100ns periods) in one day. This field is constant. + + + + + Represents the number of hours in one day (assuming no daylight savings adjustments). This field is constant. + + + + + Represents the number of days assumed in one month if month justification or unjustifcation is performed. + This is set to 30 for consistency with PostgreSQL. Note that this is means that month adjustments cause + a year to be taken as 30 × 12 = 360 rather than 356/366 days. + + + + + Represents the number of ticks (100ns periods) in one day, assuming 30 days per month. + + + + + Represents the number of months in a year. This field is constant. + + + + + Represents the maximum . This field is read-only. + + + + + Represents the minimum . This field is read-only. + + + + + Represents the zero . This field is read-only. + + + + + Initializes a new to the specified number of ticks. + + A time period expressed in 100ns units. + + + + Initializes a new to hold the same time as a + + A time period expressed in a + + + + Initializes a new to the specified number of months, days + & ticks. + + Number of months. + Number of days. + Number of 100ns units. + + + + Initializes a new to the specified number of + days, hours, minutes & seconds. + + Number of days. + Number of hours. + Number of minutes. + Number of seconds. + + + + Initializes a new to the specified number of + days, hours, minutes, seconds & milliseconds. + + Number of days. + Number of hours. + Number of minutes. + Number of seconds. + Number of milliseconds. + + + + Initializes a new to the specified number of + months, days, hours, minutes, seconds & milliseconds. + + Number of months. + Number of days. + Number of hours. + Number of minutes. + Number of seconds. + Number of milliseconds. + + + + Initializes a new to the specified number of + years, months, days, hours, minutes, seconds & milliseconds. + Years are calculated exactly equivalent to 12 months. + + Number of years. + Number of months. + Number of days. + Number of hours. + Number of minutes. + Number of seconds. + Number of milliseconds. + + + + Creates an from a number of ticks. + + The number of ticks (100ns units) in the interval. + A d with the given number of ticks. + + + + Creates an from a number of microseconds. + + The number of microseconds in the interval. + A d with the given number of microseconds. + + + + Creates an from a number of milliseconds. + + The number of milliseconds in the interval. + A d with the given number of milliseconds. + + + + Creates an from a number of seconds. + + The number of seconds in the interval. + A d with the given number of seconds. + + + + Creates an from a number of minutes. + + The number of minutes in the interval. + A d with the given number of minutes. + + + + Creates an from a number of hours. + + The number of hours in the interval. + A d with the given number of hours. + + + + Creates an from a number of days. + + The number of days in the interval. + A d with the given number of days. + + + + Creates an from a number of months. + + The number of months in the interval. + A d with the given number of months. + + + + Adds another interval to this instance and returns the result. + + An to add to this instance. + An whose values are the sums of the two instances. + + + + Subtracts another interval from this instance and returns the result. + + An to subtract from this instance. + An whose values are the differences of the two instances. + + + + Returns an whose value is the negated value of this instance. + + An whose value is the negated value of this instance. + + + + This absolute value of this instance. In the case of some, but not all, components being negative, + the rules used for justification are used to determine if the instance is positive or negative. + + An whose value is the absolute value of this instance. + + + + Equivalent to PostgreSQL's justify_days function. + + An based on this one, but with any hours outside of the range [-23, 23] + converted into days. + + + + Opposite to PostgreSQL's justify_days function. + + An based on this one, but with any days converted to multiples of ±24hours. + + + + Equivalent to PostgreSQL's justify_months function. + + An based on this one, but with any days outside of the range [-30, 30] + converted into months. + + + + Opposite to PostgreSQL's justify_months function. + + An based on this one, but with any months converted to multiples of ±30days. + + + + Equivalent to PostgreSQL's justify_interval function. + + An based on this one, + but with any months converted to multiples of ±30days + and then with any days converted to multiples of ±24hours + + + + Opposite to PostgreSQL's justify_interval function. + + An based on this one, but with any months converted to multiples of ±30days and then any days converted to multiples of ±24hours; + + + + Produces a canonical NpgslInterval with 0 months and hours in the range of [-23, 23]. + + + While the fact that for many purposes, two different instances could be considered + equivalent (e.g. one with 2days, 3hours and one with 1day 27hours) there are different possible canonical forms. + + E.g. we could move all excess hours into days and all excess days into months and have the most readable form, + or we could move everything into the ticks and have the form that allows for the easiest arithmetic) the form + chosen has two important properties that make it the best choice. + First, it is closest two how + objects are most often represented. Second, it is compatible with results of many + PostgreSQL functions, particularly with age() and the results of subtracting one date, time or timestamp from + another. + + Note that the results of casting a to is + canonicalised. + + + An based on this one, but with months converted to multiples of ±30days and with any hours outside of the range [-23, 23] + converted into days. + + + + Implicit cast of a to an + + A + An eqivalent, canonical, . + + + + Implicit cast of an to a . + + A . + An equivalent . + + + + Returns true if another is exactly the same as this instance. + + An for comparison. + true if the two instances are exactly the same, + false otherwise. + + + + Returns true if another object is an , that is exactly the same as + this instance + + An for comparison. + true if the argument is an and is exactly the same + as this one, false otherwise. + + + + Compares two instances. + + The first . + The second . + 0 if the two are equal or equivalent. A value greater than zero if x is greater than y, + a value less than zero if x is less than y. + + + + A hash code suitable for uses with hashing algorithms. + + An signed integer. + + + + Compares this instance with another/ + + An to compare this with. + 0 if the instances are equal or equivalent. A value less than zero if + this instance is less than the argument. A value greater than zero if this instance + is greater than the instance. + + + + Compares this instance with another/ + + An object to compare this with. + 0 if the argument is an and the instances are equal or equivalent. + A value less than zero if the argument is an and + this instance is less than the argument. + A value greater than zero if the argument is an and this instance + is greater than the instance. + A value greater than zero if the argument is null. + The argument is not an . + + + + Parses a and returns a instance. + Designed to use the formats generally returned by PostgreSQL. + + The to parse. + An represented by the argument. + The string was null. + A value obtained from parsing the string exceeded the values allowed for the relevant component. + The string was not in a format that could be parsed to produce an . + + + + Attempt to parse a to produce an . + + The to parse. + (out) The produced, or if the parsing failed. + true if the parsing succeeded, false otherwise. + + + + Create a representation of the instance. + The format returned is of the form: + [M mon[s]] [d day[s]] [HH:mm:ss[.f[f[f[f[f[f[f[f[f]]]]]]]]]] + A zero is represented as 00:00:00 + + Ticks are 100ns, Postgress resolution is only to 1µs at most. Hence we lose 1 or more decimal + precision in storing values in the database. Despite this, this method will output that extra + digit of precision. It's forward-compatible with any future increases in resolution up to 100ns, + and also makes this ToString() more applicable to any other use-case. + + + The representation. + + + + Adds two together. + + The first to add. + The second to add. + An whose values are the sum of the arguments. + + + + Subtracts one from another. + + The to subtract the other from. + The to subtract from the other. + An whose values are the difference of the arguments + + + + Returns true if two are exactly the same. + + The first to compare. + The second to compare. + true if the two arguments are exactly the same, false otherwise. + + + + Returns false if two are exactly the same. + + The first to compare. + The second to compare. + false if the two arguments are exactly the same, true otherwise. + + + + Compares two instances to see if the first is less than the second + + The first to compare. + The second to compare. + true if the first is less than second, false otherwise. + + + + Compares two instances to see if the first is less than or equivalent to the second + + The first to compare. + The second to compare. + true if the first is less than or equivalent to second, false otherwise. + + + + Compares two instances to see if the first is greater than the second + + The first to compare. + The second to compare. + true if the first is greater than second, false otherwise. + + + + Compares two instances to see if the first is greater than or equivalent the second + + The first to compare. + The second to compare. + true if the first is greater than or equivalent to the second, false otherwise. + + + + Returns the instance. + + An . + The argument. + + + + Negates an instance. + + An . + The negation of the argument. + + + + The total number of ticks(100ns units) contained. This is the resolution of the + type. This ignores the number of days and + months held. If you want them included use first. + The resolution of the PostgreSQL + interval type is by default 1µs = 1,000 ns. It may be smaller as follows: + + + interval(0) + resolution of 1s (1 second) + + + interval(1) + resolution of 100ms = 0.1s (100 milliseconds) + + + interval(2) + resolution of 10ms = 0.01s (10 milliseconds) + + + interval(3) + resolution of 1ms = 0.001s (1 millisecond) + + + interval(4) + resolution of 100µs = 0.0001s (100 microseconds) + + + interval(5) + resolution of 10µs = 0.00001s (10 microseconds) + + + interval(6) or interval + resolution of 1µs = 0.000001s (1 microsecond) + + + As such, if the 100-nanosecond resolution is significant to an application, a PostgreSQL interval will + not suffice for those purposes. + In more frequent cases though, the resolution of the interval suffices. + will always suffice to handle the resolution of any interval value, and upon + writing to the database, will be rounded to the resolution used. + + The number of ticks in the instance. + + + + + Gets the number of whole microseconds held in the instance. + An in the range [-999999, 999999]. + + + + + Gets the number of whole milliseconds held in the instance. + An in the range [-999, 999]. + + + + + Gets the number of whole seconds held in the instance. + An in the range [-59, 59]. + + + + + Gets the number of whole minutes held in the instance. + An in the range [-59, 59]. + + + + + Gets the number of whole hours held in the instance. + Note that this can be less than -23 or greater than 23 unless + has been used to produce this instance. + + + + + Gets the number of days held in the instance. + Note that this does not pay attention to a time component with -24 or less hours or + 24 or more hours, unless has been called to produce this instance. + + + + + Gets the number of months held in the instance. + Note that this does not pay attention to a day component with -30 or less days or + 30 or more days, unless has been called to produce this instance. + + + + + Returns a representing the time component of the instance. + Note that this may have a value beyond the range ±23:59:59.9999999 unless + has been called to produce this instance. + + + + + The total number of ticks (100ns units) in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + The total number of microseconds in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + The total number of milliseconds in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + The total number of seconds in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + The total number of minutes in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + The total number of hours in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + The total number of days in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + The total number of months in the instance, assuming 24 hours in each day and + 30 days in a month. + + + + + Normalise this time; if it is 24:00:00, convert it to 00:00:00 + + This time, normalised + + + + The total number of ticks(100ns units) contained. This is the resolution of the + type. + The resolution of the PostgreSQL + interval type is by default 1µs = 1,000 ns. It may be smaller as follows: + + + time(0) + resolution of 1s (1 second) + + + time(1) + resolution of 100ms = 0.1s (100 milliseconds) + + + time(2) + resolution of 10ms = 0.01s (10 milliseconds) + + + time(3) + resolution of 1ms = 0.001s (1 millisecond) + + + time(4) + resolution of 100µs = 0.0001s (100 microseconds) + + + time(5) + resolution of 10µs = 0.00001s (10 microseconds) + + + time(6) or interval + resolution of 1µs = 0.000001s (1 microsecond) + + + As such, if the 100-nanosecond resolution is significant to an application, a PostgreSQL time will + not suffice for those purposes. + In more frequent cases though, the resolution of time suffices. + will always suffice to handle the resolution of any time value, and upon + writing to the database, will be rounded to the resolution used. + + The number of ticks in the instance. + + + + + Gets the number of whole microseconds held in the instance. + An integer in the range [0, 999999]. + + + + + Gets the number of whole milliseconds held in the instance. + An integer in the range [0, 999]. + + + + + Gets the number of whole seconds held in the instance. + An interger in the range [0, 59]. + + + + + Gets the number of whole minutes held in the instance. + An integer in the range [0, 59]. + + + + + Gets the number of whole hours held in the instance. + Note that the time 24:00:00 can be stored for roundtrip compatibility. Any calculations on such a + value will normalised it to 00:00:00. + + + + + Normalise this time; if it is 24:00:00, convert it to 00:00:00 + + This time, normalised + + + + Compares this with another . As per postgres' rules, + first the times are compared as if they were both in the same timezone. If they are equal then + then timezones are compared (+01:00 being "smaller" than -01:00). + + the to compare with. + An integer which is 0 if they are equal, < 0 if this is the smaller and > 0 if this is the larger. + + + + Gets the number of whole microseconds held in the instance. + An integer in the range [0, 999999]. + + + + + Gets the number of whole milliseconds held in the instance. + An integer in the range [0, 999]. + + + + + Gets the number of whole seconds held in the instance. + An interger in the range [0, 59]. + + + + + Gets the number of whole minutes held in the instance. + An integer in the range [0, 59]. + + + + + Gets the number of whole hours held in the instance. + Note that the time 24:00:00 can be stored for roundtrip compatibility. Any calculations on such a + value will normalised it to 00:00:00. + + + + + Summary description for LargeObjectManager. + + + + + Options that control certain aspects of native to backend conversions that depend + on backend version and status. + + + + + Clone the current object. + + A new NativeToBackendTypeConverterOptions object. + + + + Clone the current object with a different OID/Name mapping. + + OID/Name mapping object to use in the new instance. + A new NativeToBackendTypeConverterOptions object. + + + + Provide event handlers to convert all native supported basic data types from their backend + text representation to a .NET object. + + + + + Convert UTF8 encoded text a string. + + + + + Byte array from bytea encoded as ASCII text, escaped or hex format. + + + + + Byte array from bytea encoded as binary. + + + + + Convert a postgresql boolean to a System.Boolean. + + + + + Convert a postgresql boolean to a System.Boolean. + + + + + Convert a postgresql bit to a System.Boolean. + + + + + Convert a postgresql datetime to a System.DateTime. + + + + + Convert a postgresql date to a System.DateTime. + + + + + Convert a postgresql time to a System.DateTime. + + + + + Convert a postgresql money to a System.Decimal. + + + + + Convert a postgresql float4 or float8 to a System.Float or System.Double respectively. + + + + + Provide event handlers to convert extended native supported data types from their backend + text representation to a .NET object. + + + + + Convert a postgresql point to a System.NpgsqlPoint. + + + + + Convert a postgresql point to a System.RectangleF. + + + + + LDeg. + + + + + Path. + + + + + Polygon. + + + + + Circle. + + + + + Inet. + + + + + MAC Address. + + + + + interval + + + + + Provide event handlers to convert the basic native supported data types from + native form to backend representation. + + + + + Convert a string to UTF8 encoded text, escaped and quoted as required. + + + + + Convert a string to UTF8 encoded text. + + + + + Binary data, escaped and quoted as required. + + + + + Binary data with possible older style octal escapes, quoted. + + + + + Binary data in the new hex format (>= 9.0), quoted. + + + + + Binary data, raw. + + + + + Convert to a postgresql boolean text format. + + + + + Convert to a postgresql boolean binary format. + + + + + Convert to a postgresql binary int2. + + + + + Convert to a postgresql binary int4. + + + + + Convert to a postgresql binary int8. + + + + + Convert to a postgresql bit. + + + + + Convert to a postgresql timestamp. + + + + + Convert to a postgresql date. + + + + + Convert to a postgresql time. + + + + + Convert to a postgres money. + + + + + Convert to a postgres double with maximum precision. + + + + + Convert a System.Float to a postgres float4. + + + + + Convert a System.Double to a postgres float8. + + + + + Provide event handlers to convert extended native supported data types from + native form to backend representation. + + + + + Point. + + + + + Box. + + + + + LSeg. + + + + + Open path. + + + + + Polygon. + + + + + Convert to a postgres MAC Address. + + + + + Circle. + + + + + Convert to a postgres inet. + + + + + Convert to a postgres interval + + + + + Delegate called to convert the given backend text data to its native representation. + + + + + Delegate called to convert the given backend binary data to its native representation. + + + + + Represents a backend data type. + This class can be called upon to convert a backend field representation to a native object. + + + + + Construct a new NpgsqlTypeInfo with the given attributes and conversion handlers. + + Type OID provided by the backend server. + Type name provided by the backend server. + NpgsqlDbType + DbType + System type to convert fields of this type to. + Data conversion handler for text encoding. + Data conversion handler for binary data. + + + + Perform a data conversion from a backend representation to + a native object. + + Data sent from the backend. + fieldValueSize + Type modifier field sent from the backend. + + + + Perform a data conversion from a backend representation to + a native object. + + Data sent from the backend. + TypeSize + Type modifier field sent from the backend. + + + + Type OID provided by the backend server. + + + + + Type name provided by the backend server. + + + + + NpgsqlDbType. + + + + + NpgsqlDbType. + + + + + Provider type to convert fields of this type to. + + + + + System type to convert fields of this type to. + + + + + Reports whether a backend binary to native decoder is available for this type. + + + + + Delegate called to convert the given native data to its backand representation. + + + + + Represents a backend data type. + This class can be called upon to convert a native object to its backend field representation, + + + + + Returns an NpgsqlNativeTypeInfo for an array where the elements are of the type + described by the NpgsqlNativeTypeInfo supplied. + + + + + Construct a new NpgsqlTypeInfo with the given attributes and conversion handlers. + + Type name provided by the backend server. + DbType + Quote + NpgsqlDbType + Data conversion handler for text backend encoding. + Data conversion handler for binary backend encoding (for extended queries). + + + + Perform a data conversion from a native object to + a backend representation. + DBNull and null values are handled differently depending if a plain query is used + When + + Native .NET object to be converted. + Specifies that the value should be formatted for the extended query syntax. + Options to guide serialization. If null, a default options set is used. + Specifies that the value should be formatted as an extended query array element. + + + + Type name provided by the backend server. + + + + + NpgsqlDbType. + + + + + DbType. + + + + + Apply quoting. + + + + + Use parameter size information. + + + + + Reports whether a native to backend binary encoder is available for this type. + + + + + Provide mapping between type OID, type name, and a NpgsqlBackendTypeInfo object that represents it. + + + + + Construct an empty mapping. + + + + + Copy constuctor. + + + + + Add the given NpgsqlBackendTypeInfo to this mapping. + + + + + Add a new NpgsqlBackendTypeInfo with the given attributes and conversion handlers to this mapping. + + Type OID provided by the backend server. + Type name provided by the backend server. + NpgsqlDbType + DbType + System type to convert fields of this type to. + Data conversion handler for text encoding. + Data conversion handler for binary data. + + + + Make a shallow copy of this type mapping. + + + + + Determine if a NpgsqlBackendTypeInfo with the given backend type OID exists in this mapping. + + + + + Determine if a NpgsqlBackendTypeInfo with the given backend type name exists in this mapping. + + + + + Get the number of type infos held. + + + + + Retrieve the NpgsqlBackendTypeInfo with the given backend type OID, or null if none found. + + + + + Retrieve the NpgsqlBackendTypeInfo with the given backend type name, or null if none found. + + + + + Provide mapping between type Type, NpgsqlDbType and a NpgsqlNativeTypeInfo object that represents it. + + + + + Add the given NpgsqlNativeTypeInfo to this mapping. + + + + + Add a new NpgsqlNativeTypeInfo with the given attributes and conversion handlers to this mapping. + + Type name provided by the backend server. + NpgsqlDbType + DbType + Quote + Data conversion handler for text backend encoding. + Data conversion handler for binary backend encoding (for extended query). + + + + Retrieve the NpgsqlNativeTypeInfo with the given NpgsqlDbType. + + + + + Retrieve the NpgsqlNativeTypeInfo with the given DbType. + + + + + Retrieve the NpgsqlNativeTypeInfo with the given Type. + + + + + Determine if a NpgsqlNativeTypeInfo with the given backend type name exists in this mapping. + + + + + Determine if a NpgsqlNativeTypeInfo with the given NpgsqlDbType exists in this mapping. + + + + + Determine if a NpgsqlNativeTypeInfo with the given Type name exists in this mapping. + + + + + Get the number of type infos held. + + + + + Represents a PostgreSQL Point type + + + + + Represents a PostgreSQL Line Segment type. + + + + + Represents a PostgreSQL Path type. + + + + + Represents a PostgreSQL Polygon type. + + + + + Represents a PostgreSQL Circle type. + + + + + Represents a PostgreSQL inet type. + + + + + Represents a PostgreSQL MacAddress type. + + + + + + + The macAddr parameter must contain a string that can only consist of numbers + and upper-case letters as hexadecimal digits. (See PhysicalAddress.Parse method on MSDN) + + + + This class contains helper methods for type conversion between + the .Net type system and postgresql. + + + + + A cache of basic datatype mappings keyed by server version. This way we don't + have to load the basic type mappings for every connection. + + + + + Find a NpgsqlNativeTypeInfo in the default types map that can handle objects + of the given NpgsqlDbType. + + + + + Find a NpgsqlNativeTypeInfo in the default types map that can handle objects + of the given NpgsqlDbType. + + + + + Find a NpgsqlNativeTypeInfo in the default types map that can handle objects + of the given DbType. + + + + + Find a NpgsqlNativeTypeInfo in the default types map that can handle objects + of the given System.Type. + + + + + This method is responsible to convert the byte[] received from the backend + to the corresponding NpgsqlType. + The given TypeInfo is called upon to do the conversion. + If no TypeInfo object is provided, no conversion is performed. + + + + + This method is responsible to convert the string received from the backend + to the corresponding NpgsqlType. + The given TypeInfo is called upon to do the conversion. + If no TypeInfo object is provided, no conversion is performed. + + + + + Create the one and only native to backend type map. + This map is used when formatting native data + types to backend representations. + + + + + This method creates (or retrieves from cache) a mapping between type and OID + of all natively supported postgresql data types. + This is needed as from one version to another, this mapping can be changed and + so we avoid hardcoding them. + + NpgsqlTypeMapping containing all known data types. The mapping must be + cloned before it is modified because it is cached; changes made by one connection may + effect another connection. + + + + + Attempt to map types by issuing a query against pg_type. + This function takes a list of NpgsqlTypeInfo and attempts to resolve the OID field + of each by querying pg_type. If the mapping is found, the type info object is + updated (OID) and added to the provided NpgsqlTypeMapping object. + + NpgsqlConnector to send query through. + Mapping object to add types too. + List of types that need to have OID's mapped. + + + + Set Cache Size. The default value is 20. + + + + + Lookup cached entity. null will returned if not match. + For both get{} and set{} apply LRU rule. + + key + + + + + The globally available text encoding used for frontend/backend communication. + + + + This class represents the base class for the state pattern design pattern + implementation. + + + This class represents the base class for the state pattern design pattern + implementation. + + + This class represents the base class for the state pattern design pattern + implementation. + + + + + + This method is used by the states to change the state of the context. + + + + + Call ProcessBackendResponsesEnum(), and scan and discard all results. + + + + + This method is responsible to handle all protocol messages sent from the backend. + It holds all the logic to do it. + To exchange data, it uses a Mediator object from which it reads/writes information + to handle backend requests. + + + + + + Checks for context socket availability. + Socket.Poll supports integer as microseconds parameter. + This limits the usable command timeout value + to 2,147 seconds: (2,147 x 1,000,000 less than max_int). + In order to bypass this limit, the availability of + the socket is checked in 2,147 seconds cycles + + true, if for context socket availability was checked, false otherwise. + Context. + Select mode. + + + + Called from constructor of derived class. + + + + + Finalizer for HashAlgorithm + + + + + Computes the entire hash of all the bytes in the byte array. + + + + + When overridden in a derived class, drives the hashing function. + + + + + + + + When overridden in a derived class, this pads and hashes whatever data might be left in the buffers and then returns the hash created. + + + + + When overridden in a derived class, initializes the object to prepare for hashing. + + + + + Used for stream chaining. Computes hash as data passes through it. + + The buffer from which to grab the data to be copied. + The offset into the input buffer to start reading at. + The number of bytes to be copied. + The buffer to write the copied data to. + At what point in the outputBuffer to write the data at. + + + + Used for stream chaining. Computes hash as data passes through it. Finishes off the hash. + + The buffer from which to grab the data to be copied. + The offset into the input buffer to start reading at. + The number of bytes to be copied. + + + + Get whether or not the hash can transform multiple blocks at a time. + Note: MUST be overriden if descendant can transform multiple block + on a single call! + + + + + Gets the previously computed hash. + + + + + Returns the size in bits of the hash. + + + + + Must be overriden if not 1 + + + + + Must be overriden if not 1 + + + + + Common base class for all derived MD5 implementations. + + + + + Called from constructor of derived class. + + + + + Creates the default derived class. + + C# implementation of the MD5 cryptographic hash function. @@ -3577,6 +2155,1570 @@ Position in buffer in bytes to get data from. How much data in bytes in the buffer to use. + + + Implements for version 3 of the protocol. + + + + + Reads a row, field by field, allowing a DataRow to be built appropriately. + + + + + Marker interface which identifies a class which may take possession of a stream for the duration of + it's lifetime (possibly temporarily giving that possession to another class for part of that time. + + It inherits from IDisposable, since any such class must make sure it leaves the stream in a valid state. + + The most important such class is that compiler-generated from ProcessBackendResponsesEnum. Of course + we can't make that inherit from this interface, alas. + + + + + Marker interface which identifies a class which represents part of + a response from the server. + + + + + Reads part of a field, as needed (for + and + + + + + Adds further functionality to stream that is dependant upon the type of data read. + + + + + Completes the implementation of Streamer for char data. + + + + + Completes the implementation of Streamer for byte data. + + + + + Implements for version 2 of the protocol. + + + + + Encapsulates the null mapping bytes sent at the start of a version 2 + datarow message, and the process of identifying the nullity of the data + at a particular index + + + + + This class represents a BackEndKeyData message received + from PostgreSQL + + + + + This class represents the Bind message sent to PostgreSQL + server. + + + + + + For classes representing messages sent from the client to the server. + + + + + This class represents the CancelRequest message sent to PostgreSQL + server. + + + + + + Represents a SQL statement or function (stored procedure) to execute + against a PostgreSQL database. This class cannot be inherited. + + + Represents a SQL statement or function (stored procedure) to execute + against a PostgreSQL database. This class cannot be inherited. + + + Represents a SQL statement or function (stored procedure) to execute + against a PostgreSQL database. This class cannot be inherited. + + + + + Initializes a new instance of the NpgsqlCommand class. + + + + + Initializes a new instance of the NpgsqlCommand class with the text of the query. + + The text of the query. + + + + Initializes a new instance of the NpgsqlCommand class with the text of the query and a NpgsqlConnection. + + The text of the query. + A NpgsqlConnection that represents the connection to a PostgreSQL server. + + + + Initializes a new instance of the NpgsqlCommand class with the text of the query, a NpgsqlConnection, and the NpgsqlTransaction. + + The text of the query. + A NpgsqlConnection that represents the connection to a PostgreSQL server. + The NpgsqlTransaction in which the NpgsqlCommand executes. + + + + Used to execute internal commands. + + + + + Attempts to cancel the execution of a NpgsqlCommand. + + This Method isn't implemented yet. + + + + Create a new command based on this one. + + A new NpgsqlCommand object. + + + + Create a new command based on this one. + + A new NpgsqlCommand object. + + + + Creates a new instance of an DbParameter object. + + An DbParameter object. + + + + Creates a new instance of a NpgsqlParameter object. + + A NpgsqlParameter object. + + + + Slightly optimised version of ExecuteNonQuery() for internal use in cases where the number + of affected rows is of no interest. + This function must not be called with a query that returns result rows, after calling Prepare(), or. + with a query that requires parameter substitution of any kind. + + + + + Executes a SQL statement against the connection and returns the number of rows affected. + + The number of rows affected if known; -1 otherwise. + + + + Sends the CommandText to + the Connection and builds a + NpgsqlDataReader + using one of the CommandBehavior values. + + One of the CommandBehavior values. + A NpgsqlDataReader object. + + + + Sends the CommandText to + the Connection and builds a + NpgsqlDataReader. + + A NpgsqlDataReader object. + + + + Sends the CommandText to + the Connection and builds a + NpgsqlDataReader + using one of the CommandBehavior values. + + One of the CommandBehavior values. + A NpgsqlDataReader object. + Currently the CommandBehavior parameter is ignored. + + + + This method binds the parameters from parameters collection to the bind + message. + + + + + Executes the query, and returns the first column of the first row + in the result set returned by the query. Extra columns or rows are ignored. + + The first column of the first row in the result set, + or a null reference if the result set is empty. + + + + Creates a prepared version of the command on a PostgreSQL server. + + + + + This method checks the connection state to see if the connection + is set or it is open. If one of this conditions is not met, throws + an InvalidOperationException + + + + + This method substitutes the Parameters, if exist, in the command + to their actual values. + The parameter name format is :ParameterName. + + A version of CommandText with the Parameters inserted. + + + + Process this.commandText, trimming each distinct command and substituting paramater + tokens. + + + + UTF8 encoded command ready to be sent to the backend. + + + + Find the beginning and end of each distinct SQL command and produce + a list of descriptors, one for each command. Commands described are trimmed of + leading and trailing white space and their terminating semi-colons. + + Raw command text. + List of chunk descriptors. + + + + Append a region of a source command text to an output command, performing parameter token + substitutions. + + Stream to which to append output. + Command text. + Starting index within src. + Length of region to be processed. + + + + + + Gets or sets the SQL statement or function (stored procedure) to execute at the data source. + + The Transact-SQL statement or stored procedure to execute. The default is an empty string. + + + + Gets or sets the wait time before terminating the attempt + to execute a command and generating an error. + + The time (in seconds) to wait for the command to execute. + The default is 20 seconds. + + + + Gets or sets a value indicating how the + CommandText property is to be interpreted. + + One of the CommandType values. The default is CommandType.Text. + + + + Gets or sets the NpgsqlConnection + used by this instance of the NpgsqlCommand. + + The connection to a data source. The default value is a null reference. + + + + Gets the NpgsqlParameterCollection. + + The parameters of the SQL statement or function (stored procedure). The default is an empty collection. + + + + Gets or sets the NpgsqlTransaction + within which the NpgsqlCommand executes. + + The NpgsqlTransaction. + The default value is a null reference. + + + + Gets or sets how command results are applied to the DataRow + when used by the Update + method of the DbDataAdapter. + + One of the UpdateRowSource values. + + + + Returns oid of inserted row. This is only updated when using executenonQuery and when command inserts just a single row. If table is created without oids, this will always be 0. + + + + + This class is responsible to create database commands for automatic insert, update and delete operations. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The adapter. + + + + + This method is reponsible to derive the command parameter list with values obtained from function definition. + It clears the Parameters collection of command. Also, if there is any parameter type which is not supported by Npgsql, an InvalidOperationException will be thrown. + Parameters name will be parameter1, parameter2, ... + + NpgsqlCommand whose function parameters will be obtained. + + + + Gets the automatically generated object required + to perform insertions at the data source. + + + The automatically generated object required to perform insertions. + + + + + Gets the automatically generated object required to perform insertions + at the data source, optionally using columns for parameter names. + + + If true, generate parameter names matching column names, if possible. + If false, generate @p1, @p2, and so on. + + + The automatically generated object required to perform insertions. + + + + + Gets the automatically generated System.Data.Common.DbCommand object required + to perform updates at the data source. + + + The automatically generated System.Data.Common.DbCommand object required to perform updates. + + + + + Gets the automatically generated object required to perform updates + at the data source, optionally using columns for parameter names. + + + If true, generate parameter names matching column names, if possible. + If false, generate @p1, @p2, and so on. + + + The automatically generated object required to perform updates. + + + + + Gets the automatically generated System.Data.Common.DbCommand object required + to perform deletions at the data source. + + + The automatically generated System.Data.Common.DbCommand object required to perform deletions. + + + + + Gets the automatically generated object required to perform deletions + at the data source, optionally using columns for parameter names. + + + If true, generate parameter names matching column names, if possible. + If false, generate @p1, @p2, and so on. + + + The automatically generated object required to perform deletions. + + + + + Applies the parameter information. + + The parameter. + The row. + Type of the statement. + if set to true [where clause]. + + + + Returns the name of the specified parameter in the format of @p#. + + The number to be included as part of the parameter's name.. + + The name of the parameter with the specified number appended as part of the parameter name. + + + + + Returns the full parameter name, given the partial parameter name. + + The partial name of the parameter. + + The full parameter name corresponding to the partial parameter name requested. + + + + + Returns the placeholder for the parameter in the associated SQL statement. + + The number to be included as part of the parameter's name. + + The name of the parameter with the specified number appended. + + + + + Registers the to handle the event for a . + + The to be used for the update. + + + + Adds an event handler for the event. + + The sender + A instance containing information about the event. + + + + Given an unquoted identifier in the correct catalog case, returns the correct quoted form of that identifier, including properly escaping any embedded quotes in the identifier. + + The original unquoted identifier. + + The quoted version of the identifier. Embedded quotes within the identifier are properly escaped. + + + + + Unquoted identifier parameter cannot be null + + + + Given a quoted identifier, returns the correct unquoted form of that identifier, including properly un-escaping any embedded quotes in the identifier. + + The identifier that will have its embedded quotes removed. + + The unquoted identifier, with embedded quotes properly un-escaped. + + + + + Quoted identifier parameter cannot be null + + + + Gets or sets the beginning character or characters to use when specifying database objects (for example, tables or columns) whose names contain characters such as spaces or reserved tokens. + + + The beginning character or characters to use. The default is an empty string. + + + + + + + + Gets or sets the ending character or characters to use when specifying database objects (for example, tables or columns) whose names contain characters such as spaces or reserved tokens. + + + The ending character or characters to use. The default is an empty string. + + + + + + + + Represents the method that handles the Notice events. + + The source of the event. + A NpgsqlNoticeEventArgs that contains the event data. + + + + Represents the method that handles the Notification events. + + The source of the event. + A NpgsqlNotificationEventArgs that contains the event data. + + + + This class represents a connection to a + PostgreSQL server. + + + + + Initializes a new instance of the + NpgsqlConnection class. + + + + + Initializes a new instance of the + NpgsqlConnection class + and sets the ConnectionString. + + The connection used to open the PostgreSQL database. + + + + Initializes a new instance of the + NpgsqlConnection class + and sets the ConnectionString. + + The connection used to open the PostgreSQL database. + + + + Begins a database transaction with the specified isolation level. + + The isolation level under which the transaction should run. + An DbTransaction + object representing the new transaction. + + Currently the IsolationLevel ReadCommitted and Serializable are supported by the PostgreSQL backend. + There's no support for nested transactions. + + + + + Begins a database transaction. + + A NpgsqlTransaction + object representing the new transaction. + + Currently there's no support for nested transactions. + + + + + Begins a database transaction with the specified isolation level. + + The isolation level under which the transaction should run. + A NpgsqlTransaction + object representing the new transaction. + + Currently the IsolationLevel ReadCommitted and Serializable are supported by the PostgreSQL backend. + There's no support for nested transactions. + + + + + Opens a database connection with the property settings specified by the + ConnectionString. + + + + + This method changes the current database by disconnecting from the actual + database and connecting to the specified. + + The name of the database to use in place of the current database. + + + + Releases the connection to the database. If the connection is pooled, it will be + made available for re-use. If it is non-pooled, the actual connection will be shutdown. + + + + + When a connection is closed within an enclosing TransactionScope and the transaction + hasn't been promoted, we defer the actual closing until the scope ends. + + + + + Creates and returns a DbCommand + object associated with the IDbConnection. + + A DbCommand object. + + + + Creates and returns a NpgsqlCommand + object associated with the NpgsqlConnection. + + A NpgsqlCommand object. + + + + Releases all resources used by the + NpgsqlConnection. + + true when called from Dispose(); + false when being called from the finalizer. + + + + Create a new connection based on this one. + + A new NpgsqlConnection object. + + + + Create a new connection based on this one. + + A new NpgsqlConnection object. + + + + Returns a copy of the NpgsqlConnectionStringBuilder that contains the parsed connection string values. + + + + + Default SSL CertificateSelectionCallback implementation. + + + + + Default SSL CertificateValidationCallback implementation. + + + + + Default SSL PrivateKeySelectionCallback implementation. + + + + + Default SSL ProvideClientCertificatesCallback implementation. + + + + + Default SSL ValidateRemoteCertificateCallback implementation. + + + + + Write each key/value pair in the connection string to the log. + + + + + Sets the `settings` ConnectionStringBuilder based on the given `connectionString` + + The connection string to load the builder from + + + + Sets the `settings` ConnectionStringBuilder based on the given `connectionString` + + The connection string to load the builder from + + + + Refresh the cached _connectionString whenever the builder settings change + + + + + Returns the supported collections + + + + + Returns the schema collection specified by the collection name. + + The collection name. + The collection specified. + + + + Returns the schema collection specified by the collection name filtered by the restrictions. + + The collection name. + + The restriction values to filter the results. A description of the restrictions is contained + in the Restrictions collection. + + The collection specified. + + + + Occurs on NoticeResponses from the PostgreSQL backend. + + + + + Occurs on NotificationResponses from the PostgreSQL backend. + + + + + Called to provide client certificates for SSL handshake. + + + + + Mono.Security.Protocol.Tls.CertificateSelectionCallback delegate. + + + + + Mono.Security.Protocol.Tls.CertificateValidationCallback delegate. + + + + + Mono.Security.Protocol.Tls.PrivateKeySelectionCallback delegate. + + + + + Called to validate server's certificate during SSL handshake + + + + + Gets or sets the string used to connect to a PostgreSQL database. + Valid values are: +
    +
  • + Server: Address/Name of Postgresql Server; +
  • +
  • + Port: Port to connect to; +
  • +
  • + Protocol: Protocol version to use, instead of automatic; Integer 2 or 3; +
  • +
  • + Database: Database name. Defaults to user name if not specified; +
  • +
  • + User Id: User name; +
  • +
  • + Password: Password for clear text authentication; +
  • +
  • + SSL: True or False. Controls whether to attempt a secure connection. Default = False; +
  • +
  • + Pooling: True or False. Controls whether connection pooling is used. Default = True; +
  • +
  • + MinPoolSize: Min size of connection pool; +
  • +
  • + MaxPoolSize: Max size of connection pool; +
  • +
  • + Timeout: Time to wait for connection open in seconds. Default is 15. +
  • +
  • + CommandTimeout: Time to wait for command to finish execution before throw an exception. In seconds. Default is 20. +
  • +
  • + Sslmode: Mode for ssl connection control. Can be Prefer, Require, Allow or Disable. Default is Disable. Check user manual for explanation of values. +
  • +
  • + ConnectionLifeTime: Time to wait before closing unused connections in the pool in seconds. Default is 15. +
  • +
  • + SyncNotification: Specifies if Npgsql should use synchronous notifications. +
  • +
  • + SearchPath: Changes search path to specified and public schemas. +
  • +
+
+ The connection string that includes the server name, + the database name, and other parameters needed to establish + the initial connection. The default value is an empty string. + +
+ + + Backend server host name. + + + + + Backend server port. + + + + + If true, the connection will attempt to use SSL. + + + + + Gets the time to wait while trying to establish a connection + before terminating the attempt and generating an error. + + The time (in seconds) to wait for a connection to open. The default value is 15 seconds. + + + + Gets the time to wait while trying to execute a command + before terminating the attempt and generating an error. + + The time (in seconds) to wait for a command to complete. The default value is 20 seconds. + + + + Gets the time to wait before closing unused connections in the pool if the count + of all connections exeeds MinPoolSize. + + + If connection pool contains unused connections for ConnectionLifeTime seconds, + the half of them will be closed. If there will be unused connections in a second + later then again the half of them will be closed and so on. + This strategy provide smooth change of connection count in the pool. + + The time (in seconds) to wait. The default value is 15 seconds. + + + + Gets the name of the current database or the database to be used after a connection is opened. + + The name of the current database or the name of the database to be + used after a connection is opened. The default value is the empty string. + + + + Whether datareaders are loaded in their entirety (for compatibility with earlier code). + + + + + Gets the database server name. + + + + + Gets flag indicating if we are using Synchronous notification or not. + The default value is false. + + + + + Gets the current state of the connection. + + A bitwise combination of the ConnectionState values. The default is Closed. + + + + Gets whether the current state of the connection is Open or Closed + + ConnectionState.Open or ConnectionState.Closed + + + + Version of the PostgreSQL backend. + This can only be called when there is an active connection. + + + + + Protocol version in use. + This can only be called when there is an active connection. + + + + + Process id of backend server. + This can only be called when there is an active connection. + + + + + Report whether the backend is expecting standard conformant strings. + In version 8.1, Postgres began reporting this value (false), but did not actually support standard conformant strings. + In version 8.2, Postgres began supporting standard conformant strings, but defaulted this flag to false. + As of version 9.1, this flag defaults to true. + + + + + Report whether the backend understands the string literal E prefix (>= 8.1). + + + + + Report whether the backend understands the hex byte format (>= 9.0). + + + + + The connector object connected to the backend. + + + + + Gets the NpgsqlConnectionStringBuilder containing the parsed connection string values. + + + + + User name. + + + + + Password. + + + + + Determine if connection pooling will be used for this connection. + + + + + Return an exact copy of this NpgsqlConnectionString. + + + + + No integrated security if we're on mono and .NET 4.5 because of ClaimsIdentity, + see https://github.com/npgsql/Npgsql/issues/133 + + + + + This function will set value for known key, both private member and base[key]. + + + + + value, coerced as needed to the stored type. + + + + The function will modify private member only, not base[key]. + + + + value, coerced as needed to the stored type. + + + + The function will access private member only, not base[key]. + + + value. + + + + Clear the member and assign them to the default value. + + + + + Gets or sets the backend server host name. + + + + + Gets or sets the backend server port. + + + + + Gets or sets the specified backend communication protocol version. + + + + + Gets or sets the name of the database to be used after a connection is opened. + + The name of the database to be + used after a connection is opened. + + + + Gets or sets the login user name. + + + + + This is a pretty horrible hack to fix https://github.com/npgsql/Npgsql/issues/133 + In a nutshell, starting with .NET 4.5 WindowsIdentity inherits from ClaimsIdentity + which doesn't exist in mono, and calling UserName getter above bombs. + The workaround is that the function that actually deals with WindowsIdentity never + gets called on mono, so never gets JITted and the problem goes away. + + + + + Gets or sets the login password as a UTF8 encoded byte array. + + + + + Sets the login password as a string. + + + + + Gets or sets a value indicating whether to attempt to use SSL. + + + + + Gets or sets a value indicating whether to attempt to use SSL. + + + + + Gets the backend encoding. Always returns "UTF8". + + + + + Gets or sets the time to wait while trying to establish a connection + before terminating the attempt and generating an error. + + The time (in seconds) to wait for a connection to open. The default value is 15 seconds. + + + + Gets or sets the schema search path. + + + + + Gets or sets a value indicating whether connection pooling should be used. + + + + + Gets or sets the time to wait before closing unused connections in the pool if the count + of all connections exeeds MinPoolSize. + + + If connection pool contains unused connections for ConnectionLifeTime seconds, + the half of them will be closed. If there will be unused connections in a second + later then again the half of them will be closed and so on. + This strategy provide smooth change of connection count in the pool. + + The time (in seconds) to wait. The default value is 15 seconds. + + + + Gets or sets the minimum connection pool size. + + + + + Gets or sets the maximum connection pool size. + + + + + Gets or sets a value indicating whether to listen for notifications and report them between command activity. + + + + + Gets the time to wait while trying to execute a command + before terminating the attempt and generating an error. + + The time (in seconds) to wait for a command to complete. The default value is 20 seconds. + + + + Gets or sets a value indicating whether datareaders are loaded in their entirety (for compatibility with earlier code). + + + + + Compatibilty version. When possible, behaviour caused by breaking changes will be preserved + if this version is less than that where the breaking change was introduced. + + + + + Gets or sets the ootional application name parameter to be sent to the backend during connection initiation. + + + + + Gets or sets a value indicating whether to silently Prepare() all commands before execution. + + + + + Case insensative accessor for indivual connection string values. + + + + + Set both ImplicitDefault and ExplicitDefault to the 's default value. + + + + + + + + Set ImplicitDefault to the default value of 's type, + and ExplicitDefault to . + + + + + + + + Represents the method that allows the application to provide a certificate collection to be used for SSL clien authentication + + A X509CertificateCollection to be filled with one or more client certificates. + + + + Represents the method that is called to validate the certificate provided by the server during an SSL handshake + + The server's certificate + The certificate chain containing the certificate's CA and any intermediate authorities + Any errors that were detected + + + + !!! Helper class, for compilation only. + Connector implements the logic for the Connection Objects to + access the physical connection to the database, and isolate + the application developer from connection pooling internals. + + + + + Constructor. + + Connection string. + Pooled + Controls whether the connector can be shared. + + + + This method checks if the connector is still ok. + We try to send a simple query text, select 1 as ConnectionTest; + + + + + This method is responsible for releasing all resources associated with this Connector. + + + + + This method is responsible to release all portals used by this Connector. + + + + + Default SSL CertificateSelectionCallback implementation. + + + + + Default SSL CertificateValidationCallback implementation. + + + + + Default SSL PrivateKeySelectionCallback implementation. + + + + + Default SSL ProvideClientCertificatesCallback implementation. + + + + + Default SSL ValidateRemoteCertificateCallback implementation. + + + + + This method is required to set all the version dependent features flags. + SupportsPrepare means the server can use prepared query plans (7.3+) + + + + + Opens the physical connection to the server. + + Usually called by the RequestConnector + Method of the connection pool manager. + + + + Closes the physical connection to the server. + + + + + Returns next portal index. + + + + + Returns next plan index. + + + + + Occurs on NoticeResponses from the PostgreSQL backend. + + + + + Occurs on NotificationResponses from the PostgreSQL backend. + + + + + Called to provide client certificates for SSL handshake. + + + + + Mono.Security.Protocol.Tls.CertificateSelectionCallback delegate. + + + + + Mono.Security.Protocol.Tls.CertificateValidationCallback delegate. + + + + + Mono.Security.Protocol.Tls.PrivateKeySelectionCallback delegate. + + + + + Called to validate server's certificate during SSL handshake + + + + + Gets the current state of the connection. + + + + + Return Connection String. + + + + + Version of backend server this connector is connected to. + + + + + Backend protocol version in use by this connector. + + + + + The physical connection socket to the backend. + + + + + The physical connection stream to the backend. + + + + + The top level stream to the backend. + + + + + Reports if this connector is fully connected. + + + + + The connection mediator. + + + + + Report if the connection is in a transaction. + + + + + Report whether the current connection can support prepare functionality. + + + + + Options that control certain aspects of native to backend conversions that depend + on backend version and status. + + + + + This class manages all connector objects, pooled AND non-pooled. + + + + Unique static instance of the connector pool + mamager. + + + Map of index to unused pooled connectors, avaliable to the + next RequestConnector() call. + This hashmap will be indexed by connection string. + This key will hold a list of queues of pooled connectors available to be used. + + + Timer for tracking unused connections in pools. + + + + Searches the shared and pooled connector lists for a + matching connector object or creates a new one. + + The NpgsqlConnection that is requesting + the connector. Its ConnectionString will be used to search the + pool for available connectors. + A connector object. + + + + Find a pooled connector. Handle shared/non-shared here. + + + + + Releases a connector, possibly back to the pool for future use. + + + Pooled connectors will be put back into the pool if there is room. + Shared connectors should just have their use count decremented + since they always stay in the shared pool. + + Connection to which the connector is leased. + The connector to release. + + + + Release a pooled connector. Handle shared/non-shared here. + + + + + Find an available pooled connector in the non-shared pool, or create + a new one if none found. + + + + + Put a pooled connector into the pool queue. + + Connection is leased to. + Connector to pool + + + + A queue with an extra Int32 for keeping track of busy connections. + + + + + Connections available to the end user + + + + + Connections currently in use + + + + + Represents information about COPY operation data transfer format as returned by server. + + + + + Only created when a CopyInResponse or CopyOutResponse is received by NpgsqlState.ProcessBackendResponses() + + + + + Returns true if this operation is currently active and field at given location is in binary format. + + + + + Returns true if this operation is currently active and in binary format. + + + + + Returns number of fields if this operation is currently active, otherwise -1 + + + + + Represents a PostgreSQL COPY FROM STDIN operation with a corresponding SQL statement + to execute against a PostgreSQL database + and an associated stream used to read data from (if provided by user) + or for writing it (when generated by driver). + Eg. new NpgsqlCopyIn("COPY mytable FROM STDIN", connection, streamToRead).Start(); + + + + + Creates NpgsqlCommand to run given query upon Start(). Data for the requested COPY IN operation can then be written to CopyData stream followed by a call to End() or Cancel(). + + + + + Given command is run upon Start(). Data for the requested COPY IN operation can then be written to CopyData stream followed by a call to End() or Cancel(). + + + + + Given command is executed upon Start() and all data from fromStream is passed to it as copy data. + + + + + Returns true if this operation is currently active and field at given location is in binary format. + + + + + Command specified upon creation is executed as a non-query. + If CopyStream is set upon creation, it will be flushed to server as copy data, and operation will be finished immediately. + Otherwise the CopyStream member can be used for writing copy data to server and operation finished with a call to End() or Cancel(). + + + + + Called after writing all data to CopyStream to successfully complete this copy operation. + + + + + Withdraws an already started copy operation. The operation will fail with given error message. + Will do nothing if current operation is not active. + + + + + Returns true if the connection is currently reserved for this operation. + + + + + The stream provided by user or generated upon Start(). + User may provide a stream to constructor; it is used to pass to server all data read from it. + Otherwise, call to Start() sets this to a writable NpgsqlCopyInStream that passes all data written to it to server. + In latter case this is only available while the copy operation is active and null otherwise. + + + + + Returns true if this operation is currently active and in binary format. + + + + + Returns number of fields expected on each input row if this operation is currently active, otherwise -1 + + + + + The Command used to execute this copy operation. + + + + + Set before a COPY IN query to define size of internal buffer for reading from given CopyStream. + + + + + Represents an ongoing COPY FROM STDIN operation. + Provides methods to push data to server and end or cancel the operation. + + + + + Called from NpgsqlState.ProcessBackendResponses upon CopyInResponse. + If CopyStream is already set, it is used to read data to push to server, after which the copy is completed. + Otherwise CopyStream is set to a writable NpgsqlCopyInStream that calls SendCopyData each time it is written to. + + + + + Sends given packet to server as a CopyData message. + Does not check for notifications! Use another thread for that. + + + + + Sends CopyDone message to server. Handles responses, ie. may throw an exception. + + + + + Sends CopyFail message to server. Handles responses, ie. should always throw an exception: + in CopyIn state the server responds to CopyFail with an error response; + outside of a CopyIn state the server responds to CopyFail with an error response; + without network connection or whatever, there's going to eventually be a failure, timeout or user intervention. + + + + + Copy format information returned from server. + + Stream for writing data to a table on a PostgreSQL version 7.4 or newer database during an active COPY FROM STDIN operation. @@ -3657,203 +3799,1233 @@ Number of bytes written so far; not settable - + - Represents a SQL statement or function (stored procedure) to execute - against a PostgreSQL database. This class cannot be inherited. + Represents a PostgreSQL COPY TO STDOUT operation with a corresponding SQL statement + to execute against a PostgreSQL database + and an associated stream used to write results to (if provided by user) + or for reading the results (when generated by driver). + Eg. new NpgsqlCopyOut("COPY (SELECT * FROM mytable) TO STDOUT", connection, streamToWrite).Start(); - + - Initializes a new instance of the NpgsqlCommand class. + Creates NpgsqlCommand to run given query upon Start(), after which CopyStream provides data from database as requested in the query. - + - Initializes a new instance of the NpgsqlCommand class with the text of the query. - - The text of the query. - - - - Initializes a new instance of the NpgsqlCommand class with the text of the query and a NpgsqlConnection. - - The text of the query. - A NpgsqlConnection that represents the connection to a PostgreSQL server. - - - - Initializes a new instance of the NpgsqlCommand class with the text of the query, a NpgsqlConnection, and the NpgsqlTransaction. - - The text of the query. - A NpgsqlConnection that represents the connection to a PostgreSQL server. - The NpgsqlTransaction in which the NpgsqlCommand executes. - - - - Used to execute internal commands. + Given command is run upon Start(), after which CopyStream provides data from database as requested in the query. - + - Attempts to cancel the execution of a NpgsqlCommand. - - This Method isn't implemented yet. - - - - Create a new command based on this one. - - A new NpgsqlCommand object. - - - - Create a new command based on this one. - - A new NpgsqlCommand object. - - - - Creates a new instance of an DbParameter object. - - An DbParameter object. - - - - Creates a new instance of a NpgsqlParameter object. - - A NpgsqlParameter object. - - - - Slightly optimised version of ExecuteNonQuery() for internal ues in cases where the number - of affected rows is of no interest. + Given command is executed upon Start() and all requested copy data is written to toStream immediately. - + - Executes a SQL statement against the connection and returns the number of rows affected. + Returns true if this operation is currently active and field at given location is in binary format. - The number of rows affected if known; -1 otherwise. - + - Sends the CommandText to - the Connection and builds a - NpgsqlDataReader - using one of the CommandBehavior values. + Command specified upon creation is executed as a non-query. + If CopyStream is set upon creation, all copy data from server will be written to it, and operation will be finished immediately. + Otherwise the CopyStream member can be used for reading copy data from server until no more data is available. - One of the CommandBehavior values. - A NpgsqlDataReader object. - + - Sends the CommandText to - the Connection and builds a - NpgsqlDataReader. + Flush generated CopyStream at once. Effectively reads and discard all the rest of copy data from server. - A NpgsqlDataReader object. - + - Sends the CommandText to - the Connection and builds a - NpgsqlDataReader - using one of the CommandBehavior values. + Returns true if the connection is currently reserved for this operation. - One of the CommandBehavior values. - A NpgsqlDataReader object. - Currently the CommandBehavior parameter is ignored. - + - This method binds the parameters from parameters collection to the bind - message. + The stream provided by user or generated upon Start() + + + + + The Command used to execute this copy operation. + + + + + Returns true if this operation is currently active and in binary format. + + + + + Returns number of fields if this operation is currently active, otherwise -1 + + + + + Faster alternative to using the generated CopyStream. + + + + + Represents an ongoing COPY TO STDOUT operation. + Provides methods to read data from server or end the operation. + + + + + Called from NpgsqlState.ProcessBackendResponses upon CopyOutResponse. + If CopyStream is already set, it is used to write data received from server, after which the copy ends. + Otherwise CopyStream is set to a readable NpgsqlCopyOutStream that receives data from server. + + + + + Called from NpgsqlOutStream.Read to read copy data from server. + + + + + Copy format information returned from server. + + + + + Stream for reading data from a table or select on a PostgreSQL version 7.4 or newer database during an active COPY TO STDOUT operation. + Passes data exactly as provided by the server. + + + + + Created only by NpgsqlCopyOutState.StartCopy() + + + + + Discards copy data as long as server pushes it. Returns after operation is finished. + Does nothing if this stream is not the active copy operation reader. + + + + + Not writable. + + + + + Not flushable. + + + + + Copies data read from server to given byte buffer. + Since server returns data row by row, length will differ each time, but it is only zero once the operation ends. + Can be mixed with calls to the more efficient NpgsqlCopyOutStream.Read() : byte[] though that would not make much sense. + + + + + Not seekable + + + + + Not supported + + + + + Returns a whole row of data from server without extra work. + If standard Stream.Read(...) has been called before, it's internal buffers remains are returned. + + + + + True while this stream can be used to read copy data from server + + + + + True + + + + + False + + + + + False + + + + + Number of bytes read so far + + + + + Number of bytes read so far; can not be set. + + + + + Writes given objects into a stream for PostgreSQL COPY in default copy format (not CSV or BINARY). + + + + + Represents the method that handles the RowUpdated events. + + The source of the event. + A NpgsqlRowUpdatedEventArgs that contains the event data. + + + + Represents the method that handles the RowUpdating events. + + The source of the event. + A NpgsqlRowUpdatingEventArgs that contains the event data. + + + + This class represents an adapter from many commands: select, update, insert and delete to fill Datasets. + + + + + Provides a means of reading a forward-only stream of rows from a PostgreSQL backend. This class cannot be inherited. + + + + + Return the data type name of the column at index . + + + + + Return the data type of the column at index . + + + + + Return the Npgsql specific data type of the column at requested ordinal. + + column position + Appropriate Npgsql type for column. + + + + Return the column name of the column at index . + + + + + Return the data type OID of the column at index . + + FIXME: Why this method returns String? + + + + Return the column name of the column named . + + + + + Return the data DbType of the column at index . + + + + + Return the data NpgsqlDbType of the column at index . + + + + + Get the value of a column as a . + If the differences between and + in handling of days and months is not important to your application, use + instead. + + Index of the field to find. + value of the field. + + + + Gets the value of a column converted to a Guid. + + + + + Gets the value of a column as Int16. + + + + + Gets the value of a column as Int32. + + + + + Gets the value of a column as Int64. + + + + + Gets the value of a column as Single. + + + + + Gets the value of a column as Double. + + + + + Gets the value of a column as String. + + + + + Gets the value of a column as Decimal. + + + + + Gets the value of a column as TimeSpan. + + + + + Copy values from each column in the current row into . + + Destination for column values. + The number of column values copied. + + + + Copy values from each column in the current row into . + + An array appropriately sized to store values from all columns. + The number of column values copied. + + + + Gets the value of a column as Boolean. + + + + + Gets the value of a column as Byte. Not implemented. + + + + + Gets the value of a column as Char. + + + + + Gets the value of a column as DateTime. + + + + + Returns a System.Data.DataTable that describes the column metadata of the DataReader. + + + + + This methods parses the command text and tries to get the tablename + from it. + + + + + Is raised whenever Close() is called. + + + + + Gets the number of columns in the current row. + + + + + Gets the value of a column in its native format. + + + + + Gets the value of a column in its native format. + + + + + Gets a value indicating the depth of nesting for the current row. Always returns zero. + + + + + Gets a value indicating whether the data reader is closed. + + + + + Contains the column names as the keys + + + + + Contains all unique columns + + + + + This is the primary implementation of NpgsqlDataReader. It is the one used in normal cases (where the + preload-reader option is not set in the connection string to resolve some potential backwards-compatibility + issues), the only implementation used internally, and in cases where CachingDataReader is used, it is still + used to do the actual "leg-work" of turning a response stream from the server into a datareader-style + object - with CachingDataReader then filling it's cache from here. + + + + + Iterate through the objects returned through from the server. + If it's a CompletedResponse the rowsaffected count is updated appropriately, + and we iterate again, otherwise we return it (perhaps updating our cache of pending + rows if appropriate). + + The next we will deal with. + + + + Advances the data reader to the next result, when multiple result sets were returned by the PostgreSQL backend. + + True if the reader was advanced, otherwise false. + + + + Releases the resources used by the NpgsqlCommand. + + + + + Closes the data reader object. + + + + + Advances the data reader to the next result, when multiple result sets were returned by the PostgreSQL backend. + + True if the reader was advanced, otherwise false. + + + + Advances the data reader to the next row. + + True if the reader was advanced, otherwise false. + + + + Return the value of the column at index . + + + + + Gets raw data from a column. + + + + + Gets raw data from a column. + + + + + Report whether the value in a column is DBNull. + + + + + Gets the number of rows changed, inserted, or deleted by execution of the SQL statement. + + + + + Indicates if NpgsqlDatareader has rows to be read. + + + + + Provides an implementation of NpgsqlDataReader in which all data is pre-loaded into memory. + This operates by first creating a ForwardsOnlyDataReader as usual, and then loading all of it's + Rows into memory. There is a general principle that when there is a trade-off between a class design that + is more efficient and/or scalable on the one hand and one that is less efficient but has more functionality + (in this case the internal-only functionality of caching results) that one can build the less efficent class + from the most efficient without significant extra loss in efficiency, but not the other way around. The relationship + between ForwardsOnlyDataReader and CachingDataReader is an example of this). + Since the interface presented to the user is still forwards-only, queues are used to + store this information, so that dequeueing as we go we give the garbage collector the best opportunity + possible to reclaim any memory that is no longer in use. + ForwardsOnlyDataReader being used to actually + obtain the information from the server means that the "leg-work" is still only done (and need only be + maintained) in one place. + This class exists to allow for certain potential backwards-compatibility issues to be resolved + with little effort on the part of affected users. It is considerably less efficient than ForwardsOnlyDataReader + and hence never used internally. + + + + + This is the base class for NpgsqlDescribeStatement and NpgsqlDescribePortal. + - - - Executes the query, and returns the first column of the first row - in the result set returned by the query. Extra columns or rows are ignored. - - The first column of the first row in the result set, - or a null reference if the result set is empty. + + + This class represents the Statement Describe message sent to PostgreSQL + server. + + - + + + This class represents the Portal Describe message sent to PostgreSQL + server. + + + + - Creates a prepared version of the command on a PostgreSQL server. + EventArgs class to send Notice parameters, which are just NpgsqlError's in a lighter context. - + - This method checks the connection state to see if the connection - is set or it is open. If one of this conditions is not met, throws - an InvalidOperationException + Notice information. - + - This method substitutes the Parameters, if exist, in the command - to their actual values. - The parameter name format is :ParameterName. + This class represents the ErrorResponse and NoticeResponse + message sent from PostgreSQL server. - A version of CommandText with the Parameters inserted. - + - Gets or sets the SQL statement or function (stored procedure) to execute at the data source. + Return a string representation of this error object. - The Transact-SQL statement or stored procedure to execute. The default is an empty string. - + - Gets or sets the wait time before terminating the attempt - to execute a command and generating an error. + Severity code. All versions. - The time (in seconds) to wait for the command to execute. - The default is 20 seconds. - + - Gets or sets a value indicating how the - CommandText property is to be interpreted. + Error code. PostgreSQL 7.4 and up. - One of the CommandType values. The default is CommandType.Text. - + - Gets or sets the NpgsqlConnection - used by this instance of the NpgsqlCommand. + Terse error message. All versions. - The connection to a data source. The default value is a null reference. - + - Gets the NpgsqlParameterCollection. + Detailed error message. PostgreSQL 7.4 and up. - The parameters of the SQL statement or function (stored procedure). The default is an empty collection. - + - Gets or sets the NpgsqlTransaction - within which the NpgsqlCommand executes. + Suggestion to help resolve the error. PostgreSQL 7.4 and up. - The NpgsqlTransaction. - The default value is a null reference. - + - Gets or sets how command results are applied to the DataRow - when used by the Update - method of the DbDataAdapter. + Position (one based) within the query string where the error was encounterd. PostgreSQL 7.4 and up. - One of the UpdateRowSource values. - + - Returns oid of inserted row. This is only updated when using executenonQuery and when command inserts just a single row. If table is created without oids, this will always be 0. + Position (one based) within the query string where the error was encounterd. This position refers to an internal command executed for example inside a PL/pgSQL function. PostgreSQL 7.4 and up. + + + Internal query string where the error was encounterd. This position refers to an internal command executed for example inside a PL/pgSQL function. PostgreSQL 7.4 and up. + + + + + Trace back information. PostgreSQL 7.4 and up. + + + + + Source file (in backend) reporting the error. PostgreSQL 7.4 and up. + + + + + Source file line number (in backend) reporting the error. PostgreSQL 7.4 and up. + + + + + Source routine (in backend) reporting the error. PostgreSQL 7.4 and up. + + + + + Schema name which relates to the error. PostgreSQL 9.3 and up. + + + + + Table name which relates to the error. PostgreSQL 9.3 and up. + + + + + Column name which relates to the error. PostgreSQL 9.3 and up. + + + + + Data type of column which relates to the error. PostgreSQL 9.3 and up. + + + + + Constraint name which relates to the error. PostgreSQL 9.3 and up. + + + + + String containing the sql sent which produced this error. + + + + + Backend protocol version in use. + + + + + Error and notice message field codes + + + + + Severity: the field contents are ERROR, FATAL, or PANIC (in an error message), + or WARNING, NOTICE, DEBUG, INFO, or LOG (in a notice message), or a localized + translation of one of these. Always present. + + + + + Code: the SQLSTATE code for the error (see Appendix A). Not localizable. Always present. + + + + + Message: the primary human-readable error message. This should be accurate + but terse (typically one line). Always present. + + + + + Detail: an optional secondary error message carrying more detail about the problem. + Might run to multiple lines. + + + + + Hint: an optional suggestion what to do about the problem. This is intended to differ + from Detail in that it offers advice (potentially inappropriate) rather than hard facts. + Might run to multiple lines. + + + + + Position: the field value is a decimal ASCII integer, indicating an error cursor + position as an index into the original query string. The first character has index 1, + and positions are measured in characters not bytes. + + + + + Internal position: this is defined the same as the P field, but it is used when the + cursor position refers to an internally generated command rather than the one submitted + by the client. + The q field will always appear when this field appears. + + + + + Internal query: the text of a failed internally-generated command. + This could be, for example, a SQL query issued by a PL/pgSQL function. + + + + + Where: an indication of the context in which the error occurred. + Presently this includes a call stack traceback of active procedural language functions + and internally-generated queries. The trace is one entry per line, most recent first. + + + + + Schema name: if the error was associated with a specific database object, + the name of the schema containing that object, if any. + + + + + Table name: if the error was associated with a specific table, the name of the table. + (Refer to the schema name field for the name of the table's schema.) + + + + + Column name: if the error was associated with a specific table column, the name of the column. + (Refer to the schema and table name fields to identify the table.) + + + + + Data type name: if the error was associated with a specific data type, the name of the data type. + (Refer to the schema name field for the name of the data type's schema.) + + + + + Constraint name: if the error was associated with a specific constraint, the name of the constraint. + Refer to fields listed above for the associated table or domain. + (For this purpose, indexes are treated as constraints, even if they weren't created with constraint syntax.) + + + + + File: the file name of the source-code location where the error was reported. + + + + + Line: the line number of the source-code location where the error was reported. + + + + + Routine: the name of the source-code routine reporting the error. + + + + + The level of verbosity of the NpgsqlEventLog + + + + + Don't log at all + + + + + Only log the most common issues + + + + + Log everything + + + + + This class handles all the Npgsql event and debug logging + + + + + Writes a string to the Npgsql event log if msglevel is bigger then NpgsqlEventLog.Level + + + This method is obsolete and should no longer be used. + It is likely to be removed in future versions of Npgsql + + The message to write to the event log + The minimum LogLevel for which this message should be logged. + + + + Writes a string to the Npgsql event log if msglevel is bigger then NpgsqlEventLog.Level + + The ResourceManager to get the localized resources + The name of the resource that should be fetched by the ResourceManager + The minimum LogLevel for which this message should be logged. + The additional parameters that shall be included into the log-message (must be compatible with the string in the resource): + + + + Writes the default log-message for the action of calling the Get-part of an Indexer to the log file. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Indexer + The parameter given to the Indexer + + + + Writes the default log-message for the action of calling the Set-part of an Indexer to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Indexer + The parameter given to the Indexer + The value the Indexer is set to + + + + Writes the default log-message for the action of calling the Get-part of a Property to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Property + The name of the Property + + + + Writes the default log-message for the action of calling the Set-part of a Property to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Property + The name of the Property + The value the Property is set to + + + + Writes the default log-message for the action of calling a Method without Arguments to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Method + The name of the Method + + + + Writes the default log-message for the action of calling a Method with one Argument to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Method + The name of the Method + The value of the Argument of the Method + + + + Writes the default log-message for the action of calling a Method with two Arguments to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Method + The name of the Method + The value of the first Argument of the Method + The value of the second Argument of the Method + + + + Writes the default log-message for the action of calling a Method with three Arguments to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Method + The name of the Method + The value of the first Argument of the Method + The value of the second Argument of the Method + The value of the third Argument of the Method + + + + Writes the default log-message for the action of calling a Method with more than three Arguments to the logfile. + + The minimum LogLevel for which this message should be logged. + The name of the class that contains the Method + The name of the Method + A Object-Array with zero or more Ojects that are Arguments of the Method. + + + + Sets/Returns the level of information to log to the logfile. + + The current LogLevel + + + + Sets/Returns the filename to use for logging. + + The filename of the current Log file. + + + + Sets/Returns whether Log messages should be echoed to the console + + true if Log messages are echoed to the console, otherwise false + + + + The exception that is thrown when the PostgreSQL backend reports errors. + + + + + Construct a backend error exception based on a list of one or more + backend errors. The basic Exception.Message will be built from the + first (usually the only) error in the list. + + + + + Format a .NET style exception string. + Include all errors in the list, including any hints. + + + + + Append a line to the given Stream, first checking for zero-length. + + + + + Provide access to the entire list of errors provided by the PostgreSQL backend. + + + + + Severity code. All versions. + + + + + Error code. PostgreSQL 7.4 and up. + + + + + Basic error message. All versions. + + + + + Detailed error message. PostgreSQL 7.4 and up. + + + + + Suggestion to help resolve the error. PostgreSQL 7.4 and up. + + + + + Position (one based) within the query string where the error was encounterd. PostgreSQL 7.4 and up. + + + + + Trace back information. PostgreSQL 7.4 and up. + + + + + Source file (in backend) reporting the error. PostgreSQL 7.4 and up. + + + + + Source file line number (in backend) reporting the error. PostgreSQL 7.4 and up. + + + + + Source routine (in backend) reporting the error. PostgreSQL 7.4 and up. + + + + + Schema name which relates to the error. PostgreSQL 9.3 and up. + + + + + Table name which relates to the error. PostgreSQL 9.3 and up. + + + + + Column name which relates to the error. PostgreSQL 9.3 and up. + + + + + Data type of column which relates to the error. PostgreSQL 9.3 and up. + + + + + Constraint name which relates to the error. PostgreSQL 9.3 and up. + + + + + String containing the sql sent which produced this error. + + + + + Returns the entire list of errors provided by the PostgreSQL backend. + + + + + This class represents the Execute message sent to PostgreSQL + server. + + + + + + A factory to create instances of various Npgsql objects. + + + + + Creates an NpgsqlCommand object. + + + + + This class represents the Flush message sent to PostgreSQL + server. + + + + + + For classes representing simple messages, + consisting only of a message code and length identifier, + sent from the client to the server. + + + + + This class is responsible for serving as bridge between the backend + protocol handling and the core classes. It is used as the mediator for + exchanging data generated/sent from/to backend. + + + + + + EventArgs class to send Notification parameters. + + + + + Process ID of the PostgreSQL backend that sent this notification. + + + + + Condition that triggered that notification. + + + + + Additional Information From Notifiying Process (for future use, currently postgres always sets this to an empty string) + + + + + This class represents a parameter to a command that will be sent to server + + + + + Initializes a new instance of the NpgsqlParameter class. + + + + + Initializes a new instance of the NpgsqlParameter + class with the parameter m_Name and a value of the new NpgsqlParameter. + + The m_Name of the parameter to map. + An Object that is the value of the NpgsqlParameter. + +

When you specify an Object + in the value parameter, the DbType is + inferred from the .NET Framework type of the Object.

+

When using this constructor, you must be aware of a possible misuse of the constructor which takes a DbType parameter. + This happens when calling this constructor passing an int 0 and the compiler thinks you are passing a value of DbType. + Use Convert.ToInt32(value) for example to have compiler calling the correct constructor.

+
+
+ + + Initializes a new instance of the NpgsqlParameter + class with the parameter m_Name and the data type. + + The m_Name of the parameter to map. + One of the DbType values. + + + + Initializes a new instance of the NpgsqlParameter + class with the parameter m_Name, the DbType, and the size. + + The m_Name of the parameter to map. + One of the DbType values. + The length of the parameter. + + + + Initializes a new instance of the NpgsqlParameter + class with the parameter m_Name, the DbType, the size, + and the source column m_Name. + + The m_Name of the parameter to map. + One of the DbType values. + The length of the parameter. + The m_Name of the source column. + + + + Initializes a new instance of the NpgsqlParameter + class with the parameter m_Name, the DbType, the size, + the source column m_Name, a ParameterDirection, + the precision of the parameter, the scale of the parameter, a + DataRowVersion to use, and the + value of the parameter. + + The m_Name of the parameter to map. + One of the DbType values. + The length of the parameter. + The m_Name of the source column. + One of the ParameterDirection values. + true if the value of the field can be null, otherwise false. + The total number of digits to the left and right of the decimal point to which + Value is resolved. + The total number of decimal places to which + Value is resolved. + One of the DataRowVersion values. + An Object that is the value + of the NpgsqlParameter. + + + + Creates a new NpgsqlParameter that + is a copy of the current instance. + + A new NpgsqlParameter that is a copy of this instance. + + + + The collection to which this parameter belongs, if any. + + + + + Gets or sets the maximum number of digits used to represent the + Value property. + + The maximum number of digits used to represent the + Value property. + The default value is 0, which indicates that the data provider + sets the precision for Value. + + + + Gets or sets the number of decimal places to which + Value is resolved. + + The number of decimal places to which + Value is resolved. The default is 0. + + + + Gets or sets the maximum size, in bytes, of the data within the column. + + The maximum size, in bytes, of the data within the column. + The default value is inferred from the parameter value. + + + + Gets or sets the DbType of the parameter. + + One of the DbType values. The default is String. + + + + Gets or sets the DbType of the parameter. + + One of the DbType values. The default is String. + + + + Gets or sets a value indicating whether the parameter is input-only, + output-only, bidirectional, or a stored procedure return value parameter. + + One of the ParameterDirection + values. The default is Input. + + + + Gets or sets a value indicating whether the parameter accepts null values. + + true if null values are accepted; otherwise, false. The default is false. + + + + Gets or sets the m_Name of the NpgsqlParameter. + + The m_Name of the NpgsqlParameter. + The default is an empty string. + + + + The m_Name scrubbed of any optional marker + + + + + Gets or sets the m_Name of the source column that is mapped to the + DataSet and used for loading or + returning the Value. + + The m_Name of the source column that is mapped to the + DataSet. The default is an empty string. + + + + Gets or sets the DataRowVersion + to use when loading Value. + + One of the DataRowVersion values. + The default is Current. + + + + Gets or sets the value of the parameter. + + An Object that is the value of the parameter. + The default value is null. + + + + Gets or sets the value of the parameter. + + An Object that is the value of the parameter. + The default value is null. + Represents a collection of parameters relevant to a NpgsqlCommand @@ -3866,6 +5038,12 @@ Initializes a new instance of the NpgsqlParameterCollection class. + + + Invalidate the hash lookup tables. This should be done any time a change + may throw the lookups out of sync with the list. + + Adds the specified NpgsqlParameter object to the NpgsqlParameterCollection. @@ -3875,11 +5053,8 @@ - Adds a NpgsqlParameter to the NpgsqlParameterCollection given the specified parameter name and value. + Obsolete. Use AddWithValue instead. - The name of the NpgsqlParameter. - The Value of the NpgsqlParameter to add to the collection. - The index of the new NpgsqlParameter object. Use caution when using this overload of the Add method to specify integer parameter values. @@ -3891,6 +5066,44 @@ are attempting to call the NpgsqlParameterCollection.Add(string, DbType) overload. + + + Adds a NpgsqlParameter to the NpgsqlParameterCollection given the specified parameter name and value. + + The name of the NpgsqlParameter. + The Value of the NpgsqlParameter to add to the collection. + The paramater that was added. + + + + Adds a NpgsqlParameter to the NpgsqlParameterCollection given the specified parameter name and value. + + The name of the NpgsqlParameter. + The Value of the NpgsqlParameter to add to the collection. + One of the NpgsqlDbType values. + The paramater that was added. + + + + Adds a NpgsqlParameter to the NpgsqlParameterCollection given the specified parameter name and value. + + The name of the NpgsqlParameter. + The Value of the NpgsqlParameter to add to the collection. + One of the NpgsqlDbType values. + The length of the column. + The paramater that was added. + + + + Adds a NpgsqlParameter to the NpgsqlParameterCollection given the specified parameter name and value. + + The name of the NpgsqlParameter. + The Value of the NpgsqlParameter to add to the collection. + One of the NpgsqlDbType values. + The length of the column. + The name of the source column. + The paramater that was added. + Adds a NpgsqlParameter to the NpgsqlParameterCollection given the parameter name and the data type. @@ -3949,13 +5162,19 @@ Inserts a NpgsqlParameter into the collection at the specified index. The zero-based index where the parameter is to be inserted within the collection. - The NpgsqlParameter to add to the collection. + The NpgsqlParameter to add to the collection. + + + + Removes the specified NpgsqlParameter from the collection. + + The name of the NpgsqlParameter to remove from the collection. Removes the specified NpgsqlParameter from the collection. - The NpgsqlParameter to remove from the collection. + The NpgsqlParameter to remove from the collection. @@ -4031,84 +5250,19 @@ The number of NpgsqlParameter objects in the collection. - - - Represents an ongoing COPY FROM STDIN operation. - Provides methods to push data to server and end or cancel the operation. - - - - - Called from NpgsqlState.ProcessBackendResponses upon CopyInResponse. - If CopyStream is already set, it is used to read data to push to server, after which the copy is completed. - Otherwise CopyStream is set to a writable NpgsqlCopyInStream that calls SendCopyData each time it is written to. - - - - - Sends given packet to server as a CopyData message. - Does not check for notifications! Use another thread for that. - - - - - Sends CopyDone message to server. Handles responses, ie. may throw an exception. - - - - - Sends CopyFail message to server. Handles responses, ie. should always throw an exception: - in CopyIn state the server responds to CopyFail with an error response; - outside of a CopyIn state the server responds to CopyFail with an error response; - without network connection or whatever, there's going to eventually be a failure, timeout or user intervention. - - - - - Copy format information returned from server. - - - - - Represents a PostgreSQL Point type - - - - - Represents a PostgreSQL Line Segment type. - - - - - Represents a PostgreSQL Path type. - - - - - Represents a PostgreSQL Polygon type. - - - - - Represents a PostgreSQL Circle type. - - - - - Represents a PostgreSQL inet type. - - - - - Represents a PostgreSQL MacAddress type. - - - - + + + This class represents the ParameterStatus message sent from PostgreSQL + server. + + + + + + This class represents the Parse message sent to PostgreSQL + server. + - - The macAddr parameter must contain a string that can only consist of numbers - and upper-case letters as hexadecimal digits. (See PhysicalAddress.Parse method on MSDN) @@ -4116,5 +5270,351 @@ PostgreSQL. + + + Used when a connection is closed + + + + + Summary description for NpgsqlQuery + + + + + This is the abstract base class for NpgsqlAsciiRow and NpgsqlBinaryRow. + + + + + This class represents a RowDescription message sent from + the PostgreSQL. + + + + + + This struct represents the internal data of the RowDescription message. + + + + + Provides the underlying mechanism for reading schema information. + + + + + Returns the MetaDataCollections that lists all possible collections. + + The MetaDataCollections + + + + Returns the Restrictions that contains the meaning and position of the values in the restrictions array. + + The Restrictions + + + + Returns the Databases that contains a list of all accessable databases. + + The database connection on which to run the metadataquery. + The restrictions to filter the collection. + The Databases + + + + Returns the Tables that contains table and view names and the database and schema they come from. + + The database connection on which to run the metadataquery. + The restrictions to filter the collection. + The Tables + + + + Returns the Columns that contains information about columns in tables. + + The database connection on which to run the metadataquery. + The restrictions to filter the collection. + The Columns. + + + + Returns the Views that contains view names and the database and schema they come from. + + The database connection on which to run the metadataquery. + The restrictions to filter the collection. + The Views + + + + Returns the Users containing user names and the sysid of those users. + + The database connection on which to run the metadataquery. + The restrictions to filter the collection. + The Users. + + + + This class represents a StartupPacket message of PostgreSQL + protocol. + + + + + + Represents a completed response message. + + + + + This class represents the Sync message sent to PostgreSQL + server. + + + + + + Represents a transaction to be made in a PostgreSQL database. This class cannot be inherited. + + + + + Commits the database transaction. + + + + + Rolls back a transaction from a pending state. + + + + + Rolls back a transaction from a pending savepoint state. + + + + + Creates a transaction save point. + + + + + Cancel the transaction without telling the backend about it. This is + used to make the transaction go away when closing a connection. + + + + + Gets the NpgsqlConnection + object associated with the transaction, or a null reference if the + transaction is no longer valid. + + The NpgsqlConnection + object associated with the transaction. + + + + Specifies the IsolationLevel for this transaction. + + The IsolationLevel for this transaction. + The default is ReadCommitted. + + + + This class provides many util methods to handle + reading and writing of PostgreSQL protocol messages. + + + + + This method takes a ProtocolVersion and returns an integer + version number that the Postgres backend will recognize in a + startup packet. + + + + + This method takes a version string as returned by SELECT VERSION() and returns + a valid version string ("7.2.2" for example). + This is only needed when running protocol version 2. + This does not do any validity checks. + + + + + This method gets a C NULL terminated string from the network stream. + It keeps reading a byte in each time until a NULL byte is returned. + It returns the resultant string of bytes read. + This string is sent from backend. + + + + + Reads requested number of bytes from stream with retries until Stream.Read returns 0 or count is reached. + + Stream to read + byte buffer to fill + starting position to fill the buffer + number of bytes to read + The number of bytes read. May be less than count if no more bytes are available. + + + + Reads requested number of bytes from . If output matches exactly, and == false, is returned directly. + + Source array. + Starting position to read from + Number of bytes to read + Force a copy, even if the output is an exact copy of . + byte[] containing data requested. + + + + This method writes a string to the network stream. + + + + + This method writes a string to the network stream. + + + + + This method writes a C NULL terminated string to the network stream. + It appends a NULL terminator to the end of the String. + + + + + This method writes a C NULL terminated string to the network stream. + It appends a NULL terminator to the end of the String. + + + + + This method writes a byte to the stream. It also enables logging of them. + + + + + This method writes a byte to the stream. It also enables logging of them. + + + + + This method writes a set of bytes to the stream. It also enables logging of them. + + + + + This method writes a set of bytes to the stream. It also enables logging of them. + + + + + This method writes a C NULL terminated string limited in length to the + backend server. + It pads the string with null bytes to the size specified. + + + + + This method writes a C NULL terminated byte[] limited in length to the + backend server. + It pads the string with null bytes to the size specified. + + + + + Write a 32-bit integer to the given stream in the correct byte order. + + + + + Read a 32-bit integer from the given stream in the correct byte order. + + + + + Read a 32-bit integer from the given array in the correct byte order. + + + + + Write a 16-bit integer to the given stream in the correct byte order. + + + + + Read a 16-bit integer from the given stream in the correct byte order. + + + + + Read a 16-bit integer from the given array in the correct byte order. + + + + + Copy and possibly reverse a byte array, depending on host architecture endienness. + + Source byte array. + Force a copy even if no swap is performed. + , reversed if on a little-endian architecture, copied if required. + + + + Copy and possibly reverse a byte array, depending on host architecture endienness. + + Source byte array. + Starting offset in source array. + Number of bytes to copy. + Force a copy even if no swap is performed. + , reversed if on a little-endian architecture, copied if required. + + + + Represent the frontend/backend protocol version. + + + + + Represent the backend server version. + As this class offers no functionality beyond that offered by it has been + deprecated in favour of that class. + + + + + + Returns the string representation of this version in three place dot notation (Major.Minor.Patch). + + + + + Server version major number. + + + + + Server version minor number. + + + + + Server version patch level number. + + + + + A class to handle everything associated with SSPI authentication + + + + + Simplified SecBufferDesc struct with only one SecBuffer + + diff --git a/bin/OpenMetaverse.Rendering.Meshmerizer.dll b/bin/OpenMetaverse.Rendering.Meshmerizer.dll index 1a12a1e774..eab5fc7f40 100755 Binary files a/bin/OpenMetaverse.Rendering.Meshmerizer.dll and b/bin/OpenMetaverse.Rendering.Meshmerizer.dll differ diff --git a/bin/OpenMetaverse.StructuredData.XML b/bin/OpenMetaverse.StructuredData.XML deleted file mode 100644 index 8f0dd817a3..0000000000 --- a/bin/OpenMetaverse.StructuredData.XML +++ /dev/null @@ -1,349 +0,0 @@ - - - - OpenMetaverse.StructuredData - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Uses reflection to create an SDMap from all of the SD - serializable types in an object - - Class or struct containing serializable types - An SDMap holding the serialized values from the - container object - - - - Uses reflection to deserialize member variables in an object from - an SDMap - - Reference to an object to fill with deserialized - values - Serialized values to put in the target - object - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Deserializes binary LLSD - - Serialized data - OSD containting deserialized data - - - - Deserializes binary LLSD - - Stream to read the data from - OSD containting deserialized data - - - - Serializes OSD to binary format. It does no prepend header - - OSD to serialize - Serialized data - - - - Serializes OSD to binary format - - OSD to serialize - - Serialized data - - - - Serializes OSD to binary format. It does no prepend header - - OSD to serialize - Serialized data - - - - Serializes OSD to binary format - - OSD to serialize - - Serialized data - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/bin/OpenMetaverse.StructuredData.dll b/bin/OpenMetaverse.StructuredData.dll index 7aeb0894f2..999463da4b 100755 Binary files a/bin/OpenMetaverse.StructuredData.dll and b/bin/OpenMetaverse.StructuredData.dll differ diff --git a/bin/OpenMetaverse.XML b/bin/OpenMetaverse.XML deleted file mode 100644 index ce8ca8678a..0000000000 --- a/bin/OpenMetaverse.XML +++ /dev/null @@ -1,36656 +0,0 @@ - - - - OpenMetaverse - - - - - Permission request flags, asked when a script wants to control an Avatar - - - - Placeholder for empty values, shouldn't ever see this - - - Script wants ability to take money from you - - - Script wants to take camera controls for you - - - Script wants to remap avatars controls - - - Script wants to trigger avatar animations - This function is not implemented on the grid - - - Script wants to attach or detach the prim or primset to your avatar - - - Script wants permission to release ownership - This function is not implemented on the grid - The concept of "public" objects does not exist anymore. - - - Script wants ability to link/delink with other prims - - - Script wants permission to change joints - This function is not implemented on the grid - - - Script wants permissions to change permissions - This function is not implemented on the grid - - - Script wants to track avatars camera position and rotation - - - Script wants to control your camera - - - Script wants the ability to teleport you - - - - Special commands used in Instant Messages - - - - Indicates a regular IM from another agent - - - Simple notification box with an OK button - - - You've been invited to join a group. - - - Inventory offer - - - Accepted inventory offer - - - Declined inventory offer - - - Group vote - - - An object is offering its inventory - - - Accept an inventory offer from an object - - - Decline an inventory offer from an object - - - Unknown - - - Start a session, or add users to a session - - - Start a session, but don't prune offline users - - - Start a session with your group - - - Start a session without a calling card (finder or objects) - - - Send a message to a session - - - Leave a session - - - Indicates that the IM is from an object - - - Sent an IM to a busy user, this is the auto response - - - Shows the message in the console and chat history - - - Send a teleport lure - - - Response sent to the agent which inititiated a teleport invitation - - - Response sent to the agent which inititiated a teleport invitation - - - Only useful if you have Linden permissions - - - Request a teleport lure - - - IM to tell the user to go to an URL - - - IM for help - - - IM sent automatically on call for help, sends a lure - to each Helper reached - - - Like an IM but won't go to email - - - IM from a group officer to all group members - - - Unknown - - - Unknown - - - Accept a group invitation - - - Decline a group invitation - - - Unknown - - - An avatar is offering you friendship - - - An avatar has accepted your friendship offer - - - An avatar has declined your friendship offer - - - Indicates that a user has started typing - - - Indicates that a user has stopped typing - - - - Flag in Instant Messages, whether the IM should be delivered to - offline avatars as well - - - - Only deliver to online avatars - - - If the avatar is offline the message will be held until - they login next, and possibly forwarded to their e-mail account - - - - Conversion type to denote Chat Packet types in an easier-to-understand format - - - - Whisper (5m radius) - - - Normal chat (10/20m radius), what the official viewer typically sends - - - Shouting! (100m radius) - - - Event message when an Avatar has begun to type - - - Event message when an Avatar has stopped typing - - - Send the message to the debug channel - - - Event message when an object uses llOwnerSay - - - Event message when an object uses llRegionSayTo - - - Special value to support llRegionSay, never sent to the client - - - - Identifies the source of a chat message - - - - Chat from the grid or simulator - - - Chat from another avatar - - - Chat from an object - - - - - - - - - - - - - - - - - - Effect type used in ViewerEffect packets - - - - - - - - - - - - - - - - - - - - - - - - - Project a beam from a source to a destination, such as - the one used when editing an object - - - - - - - - - - - - Create a swirl of particles around an object - - - - - - - - - Cause an avatar to look at an object - - - Cause an avatar to point at an object - - - - The action an avatar is doing when looking at something, used in - ViewerEffect packets for the LookAt effect - - - - - - - - - - - - - - - - - - - - - - Deprecated - - - - - - - - - - - - - - - - The action an avatar is doing when pointing at something, used in - ViewerEffect packets for the PointAt effect - - - - - - - - - - - - - - - - - Money transaction types - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Flags sent when a script takes or releases a control - - NOTE: (need to verify) These might be a subset of the ControlFlags enum in Movement, - - - No Flags set - - - Forward (W or up Arrow) - - - Back (S or down arrow) - - - Move left (shift+A or left arrow) - - - Move right (shift+D or right arrow) - - - Up (E or PgUp) - - - Down (C or PgDown) - - - Rotate left (A or left arrow) - - - Rotate right (D or right arrow) - - - Left Mouse Button - - - Left Mouse button in MouseLook - - - - Currently only used to hide your group title - - - - No flags set - - - Hide your group title - - - - Action state of the avatar, which can currently be typing and - editing - - - - - - - - - - - - - - Current teleport status - - - - Unknown status - - - Teleport initialized - - - Teleport in progress - - - Teleport failed - - - Teleport completed - - - Teleport cancelled - - - - - - - - No flags set, or teleport failed - - - Set when newbie leaves help island for first time - - - - - - Via Lure - - - Via Landmark - - - Via Location - - - Via Home - - - Via Telehub - - - Via Login - - - Linden Summoned - - - Linden Forced me - - - - - - Agent Teleported Home via Script - - - - - - - - - - - - forced to new location for example when avatar is banned or ejected - - - Teleport Finished via a Lure - - - Finished, Sim Changed - - - Finished, Same Sim - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Type of mute entry - - - - Object muted by name - - - Muted residet - - - Object muted by UUID - - - Muted group - - - Muted external entry - - - - Flags of mute entry - - - - No exceptions - - - Don't mute text chat - - - Don't mute voice chat - - - Don't mute particles - - - Don't mute sounds - - - Don't mute - - - - Instant Message - - - - Key of sender - - - Name of sender - - - Key of destination avatar - - - ID of originating estate - - - Key of originating region - - - Coordinates in originating region - - - Instant message type - - - Group IM session toggle - - - Key of IM session, for Group Messages, the groups UUID - - - Timestamp of the instant message - - - Instant message text - - - Whether this message is held for offline avatars - - - Context specific packed data - - - Print the struct data as a string - A string containing the field name, and field value - - - Represents muted object or resident - - - Type of the mute entry - - - UUID of the mute etnry - - - Mute entry name - - - Mute flags - - - Transaction detail sent with MoneyBalanceReply message - - - Type of the transaction - - - UUID of the transaction source - - - Is the transaction source a group - - - UUID of the transaction destination - - - Is transaction destination a group - - - Transaction amount - - - Transaction description - - - - Manager class for our own avatar - - - - - Called once attachment resource usage information has been collected - - Indicates if operation was successfull - Attachment resource usage information - - - The event subscribers. null if no subcribers - - - Raises the ChatFromSimulator event - A ChatEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a scripted object or agent within range sends a public message - - - The event subscribers. null if no subcribers - - - Raises the ScriptDialog event - A SctriptDialogEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a scripted object sends a dialog box containing possible - options an agent can respond to - - - The event subscribers. null if no subcribers - - - Raises the ScriptQuestion event - A ScriptQuestionEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when an object requests a change in the permissions an agent has permitted - - - The event subscribers. null if no subcribers - - - Raises the LoadURL event - A LoadUrlEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a script requests an agent open the specified URL - - - The event subscribers. null if no subcribers - - - Raises the MoneyBalance event - A BalanceEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when an agents currency balance is updated - - - The event subscribers. null if no subcribers - - - Raises the MoneyBalanceReply event - A MoneyBalanceReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a transaction occurs involving currency such as a land purchase - - - The event subscribers. null if no subcribers - - - Raises the IM event - A InstantMessageEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when an ImprovedInstantMessage packet is recieved from the simulator, this is used for everything from - private messaging to friendship offers. The Dialog field defines what type of message has arrived - - - The event subscribers. null if no subcribers - - - Raises the TeleportProgress event - A TeleportEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when an agent has requested a teleport to another location, or when responding to a lure. Raised multiple times - for each teleport indicating the progress of the request - - - The event subscribers. null if no subcribers - - - Raises the AgentDataReply event - A AgentDataReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a simulator sends agent specific information for our avatar. - - - The event subscribers. null if no subcribers - - - Raises the AnimationsChanged event - A AnimationsChangedEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when our agents animation playlist changes - - - The event subscribers. null if no subcribers - - - Raises the MeanCollision event - A MeanCollisionEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when an object or avatar forcefully collides with our agent - - - The event subscribers. null if no subcribers - - - Raises the RegionCrossed event - A RegionCrossedEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when our agent crosses a region border into another region - - - The event subscribers. null if no subcribers - - - Raises the GroupChatJoined event - A GroupChatJoinedEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when our agent succeeds or fails to join a group chat session - - - The event subscribers. null if no subcribers - - - Raises the AlertMessage event - A AlertMessageEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a simulator sends an urgent message usually indication the recent failure of - another action we have attempted to take such as an attempt to enter a parcel where we are denied access - - - The event subscribers. null if no subcribers - - - Raises the ScriptControlChange event - A ScriptControlEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a script attempts to take or release specified controls for our agent - - - The event subscribers. null if no subcribers - - - Raises the CameraConstraint event - A CameraConstraintEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator detects our agent is trying to view something - beyond its limits - - - The event subscribers. null if no subcribers - - - Raises the ScriptSensorReply event - A ScriptSensorReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a script sensor reply is received from a simulator - - - The event subscribers. null if no subcribers - - - Raises the AvatarSitResponse event - A AvatarSitResponseEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised in response to a request - - - The event subscribers. null if no subcribers - - - Raises the ChatSessionMemberAdded event - A ChatSessionMemberAddedEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when an avatar enters a group chat session we are participating in - - - The event subscribers. null if no subcribers - - - Raises the ChatSessionMemberLeft event - A ChatSessionMemberLeftEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when an agent exits a group chat session we are participating in - - - The event subscribers, null of no subscribers - - - Raises the SetDisplayNameReply Event - A SetDisplayNameReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the details of display name change - - - The event subscribers. null if no subcribers - - - Raises the MuteListUpdated event - A EventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a scripted object or agent within range sends a public message - - - Reference to the GridClient instance - - - Used for movement and camera tracking - - - Currently playing animations for the agent. Can be used to - check the current movement status such as walking, hovering, aiming, - etc. by checking against system animations found in the Animations class - - - Dictionary containing current Group Chat sessions and members - - - Dictionary containing mute list keyead on mute name and key - - - Your (client) avatars - "client", "agent", and "avatar" all represent the same thing - - - Temporary assigned to this session, used for - verifying our identity in packets - - - Shared secret that is never sent over the wire - - - Your (client) avatar ID, local to the current region/sim - - - Where the avatar started at login. Can be "last", "home" - or a login - - - The access level of this agent, usually M, PG or A - - - The CollisionPlane of Agent - - - An representing the velocity of our agent - - - An representing the acceleration of our agent - - - A which specifies the angular speed, and axis about which an Avatar is rotating. - - - Position avatar client will goto when login to 'home' or during - teleport request to 'home' region. - - - LookAt point saved/restored with HomePosition - - - Avatar First Name (i.e. Philip) - - - Avatar Last Name (i.e. Linden) - - - LookAt point received with the login response message - - - Avatar Full Name (i.e. Philip Linden) - - - Gets the health of the agent - - - Gets the current balance of the agent - - - Gets the local ID of the prim the agent is sitting on, - zero if the avatar is not currently sitting - - - Gets the of the agents active group. - - - Gets the Agents powers in the currently active group - - - Current status message for teleporting - - - Current position of the agent as a relative offset from - the simulator, or the parent object if we are sitting on something - - - Current rotation of the agent as a relative rotation from - the simulator, or the parent object if we are sitting on something - - - Current position of the agent in the simulator - - - - A representing the agents current rotation - - - - Returns the global grid position of the avatar - - - Various abilities and preferences sent by the grid - - - - Constructor, setup callbacks for packets related to our avatar - - A reference to the Class - - - - Send a text message from the Agent to the Simulator - - A containing the message - The channel to send the message on, 0 is the public channel. Channels above 0 - can be used however only scripts listening on the specified channel will see the message - Denotes the type of message being sent, shout, whisper, etc. - - - - Request any instant messages sent while the client was offline to be resent. - - - - - Send an Instant Message to another Avatar - - The recipients - A containing the message to send - - - - Send an Instant Message to an existing group chat or conference chat - - The recipients - A containing the message to send - IM session ID (to differentiate between IM windows) - - - - Send an Instant Message - - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - IDs of sessions for a conference - - - - Send an Instant Message - - The name this IM will show up as being from - Key of Avatar - Text message being sent - IM session ID (to differentiate between IM windows) - Type of instant message to send - Whether to IM offline avatars as well - Senders Position - RegionID Sender is In - Packed binary data that is specific to - the dialog type - - - - Send an Instant Message to a group - - of the group to send message to - Text Message being sent. - - - - Send an Instant Message to a group the agent is a member of - - The name this IM will show up as being from - of the group to send message to - Text message being sent - - - - Send a request to join a group chat session - - of Group to leave - - - - Exit a group chat session. This will stop further Group chat messages - from being sent until session is rejoined. - - of Group chat session to leave - - - - Reply to script dialog questions. - - Channel initial request came on - Index of button you're "clicking" - Label of button you're "clicking" - of Object that sent the dialog request - - - - - Accept invite for to a chatterbox session - - of session to accept invite to - - - - Start a friends conference - - List of UUIDs to start a conference with - the temportary session ID returned in the callback> - - - - Start a particle stream between an agent and an object - - Key of the source agent - Key of the target object - - The type from the enum - A unique for this effect - - - - Start a particle stream between an agent and an object - - Key of the source agent - Key of the target object - A representing the beams offset from the source - A which sets the avatars lookat animation - of the Effect - - - - Create a particle beam between an avatar and an primitive - - The ID of source avatar - The ID of the target primitive - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam - - - - - Create a particle swirl around a target position using a packet - - global offset - A object containing the combined red, green, blue and alpha - color values of particle beam - a float representing the duration the parcicle beam will last - A Unique ID for the beam - - - - Sends a request to sit on the specified object - - of the object to sit on - Sit at offset - - - - Follows a call to to actually sit on the object - - - - Stands up from sitting on a prim or the ground - true of AgentUpdate was sent - - - - Does a "ground sit" at the avatar's current position - - - - - Starts or stops flying - - True to start flying, false to stop flying - - - - Starts or stops crouching - - True to start crouching, false to stop crouching - - - - Starts a jump (begin holding the jump key) - - - - - Use the autopilot sim function to move the avatar to a new - position. Uses double precision to get precise movements - - The z value is currently not handled properly by the simulator - Global X coordinate to move to - Global Y coordinate to move to - Z coordinate to move to - - - - Use the autopilot sim function to move the avatar to a new position - - The z value is currently not handled properly by the simulator - Integer value for the global X coordinate to move to - Integer value for the global Y coordinate to move to - Floating-point value for the Z coordinate to move to - - - - Use the autopilot sim function to move the avatar to a new position - - The z value is currently not handled properly by the simulator - Integer value for the local X coordinate to move to - Integer value for the local Y coordinate to move to - Floating-point value for the Z coordinate to move to - - - Macro to cancel autopilot sim function - Not certain if this is how it is really done - true if control flags were set and AgentUpdate was sent to the simulator - - - - Grabs an object - - an unsigned integer of the objects ID within the simulator - - - - - Overload: Grab a simulated object - - an unsigned integer of the objects ID within the simulator - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - - - - Drag an object - - of the object to drag - Drag target in region coordinates - - - - Overload: Drag an object - - of the object to drag - Drag target in region coordinates - - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - - - - Release a grabbed object - - The Objects Simulator Local ID - - - - - - - Release a grabbed object - - The Objects Simulator Local ID - The texture coordinates to grab - The surface coordinates to grab - The face of the position to grab - The region coordinates of the position to grab - The surface normal of the position to grab (A normal is a vector perpindicular to the surface) - The surface binormal of the position to grab (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - - - - Touches an object - - an unsigned integer of the objects ID within the simulator - - - - - Request the current L$ balance - - - - - Give Money to destination Avatar - - UUID of the Target Avatar - Amount in L$ - - - - Give Money to destination Avatar - - UUID of the Target Avatar - Amount in L$ - Description that will show up in the - recipients transaction history - - - - Give L$ to an object - - object to give money to - amount of L$ to give - name of object - - - - Give L$ to a group - - group to give money to - amount of L$ to give - - - - Give L$ to a group - - group to give money to - amount of L$ to give - description of transaction - - - - Pay texture/animation upload fee - - - - - Pay texture/animation upload fee - - description of the transaction - - - - Give Money to destination Object or Avatar - - UUID of the Target Object/Avatar - Amount in L$ - Reason (Optional normally) - The type of transaction - Transaction flags, mostly for identifying group - transactions - - - - Plays a gesture - - Asset of the gesture - - - - Mark gesture active - - Inventory of the gesture - Asset of the gesture - - - - Mark gesture inactive - - Inventory of the gesture - - - - Send an AgentAnimation packet that toggles a single animation on - - The of the animation to start playing - Whether to ensure delivery of this packet or not - - - - Send an AgentAnimation packet that toggles a single animation off - - The of a - currently playing animation to stop playing - Whether to ensure delivery of this packet or not - - - - Send an AgentAnimation packet that will toggle animations on or off - - A list of animation s, and whether to - turn that animation on or off - Whether to ensure delivery of this packet or not - - - - Teleports agent to their stored home location - - true on successful teleport to home location - - - - Teleport agent to a landmark - - of the landmark to teleport agent to - true on success, false on failure - - - - Attempt to look up a simulator name and teleport to the discovered - destination - - Region name to look up - Position to teleport to - True if the lookup and teleport were successful, otherwise - false - - - - Attempt to look up a simulator name and teleport to the discovered - destination - - Region name to look up - Position to teleport to - Target to look at - True if the lookup and teleport were successful, otherwise - false - - - - Teleport agent to another region - - handle of region to teleport agent to - position in destination sim to teleport to - true on success, false on failure - This call is blocking - - - - Teleport agent to another region - - handle of region to teleport agent to - position in destination sim to teleport to - direction in destination sim agent will look at - true on success, false on failure - This call is blocking - - - - Request teleport to a another simulator - - handle of region to teleport agent to - position in destination sim to teleport to - - - - Request teleport to a another simulator - - handle of region to teleport agent to - position in destination sim to teleport to - direction in destination sim agent will look at - - - - Teleport agent to a landmark - - of the landmark to teleport agent to - - - - Send a teleport lure to another avatar with default "Join me in ..." invitation message - - target avatars to lure - - - - Send a teleport lure to another avatar with custom invitation message - - target avatars to lure - custom message to send with invitation - - - - Respond to a teleport lure by either accepting it and initiating - the teleport, or denying it - - of the avatar sending the lure - IM session of the incoming lure request - true to accept the lure, false to decline it - - - - Update agent profile - - struct containing updated - profile information - - - - Update agents profile interests - - selection of interests from struct - - - - Set the height and the width of the client window. This is used - by the server to build a virtual camera frustum for our avatar - - New height of the viewer window - New width of the viewer window - - - - Request the list of muted objects and avatars for this agent - - - - - Mute an object, resident, etc. - - Mute type - Mute UUID - Mute name - - - - Mute an object, resident, etc. - - Mute type - Mute UUID - Mute name - Mute flags - - - - Unmute an object, resident, etc. - - Mute UUID - Mute name - - - - Sets home location to agents current position - - will fire an AlertMessage () with - success or failure message - - - - Move an agent in to a simulator. This packet is the last packet - needed to complete the transition in to a new simulator - - Object - - - - Reply to script permissions request - - Object - of the itemID requesting permissions - of the taskID requesting permissions - list of permissions to allow - - - - Respond to a group invitation by either accepting or denying it - - UUID of the group (sent in the AgentID field of the invite message) - IM Session ID from the group invitation message - Accept the group invitation or deny it - - - - Requests script detection of objects and avatars - - name of the object/avatar to search for - UUID of the object or avatar to search for - Type of search from ScriptSensorTypeFlags - range of scan (96 max?) - the arc in radians to search within - an user generated ID to correlate replies with - Simulator to perform search in - - - - Create or update profile pick - - UUID of the pick to update, or random UUID to create a new pick - Is this a top pick? (typically false) - UUID of the parcel (UUID.Zero for the current parcel) - Name of the pick - Global position of the pick landmark - UUID of the image displayed with the pick - Long description of the pick - - - - Delete profile pick - - UUID of the pick to delete - - - - Create or update profile Classified - - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Global position of the classified landmark - Name of the classified - Long description of the classified - if true, auto renew classified after expiration - - - - Create or update profile Classified - - UUID of the classified to update, or random UUID to create a new classified - Defines what catagory the classified is in - UUID of the image displayed with the classified - Price that the classified will cost to place for a week - Name of the classified - Long description of the classified - if true, auto renew classified after expiration - - - - Delete a classified ad - - The classified ads ID - - - - Fetches resource usage by agents attachmetns - - Called when the requested information is collected - - - - Initates request to set a new display name - - Previous display name - Desired new display name - - - - Tells the sim what UI language is used, and if it's ok to share that with scripts - - Two letter language code - Share language info with scripts - - - - Sets agents maturity access level - - PG, M or A - - - - Sets agents maturity access level - - PG, M or A - Callback function - - - - Take an incoming ImprovedInstantMessage packet, auto-parse, and if - OnInstantMessage is defined call that with the appropriate arguments - - The sender - The EventArgs object containing the packet data - - - - Take an incoming Chat packet, auto-parse, and if OnChat is defined call - that with the appropriate arguments. - - The sender - The EventArgs object containing the packet data - - - - Used for parsing llDialogs - - The sender - The EventArgs object containing the packet data - - - - Used for parsing llRequestPermissions dialogs - - The sender - The EventArgs object containing the packet data - - - - Handles Script Control changes when Script with permissions releases or takes a control - - The sender - The EventArgs object containing the packet data - - - - Used for parsing llLoadURL Dialogs - - The sender - The EventArgs object containing the packet data - - - - Update client's Position, LookAt and region handle from incoming packet - - The sender - The EventArgs object containing the packet data - This occurs when after an avatar moves into a new sim - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - EQ Message fired with the result of SetDisplayName request - - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - - - Process TeleportFailed message sent via EventQueue, informs agent its last teleport has failed and why. - - The Message Key - An IMessage object Deserialized from the recieved message event - The simulator originating the event message - - - - Process TeleportFinish from Event Queue and pass it onto our TeleportHandler - - The message system key for this event - IMessage object containing decoded data from OSD - The simulator originating the event message - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. - - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - This packet is now being sent via the EventQueue - - - - Group Chat event handler - - The capability Key - IMessage object containing decoded data from OSD - - - - - Response from request to join a group chat - - - IMessage object containing decoded data from OSD - - - - - Someone joined or left group chat - - - IMessage object containing decoded data from OSD - - - - - Handle a group chat Invitation - - Caps Key - IMessage object containing decoded data from OSD - Originating Simulator - - - - Moderate a chat session - - the of the session to moderate, for group chats this will be the groups UUID - the of the avatar to moderate - Either "voice" to moderate users voice, or "text" to moderate users text session - true to moderate (silence user), false to allow avatar to speak - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - Agent movement and camera control - - Agent movement is controlled by setting specific - After the control flags are set, An AgentUpdate is required to update the simulator of the specified flags - This is most easily accomplished by setting one or more of the AgentMovement properties - - Movement of an avatar is always based on a compass direction, for example AtPos will move the - agent from West to East or forward on the X Axis, AtNeg will of course move agent from - East to West or backward on the X Axis, LeftPos will be South to North or forward on the Y Axis - The Z axis is Up, finer grained control of movements can be done using the Nudge properties - - - - - Camera controls for the agent, mostly a thin wrapper around - CoordinateFrame. This class is only responsible for state - tracking and math, it does not send any packets - - - - - - - The camera is a local frame of reference inside of - the larger grid space. This is where the math happens - - - - - - - - - - - - - - - - Default constructor - - - - Move agent positive along the X axis - - - Move agent negative along the X axis - - - Move agent positive along the Y axis - - - Move agent negative along the Y axis - - - Move agent positive along the Z axis - - - Move agent negative along the Z axis - - - - - - - - - - - - - - - - - - - - - - - - Causes simulator to make agent fly - - - Stop movement - - - Finish animation - - - Stand up from a sit - - - Tells simulator to sit agent on ground - - - Place agent into mouselook mode - - - Nudge agent positive along the X axis - - - Nudge agent negative along the X axis - - - Nudge agent positive along the Y axis - - - Nudge agent negative along the Y axis - - - Nudge agent positive along the Z axis - - - Nudge agent negative along the Z axis - - - - - - - - - Tell simulator to mark agent as away - - - - - - - - - - - - - - - - Returns "always run" value, or changes it by sending a SetAlwaysRunPacket - - - - The current value of the agent control flags - - - Gets or sets the interval in milliseconds at which - AgentUpdate packets are sent to the current simulator. Setting - this to a non-zero value will also enable the packet sending if - it was previously off, and setting it to zero will disable - - - Gets or sets whether AgentUpdate packets are sent to - the current simulator - - - Reset movement controls every time we send an update - - - Agent camera controls - - - Currently only used for hiding your group title - - - Action state of the avatar, which can currently be - typing and editing - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Timer for sending AgentUpdate packets - - - Default constructor - - - - Send an AgentUpdate with the camera set at the current agent - position and pointing towards the heading specified - - Camera rotation in radians - Whether to send the AgentUpdate reliable - or not - - - - Rotates the avatar body and camera toward a target position. - This will also anchor the camera position on the avatar - - Region coordinates to turn toward - - - - Rotates the avatar body and camera toward a target position. - This will also anchor the camera position on the avatar - - Region coordinates to turn toward - whether to send update or not - - - - Send new AgentUpdate packet to update our current camera - position and rotation - - - - - Send new AgentUpdate packet to update our current camera - position and rotation - - Whether to require server acknowledgement - of this packet - - - - Send new AgentUpdate packet to update our current camera - position and rotation - - Whether to require server acknowledgement - of this packet - Simulator to send the update to - - - - Builds an AgentUpdate packet entirely from parameters. This - will not touch the state of Self.Movement or - Self.Movement.Camera in any way - - - - - - - - - - - - - - - - Sends update of Field of Vision vertical angle to the simulator - - Angle in radians - - - - Used to specify movement actions for your agent - - - - Empty flag - - - Move Forward (SL Keybinding: W/Up Arrow) - - - Move Backward (SL Keybinding: S/Down Arrow) - - - Move Left (SL Keybinding: Shift-(A/Left Arrow)) - - - Move Right (SL Keybinding: Shift-(D/Right Arrow)) - - - Not Flying: Jump/Flying: Move Up (SL Keybinding: E) - - - Not Flying: Croutch/Flying: Move Down (SL Keybinding: C) - - - Unused - - - Unused - - - Unused - - - Unused - - - ORed with AGENT_CONTROL_AT_* if the keyboard is being used - - - ORed with AGENT_CONTROL_LEFT_* if the keyboard is being used - - - ORed with AGENT_CONTROL_UP_* if the keyboard is being used - - - Fly - - - - - - Finish our current animation - - - Stand up from the ground or a prim seat - - - Sit on the ground at our current location - - - Whether mouselook is currently enabled - - - Legacy, used if a key was pressed for less than a certain amount of time - - - Legacy, used if a key was pressed for less than a certain amount of time - - - Legacy, used if a key was pressed for less than a certain amount of time - - - Legacy, used if a key was pressed for less than a certain amount of time - - - Legacy, used if a key was pressed for less than a certain amount of time - - - Legacy, used if a key was pressed for less than a certain amount of time - - - - - - - - - Set when the avatar is idled or set to away. Note that the away animation is - activated separately from setting this flag - - - - - - - - - - - - - - - - Class for sending info on the success of the opration - of setting the maturity access level - - - - - New maturity accesss level returned from the sim - - - - - True if setting the new maturity access level has succedded - - - - - Creates new instance of the EventArgs class - - Has setting new maturty access level succeeded - New maturity access level as returned by the simulator - - - - - - - - Get the simulator sending the message - - - Get the message sent - - - Get the audible level of the message - - - Get the type of message sent: whisper, shout, etc - - - Get the source type of the message sender - - - Get the name of the agent or object sending the message - - - Get the ID of the agent or object sending the message - - - Get the ID of the object owner, or the agent ID sending the message - - - Get the position of the agent or object sending the message - - - - Construct a new instance of the ChatEventArgs object - - Sim from which the message originates - The message sent - The audible level of the message - The type of message sent: whisper, shout, etc - The source type of the message sender - The name of the agent or object sending the message - The ID of the agent or object sending the message - The ID of the object owner, or the agent ID sending the message - The position of the agent or object sending the message - - - Contains the data sent when a primitive opens a dialog with this agent - - - Get the dialog message - - - Get the name of the object that sent the dialog request - - - Get the ID of the image to be displayed - - - Get the ID of the primitive sending the dialog - - - Get the first name of the senders owner - - - Get the last name of the senders owner - - - Get the communication channel the dialog was sent on, responses - should also send responses on this same channel - - - Get the string labels containing the options presented in this dialog - - - UUID of the scritped object owner - - - - Construct a new instance of the ScriptDialogEventArgs - - The dialog message - The name of the object that sent the dialog request - The ID of the image to be displayed - The ID of the primitive sending the dialog - The first name of the senders owner - The last name of the senders owner - The communication channel the dialog was sent on - The string labels containing the options presented in this dialog - UUID of the scritped object owner - - - Contains the data sent when a primitive requests debit or other permissions - requesting a YES or NO answer - - - Get the simulator containing the object sending the request - - - Get the ID of the script making the request - - - Get the ID of the primitive containing the script making the request - - - Get the name of the primitive making the request - - - Get the name of the owner of the object making the request - - - Get the permissions being requested - - - - Construct a new instance of the ScriptQuestionEventArgs - - The simulator containing the object sending the request - The ID of the script making the request - The ID of the primitive containing the script making the request - The name of the primitive making the request - The name of the owner of the object making the request - The permissions being requested - - - Contains the data sent when a primitive sends a request - to an agent to open the specified URL - - - Get the name of the object sending the request - - - Get the ID of the object sending the request - - - Get the ID of the owner of the object sending the request - - - True if the object is owned by a group - - - Get the message sent with the request - - - Get the URL the object sent - - - - Construct a new instance of the LoadUrlEventArgs - - The name of the object sending the request - The ID of the object sending the request - The ID of the owner of the object sending the request - True if the object is owned by a group - The message sent with the request - The URL the object sent - - - The date received from an ImprovedInstantMessage - - - Get the InstantMessage object - - - Get the simulator where the InstantMessage origniated - - - - Construct a new instance of the InstantMessageEventArgs object - - the InstantMessage object - the simulator where the InstantMessage origniated - - - Contains the currency balance - - - - Get the currenct balance - - - - - Construct a new BalanceEventArgs object - - The currenct balance - - - Contains the transaction summary when an item is purchased, - money is given, or land is purchased - - - Get the ID of the transaction - - - True of the transaction was successful - - - Get the remaining currency balance - - - Get the meters credited - - - Get the meters comitted - - - Get the description of the transaction - - - Detailed transaction information - - - - Construct a new instance of the MoneyBalanceReplyEventArgs object - - The ID of the transaction - True of the transaction was successful - The current currency balance - The meters credited - The meters comitted - A brief description of the transaction - Transaction info - - - Data sent from the simulator containing information about your agent and active group information - - - Get the agents first name - - - Get the agents last name - - - Get the active group ID of your agent - - - Get the active groups title of your agent - - - Get the combined group powers of your agent - - - Get the active group name of your agent - - - - Construct a new instance of the AgentDataReplyEventArgs object - - The agents first name - The agents last name - The agents active group ID - The group title of the agents active group - The combined group powers the agent has in the active group - The name of the group the agent has currently active - - - Data sent by the simulator to indicate the active/changed animations - applied to your agent - - - Get the dictionary that contains the changed animations - - - - Construct a new instance of the AnimationsChangedEventArgs class - - The dictionary that contains the changed animations - - - - Data sent from a simulator indicating a collision with your agent - - - - Get the Type of collision - - - Get the ID of the agent or object that collided with your agent - - - Get the ID of the agent that was attacked - - - A value indicating the strength of the collision - - - Get the time the collision occurred - - - - Construct a new instance of the MeanCollisionEventArgs class - - The type of collision that occurred - The ID of the agent or object that perpetrated the agression - The ID of the Victim - The strength of the collision - The Time the collision occurred - - - Data sent to your agent when it crosses region boundaries - - - Get the simulator your agent just left - - - Get the simulator your agent is now in - - - - Construct a new instance of the RegionCrossedEventArgs class - - The simulator your agent just left - The simulator your agent is now in - - - Data sent from the simulator when your agent joins a group chat session - - - Get the ID of the group chat session - - - Get the name of the session - - - Get the temporary session ID used for establishing new sessions - - - True if your agent successfully joined the session - - - - Construct a new instance of the GroupChatJoinedEventArgs class - - The ID of the session - The name of the session - A temporary session id used for establishing new sessions - True of your agent successfully joined the session - - - Data sent by the simulator containing urgent messages - - - Get the alert message - - - - Construct a new instance of the AlertMessageEventArgs class - - The alert message - - - Data sent by a script requesting to take or release specified controls to your agent - - - Get the controls the script is attempting to take or release to the agent - - - True if the script is passing controls back to the agent - - - True if the script is requesting controls be released to the script - - - - Construct a new instance of the ScriptControlEventArgs class - - The controls the script is attempting to take or release to the agent - True if the script is passing controls back to the agent - True if the script is requesting controls be released to the script - - - - Data sent from the simulator to an agent to indicate its view limits - - - - Get the collision plane - - - - Construct a new instance of the CameraConstraintEventArgs class - - The collision plane - - - - Data containing script sensor requests which allow an agent to know the specific details - of a primitive sending script sensor requests - - - - Get the ID of the primitive sending the sensor - - - Get the ID of the group associated with the primitive - - - Get the name of the primitive sending the sensor - - - Get the ID of the primitive sending the sensor - - - Get the ID of the owner of the primitive sending the sensor - - - Get the position of the primitive sending the sensor - - - Get the range the primitive specified to scan - - - Get the rotation of the primitive sending the sensor - - - Get the type of sensor the primitive sent - - - Get the velocity of the primitive sending the sensor - - - - Construct a new instance of the ScriptSensorReplyEventArgs - - The ID of the primitive sending the sensor - The ID of the group associated with the primitive - The name of the primitive sending the sensor - The ID of the primitive sending the sensor - The ID of the owner of the primitive sending the sensor - The position of the primitive sending the sensor - The range the primitive specified to scan - The rotation of the primitive sending the sensor - The type of sensor the primitive sent - The velocity of the primitive sending the sensor - - - Contains the response data returned from the simulator in response to a - - - Get the ID of the primitive the agent will be sitting on - - - True if the simulator Autopilot functions were involved - - - Get the camera offset of the agent when seated - - - Get the camera eye offset of the agent when seated - - - True of the agent will be in mouselook mode when seated - - - Get the position of the agent when seated - - - Get the rotation of the agent when seated - - - Construct a new instance of the AvatarSitResponseEventArgs object - - - Data sent when an agent joins a chat session your agent is currently participating in - - - Get the ID of the chat session - - - Get the ID of the agent that joined - - - - Construct a new instance of the ChatSessionMemberAddedEventArgs object - - The ID of the chat session - The ID of the agent joining - - - Data sent when an agent exits a chat session your agent is currently participating in - - - Get the ID of the chat session - - - Get the ID of the agent that left - - - - Construct a new instance of the ChatSessionMemberLeftEventArgs object - - The ID of the chat session - The ID of the Agent that left - - - Event arguments with the result of setting display name operation - - - Status code, 200 indicates settign display name was successful - - - Textual description of the status - - - Details of the newly set display name - - - Default constructor - - - - Throttles the network traffic for various different traffic types. - Access this class through GridClient.Throttle - - - - Maximum bits per second for resending unacknowledged packets - - - Maximum bits per second for LayerData terrain - - - Maximum bits per second for LayerData wind data - - - Maximum bits per second for LayerData clouds - - - Unknown, includes object data - - - Maximum bits per second for textures - - - Maximum bits per second for downloaded assets - - - Maximum bits per second the entire connection, divided up - between invidiual streams using default multipliers - - - - Default constructor, uses a default high total of 1500 KBps (1536000) - - - - - Constructor that decodes an existing AgentThrottle packet in to - individual values - - Reference to the throttle data in an AgentThrottle - packet - Offset position to start reading at in the - throttle data - This is generally not needed in clients as the server will - never send a throttle packet to the client - - - - Send an AgentThrottle packet to the current server using the - current values - - - - - Send an AgentThrottle packet to the specified server using the - current values - - - - - Convert the current throttle values to a byte array that can be put - in an AgentThrottle packet - - Byte array containing all the throttle values - - - - Static pre-defined animations available to all agents - - - - Agent with afraid expression on face - - - Agent aiming a bazooka (right handed) - - - Agent aiming a bow (left handed) - - - Agent aiming a hand gun (right handed) - - - Agent aiming a rifle (right handed) - - - Agent with angry expression on face - - - Agent hunched over (away) - - - Agent doing a backflip - - - Agent laughing while holding belly - - - Agent blowing a kiss - - - Agent with bored expression on face - - - Agent bowing to audience - - - Agent brushing himself/herself off - - - Agent in busy mode - - - Agent clapping hands - - - Agent doing a curtsey bow - - - Agent crouching - - - Agent crouching while walking - - - Agent crying - - - Agent unanimated with arms out (e.g. setting appearance) - - - Agent re-animated after set appearance finished - - - Agent dancing - - - Agent dancing - - - Agent dancing - - - Agent dancing - - - Agent dancing - - - Agent dancing - - - Agent dancing - - - Agent dancing - - - Agent on ground unanimated - - - Agent boozing it up - - - Agent with embarassed expression on face - - - Agent with afraid expression on face - - - Agent with angry expression on face - - - Agent with bored expression on face - - - Agent crying - - - Agent showing disdain (dislike) for something - - - Agent with embarassed expression on face - - - Agent with frowning expression on face - - - Agent with kissy face - - - Agent expressing laughgter - - - Agent with open mouth - - - Agent with repulsed expression on face - - - Agent expressing sadness - - - Agent shrugging shoulders - - - Agent with a smile - - - Agent expressing surprise - - - Agent sticking tongue out - - - Agent with big toothy smile - - - Agent winking - - - Agent expressing worry - - - Agent falling down - - - Agent walking (feminine version) - - - Agent wagging finger (disapproval) - - - I'm not sure I want to know - - - Agent in superman position - - - Agent in superman position - - - Agent greeting another - - - Agent holding bazooka (right handed) - - - Agent holding a bow (left handed) - - - Agent holding a handgun (right handed) - - - Agent holding a rifle (right handed) - - - Agent throwing an object (right handed) - - - Agent in static hover - - - Agent hovering downward - - - Agent hovering upward - - - Agent being impatient - - - Agent jumping - - - Agent jumping with fervor - - - Agent point to lips then rear end - - - Agent landing from jump, finished flight, etc - - - Agent laughing - - - Agent landing from jump, finished flight, etc - - - Agent sitting on a motorcycle - - - - - - Agent moving head side to side - - - Agent moving head side to side with unhappy expression - - - Agent taunting another - - - - - - Agent giving peace sign - - - Agent pointing at self - - - Agent pointing at another - - - Agent preparing for jump (bending knees) - - - Agent punching with left hand - - - Agent punching with right hand - - - Agent acting repulsed - - - Agent trying to be Chuck Norris - - - Rocks, Paper, Scissors 1, 2, 3 - - - Agent with hand flat over other hand - - - Agent with fist over other hand - - - Agent with two fingers spread over other hand - - - Agent running - - - Agent appearing sad - - - Agent saluting - - - Agent shooting bow (left handed) - - - Agent cupping mouth as if shouting - - - Agent shrugging shoulders - - - Agent in sit position - - - Agent in sit position (feminine) - - - Agent in sit position (generic) - - - Agent sitting on ground - - - Agent sitting on ground - - - - - - Agent sleeping on side - - - Agent smoking - - - Agent inhaling smoke - - - - - - Agent taking a picture - - - Agent standing - - - Agent standing up - - - Agent standing - - - Agent standing - - - Agent standing - - - Agent standing - - - Agent stretching - - - Agent in stride (fast walk) - - - Agent surfing - - - Agent acting surprised - - - Agent striking with a sword - - - Agent talking (lips moving) - - - Agent throwing a tantrum - - - Agent throwing an object (right handed) - - - Agent trying on a shirt - - - Agent turning to the left - - - Agent turning to the right - - - Agent typing - - - Agent walking - - - Agent whispering - - - Agent whispering with fingers in mouth - - - Agent winking - - - Agent winking - - - Agent worried - - - Agent nodding yes - - - Agent nodding yes with happy face - - - Agent floating with legs and arms crossed - - - - A dictionary containing all pre-defined animations - - A dictionary containing the pre-defined animations, - where the key is the animations ID, and the value is a string - containing a name to identify the purpose of the animation - - - - Index of TextureEntry slots for avatar appearances - - - - - Bake layers for avatar appearance - - - - - Appearance Flags, introdued with server side baking, currently unused - - - - Mask for multiple attachments - - - Mapping between BakeType and AvatarTextureIndex - - - Maximum number of concurrent downloads for wearable assets and textures - - - Maximum number of concurrent uploads for baked textures - - - Timeout for fetching inventory listings - - - Timeout for fetching a single wearable, or receiving a single packet response - - - Timeout for fetching a single texture - - - Timeout for uploading a single baked texture - - - Number of times to retry bake upload - - - When changing outfit, kick off rebake after - 20 seconds has passed since the last change - - - Total number of wearables for each avatar - - - Total number of baked textures on each avatar - - - Total number of wearables per bake layer - - - Map of what wearables are included in each bake - - - Magic values to finalize the cache check hashes for each - bake - - - Default avatar texture, used to detect when a custom - texture is not set for a face - - - - Contains information about a wearable inventory item - - - - Inventory ItemID of the wearable - - - AssetID of the wearable asset - - - WearableType of the wearable - - - AssetType of the wearable - - - Asset data for the wearable - - - - Data collected from visual params for each wearable - needed for the calculation of the color - - - - - Holds a texture assetID and the data needed to bake this layer into - an outfit texture. Used to keep track of currently worn textures - and baking data - - - - A texture AssetID - - - Asset data for the texture - - - Collection of alpha masks that needs applying - - - Tint that should be applied to the texture - - - Where on avatar does this texture belong - - - The event subscribers. null if no subcribers - - - Raises the AgentWearablesReply event - An AgentWearablesReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Triggered when an AgentWearablesUpdate packet is received, - telling us what our avatar is currently wearing - request. - - - The event subscribers. null if no subcribers - - - Raises the CachedBakesReply event - An AgentCachedBakesReplyEventArgs object containing the - data returned from the data server AgentCachedTextureResponse - - - Thread sync lock object - - - Raised when an AgentCachedTextureResponse packet is - received, giving a list of cached bakes that were found on the - simulator - request. - - - The event subscribers. null if no subcribers - - - Raises the AppearanceSet event - An AppearanceSetEventArgs object indicating if the operatin was successfull - - - Thread sync lock object - - - - Raised when appearance data is sent to the simulator, also indicates - the main appearance thread is finished. - - request. - - - The event subscribers. null if no subcribers - - - Raises the RebakeAvatarRequested event - An RebakeAvatarTexturesEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - - Triggered when the simulator requests the agent rebake its appearance. - - - - - - Returns true if AppearanceManager is busy and trying to set or change appearance will fail - - - - Visual parameters last sent to the sim - - - Textures about this client sent to the sim - - - A cache of wearables currently being worn - - - A cache of textures currently being worn - - - Incrementing serial number for AgentCachedTexture packets - - - Incrementing serial number for AgentSetAppearance packets - - - Indicates if WearablesRequest succeeded - - - Indicates whether or not the appearance thread is currently - running, to prevent multiple appearance threads from running - simultaneously - - - Reference to our agent - - - - Timer used for delaying rebake on changing outfit - - - - - Main appearance thread - - - - - Is server baking complete. It needs doing only once - - - - - Default constructor - - A reference to our agent - - - - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread - - - - - Obsolete method for setting appearance. This function no longer does anything. - Use RequestSetAppearance() to manually start the appearance thread - - Unused parameter - - - - Starts the appearance setting thread - - - - - Starts the appearance setting thread - - True to force rebaking, otherwise false - - - - Check if current region supports server side baking - - True if server side baking support is detected - - - - Ask the server what textures our agent is currently wearing - - - - - Build hashes out of the texture assetIDs for each baking layer to - ask the simulator whether it has cached copies of each baked texture - - - - - Returns the AssetID of the asset that is currently being worn in a - given WearableType slot - - WearableType slot to get the AssetID for - The UUID of the asset being worn in the given slot, or - UUID.Zero if no wearable is attached to the given slot or wearables - have not been downloaded yet - - - - Add a wearable to the current outfit and set appearance - - Wearable to be added to the outfit - - - - Add a wearable to the current outfit and set appearance - - Wearable to be added to the outfit - Should existing item on the same point or of the same type be replaced - - - - Add a list of wearables to the current outfit and set appearance - - List of wearable inventory items to - be added to the outfit - Should existing item on the same point or of the same type be replaced - - - - Add a list of wearables to the current outfit and set appearance - - List of wearable inventory items to - be added to the outfit - Should existing item on the same point or of the same type be replaced - - - - Remove a wearable from the current outfit and set appearance - - Wearable to be removed from the outfit - - - - Removes a list of wearables from the current outfit and set appearance - - List of wearable inventory items to - be removed from the outfit - - - - Replace the current outfit with a list of wearables and set appearance - - List of wearable inventory items that - define a new outfit - - - - Replace the current outfit with a list of wearables and set appearance - - List of wearable inventory items that - define a new outfit - Check if we have all body parts, set this to false only - if you know what you're doing - - - - Checks if an inventory item is currently being worn - - The inventory item to check against the agent - wearables - The WearableType slot that the item is being worn in, - or WearbleType.Invalid if it is not currently being worn - - - - Returns a copy of the agents currently worn wearables - - A copy of the agents currently worn wearables - Avoid calling this function multiple times as it will make - a copy of all of the wearable data each time - - - - Calls either or - depending on the value of - replaceItems - - List of wearable inventory items to add - to the outfit or become a new outfit - True to replace existing items with the - new list of items, false to add these items to the existing outfit - - - - Adds a list of attachments to our agent - - A List containing the attachments to add - If true, tells simulator to remove existing attachment - first - - - - Adds a list of attachments to our agent - - A List containing the attachments to add - If true, tells simulator to remove existing attachment - If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) - first - - - - Attach an item to our agent at a specific attach point - - A to attach - the on the avatar - to attach the item to - - - - Attach an item to our agent at a specific attach point - - A to attach - the on the avatar - If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) - to attach the item to - - - - Attach an item to our agent specifying attachment details - - The of the item to attach - The attachments owner - The name of the attachment - The description of the attahment - The to apply when attached - The of the attachment - The on the agent - to attach the item to - - - - Attach an item to our agent specifying attachment details - - The of the item to attach - The attachments owner - The name of the attachment - The description of the attahment - The to apply when attached - The of the attachment - The on the agent - If true replace existing attachment on this attachment point, otherwise add to it (multi-attachments) - to attach the item to - - - - Detach an item from our agent using an object - - An object - - - - Detach an item from our agent - - The inventory itemID of the item to detach - - - - Inform the sim which wearables are part of our current outfit - - - - - Replaces the Wearables collection with a list of new wearable items - - Wearable items to replace the Wearables collection with - - - - Calculates base color/tint for a specific wearable - based on its params - - All the color info gathered from wearable's VisualParams - passed as list of ColorParamInfo tuples - Base color/tint for the wearable - - - - Blocking method to populate the Wearables dictionary - - True on success, otherwise false - - - - Blocking method to populate the Textures array with cached bakes - - True on success, otherwise false - - - - Populates textures and visual params from a decoded asset - - Wearable to decode - - Populates textures and visual params from a decoded asset - - Wearable to decode - - - - Blocking method to download and parse currently worn wearable assets - - True on success, otherwise false - - - - Get a list of all of the textures that need to be downloaded for a - single bake layer - - Bake layer to get texture AssetIDs for - A list of texture AssetIDs to download - - - - Helper method to lookup the TextureID for a single layer and add it - to a list if it is not already present - - - - - - - Blocking method to download all of the textures needed for baking - the given bake layers - - A list of layers that need baking - No return value is given because the baking will happen - whether or not all textures are successfully downloaded - - - - Blocking method to create and upload baked textures for all of the - missing bakes - - True on success, otherwise false - - - - Blocking method to create and upload a baked texture for a single - bake layer - - Layer to bake - True on success, otherwise false - - - - Blocking method to upload a baked texture - - Five channel JPEG2000 texture data to upload - UUID of the newly created asset on success, otherwise UUID.Zero - - - - Creates a dictionary of visual param values from the downloaded wearables - - A dictionary of visual param indices mapping to visual param - values for our agent that can be fed to the Baker class - - - - Initate server baking process - - True if the server baking was successful - - - - Get the latest version of COF - - Current Outfit Folder (or null if getting the data failed) - - - - Create an AgentSetAppearance packet from Wearables data and the - Textures array and send it - - - - - Converts a WearableType to a bodypart or clothing WearableType - - A WearableType - AssetType.Bodypart or AssetType.Clothing or AssetType.Unknown - - - - Converts a BakeType to the corresponding baked texture slot in AvatarTextureIndex - - A BakeType - The AvatarTextureIndex slot that holds the given BakeType - - - - Gives the layer number that is used for morph mask - - >A BakeType - Which layer number as defined in BakeTypeToTextures is used for morph mask - - - - Converts a BakeType to a list of the texture slots that make up that bake - - A BakeType - A list of texture slots that are inputs for the given bake - - - Contains the Event data returned from the data server from an AgentWearablesRequest - - - Construct a new instance of the AgentWearablesReplyEventArgs class - - - Contains the Event data returned from the data server from an AgentCachedTextureResponse - - - Construct a new instance of the AgentCachedBakesReplyEventArgs class - - - Contains the Event data returned from an AppearanceSetRequest - - - Indicates whether appearance setting was successful - - - - Triggered when appearance data is sent to the sim and - the main appearance thread is done. - Indicates whether appearance setting was successful - - - Contains the Event data returned from the data server from an RebakeAvatarTextures - - - The ID of the Texture Layer to bake - - - - Triggered when the simulator sends a request for this agent to rebake - its appearance - - The ID of the Texture Layer to bake - - - - Class that handles the local asset cache - - - - - Allows setting weather to periodicale prune the cache if it grows too big - Default is enabled, when caching is enabled - - - - - How long (in ms) between cache checks (default is 5 min.) - - - - - Default constructor - - A reference to the GridClient object - - - - Disposes cleanup timer - - - - - Only create timer when needed - - - - - Return bytes read from the local asset cache, null if it does not exist - - UUID of the asset we want to get - Raw bytes of the asset, or null on failure - - - - Returns ImageDownload object of the - image from the local image cache, null if it does not exist - - UUID of the image we want to get - ImageDownload object containing the image, or null on failure - - - - Constructs a file name of the cached asset - - UUID of the asset - String with the file name of the cahced asset - - - - Constructs a file name of the static cached asset - - UUID of the asset - String with the file name of the static cached asset - - - - Saves an asset to the local cache - - UUID of the asset - Raw bytes the asset consists of - Weather the operation was successfull - - - - Get the file name of the asset stored with gived UUID - - UUID of the asset - Null if we don't have that UUID cached on disk, file name if found in the cache folder - - - - Checks if the asset exists in the local cache - - UUID of the asset - True is the asset is stored in the cache, otherwise false - - - - Wipes out entire cache - - - - - Brings cache size to the 90% of the max size - - - - - Asynchronously brings cache size to the 90% of the max size - - - - - Adds up file sizes passes in a FileInfo array - - - - - Checks whether caching is enabled - - - - - Periodically prune the cache - - - - - Nicely formats file sizes - - Byte size we want to output - String with humanly readable file size - - - - Helper class for sorting files by their last accessed time - - - - - - - - - OK - - - Transfer completed - - - - - - - - - Unknown error occurred - - - Equivalent to a 404 error - - - Client does not have permission for that resource - - - Unknown status - - - - - - - - - - - Unknown - - - Virtually all asset transfers use this channel - - - - - - - - - - - Asset from the asset server - - - Inventory item - - - Estate asset, such as an estate covenant - - - - - - - - - - - - - - - - - - When requesting image download, type of the image requested - - - - Normal in-world object texture - - - Avatar texture - - - Server baked avatar texture - - - - Image file format - - - - - - - - - Number of milliseconds passed since the last transfer - packet was received - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Number of milliseconds to wait for a transfer header packet if out of order data was received - - - - Callback used for various asset download requests - - Transfer information - Downloaded asset, null on fail - - - - Callback used upon competition of baked texture upload - - Asset UUID of the newly uploaded baked texture - - - - A callback that fires upon the completition of the RequestMesh call - - Was the download successfull - Resulting mesh or null on problems - - - The event subscribers. null if no subcribers - - - Raises the XferReceived event - A XferReceivedEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds sends - - - The event subscribers. null if no subcribers - - - Raises the AssetUploaded event - A AssetUploadedEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised during upload completes - - - The event subscribers. null if no subcribers - - - Raises the UploadProgress event - A UploadProgressEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised during upload with progres update - - - The event subscribers. null if no subcribers - - - Raises the InitiateDownload event - A InitiateDownloadEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Fired when the simulator sends an InitiateDownloadPacket, used to download terrain .raw files - - - The event subscribers. null if no subcribers - - - Raises the ImageReceiveProgress event - A ImageReceiveProgressEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Fired when a texture is in the process of being downloaded by the TexturePipeline class - - - Texture download cache - - - - Default constructor - - A reference to the GridClient object - - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - The callback to fire when the simulator responds with the asset data - - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - The callback to fire when the simulator responds with the asset data - - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - UUID of the transaction - The callback to fire when the simulator responds with the asset data - - - - Request an asset download - - Asset UUID - Asset type, must be correct for the transfer to succeed - Whether to give this transfer an elevated priority - Source location of the requested asset - UUID of the transaction - The callback to fire when the simulator responds with the asset data - - - - Request an asset download through the almost deprecated Xfer system - - Filename of the asset to request - Whether or not to delete the asset - off the server after it is retrieved - Use large transfer packets or not - UUID of the file to request, if filename is - left empty - Asset type of vFileID, or - AssetType.Unknown if filename is not empty - Sets the FilePath in the request to Cache - (4) if true, otherwise Unknown (0) is used - - - - - - - Use UUID.Zero if you do not have the - asset ID but have all the necessary permissions - The item ID of this asset in the inventory - Use UUID.Zero if you are not requesting an - asset from an object inventory - The owner of this asset - Asset type - Whether to prioritize this asset download or not - - - - - Used to force asset data into the PendingUpload property, ie: for raw terrain uploads - - An AssetUpload object containing the data to upload to the simulator - - - - Request an asset be uploaded to the simulator - - The Object containing the asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired - - - - Request an asset be uploaded to the simulator - - The of the asset being uploaded - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired - - - - Request an asset be uploaded to the simulator - - - Asset type to upload this data as - A byte array containing the encoded asset data - If True, the asset once uploaded will be stored on the simulator - in which the client was connected in addition to being stored on the asset server - The of the transfer, can be used to correlate the upload with - events being fired - - - - Initiate an asset upload - - The ID this asset will have if the - upload succeeds - Asset type to upload this data as - Raw asset data to upload - Whether to store this asset on the local - simulator or the grid-wide asset server - The tranaction id for the upload - The transaction ID of this transfer - - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent. Sending with value -1 combined with priority of 0 cancels an in-progress - transfer. - A bug exists in the Linden Simulator where a -1 will occasionally be sent with a non-zero priority - indicating an off-by-one error. - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request - - Request an image and fire a callback when the request is complete - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - - Request an image and use an inline anonymous method to handle the downloaded texture data - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, delegate(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - Console.WriteLine("Texture {0} ({1} bytes) has been successfully downloaded", - asset.AssetID, - asset.AssetData.Length); - } - } - ); - - Request a texture, decode the texture to a bitmap image and apply it to a imagebox - - Client.Assets.RequestImage(UUID.Parse("c307629f-e3a1-4487-5e88-0d96ac9d4965"), ImageType.Normal, TextureDownloader_OnDownloadFinished); - - private void TextureDownloader_OnDownloadFinished(TextureRequestState state, AssetTexture asset) - { - if(state == TextureRequestState.Finished) - { - ManagedImage imgData; - Image bitmap; - - if (state == TextureRequestState.Finished) - { - OpenJPEG.DecodeToImage(assetTexture.AssetData, out imgData, out bitmap); - picInsignia.Image = bitmap; - } - } - } - - - - - - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - - - - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - - - - Overload: Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request - - - - Cancel a texture request - - The texture assets - - - - Requests download of a mesh asset - - UUID of the mesh asset - Callback when the request completes - - - - Fetach avatar texture on a grid capable of server side baking - - ID of the avatar - ID of the texture - Name of the part of the avatar texture applies to - Callback invoked on operation completion - - - - Lets TexturePipeline class fire the progress event - - The texture ID currently being downloaded - the number of bytes transferred - the total number of bytes expected - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Xfer data - - - Upload data - - - Filename used on the simulator - - - Filename used by the client - - - UUID of the image that is in progress - - - Number of bytes received so far - - - Image size in bytes - - - - Avatar profile flags - - - - - Represents an avatar (other than your own) - - - - - Positive and negative ratings - - - - Positive ratings for Behavior - - - Negative ratings for Behavior - - - Positive ratings for Appearance - - - Negative ratings for Appearance - - - Positive ratings for Building - - - Negative ratings for Building - - - Positive ratings given by this avatar - - - Negative ratings given by this avatar - - - - Avatar properties including about text, profile URL, image IDs and - publishing settings - - - - First Life about text - - - First Life image ID - - - - - - - - - - - - - - - Profile image ID - - - Flags of the profile - - - Web URL for this profile - - - Should this profile be published on the web - - - Avatar Online Status - - - Is this a mature profile - - - - - - - - - - Avatar interests including spoken languages, skills, and "want to" - choices - - - - Languages profile field - - - - - - - - - - - - - - - Groups that this avatar is a member of - - - Positive and negative ratings - - - Avatar properties including about text, profile URL, image IDs and - publishing settings - - - Avatar interests including spoken languages, skills, and "want to" - choices - - - Movement control flags for avatars. Typically not set or used by - clients. To move your avatar, use Client.Self.Movement instead - - - - Contains the visual parameters describing the deformation of the avatar - - - - - Appearance version. Value greater than 0 indicates using server side baking - - - - - Version of the Current Outfit Folder that the appearance is based on - - - - - Appearance flags. Introduced with server side baking, currently unused. - - - - - List of current avatar animations - - - - First name - - - Last name - - - Full name - - - Active group - - - - Default constructor - - - - Information about agents display name - - - Agent UUID - - - Username - - - Display name - - - First name (legacy) - - - Last name (legacy) - - - Full name (legacy) - - - Is display name default display name - - - Cache display name until - - - Last updated timestamp - - - - Creates AgentDisplayName object from OSD - - Incoming OSD data - AgentDisplayName object - - - - Return object as OSD map - - OSD containing agent's display name data - - - - Holds group information for Avatars such as those you might find in a profile - - - - true of Avatar accepts group notices - - - Groups Key - - - Texture Key for groups insignia - - - Name of the group - - - Powers avatar has in the group - - - Avatars Currently selected title - - - true of Avatar has chosen to list this in their profile - - - - Contains an animation currently being played by an agent - - - - The ID of the animation asset - - - A number to indicate start order of currently playing animations - On Linden Grids this number is unique per region, with OpenSim it is per client - - - - - - - Holds group information on an individual profile pick - - - - - Retrieve friend status notifications, and retrieve avatar names and - profiles - - - - The event subscribers, null of no subscribers - - - Raises the AvatarAnimation Event - An AvatarAnimationEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - an agents animation playlist - - - The event subscribers, null of no subscribers - - - Raises the AvatarAppearance Event - A AvatarAppearanceEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the appearance information for an agent - - - The event subscribers, null of no subscribers - - - Raises the UUIDNameReply Event - A UUIDNameReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - agent names/id values - - - The event subscribers, null of no subscribers - - - Raises the AvatarInterestsReply Event - A AvatarInterestsReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the interests listed in an agents profile - - - The event subscribers, null of no subscribers - - - Raises the AvatarPropertiesReply Event - A AvatarPropertiesReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - profile property information for an agent - - - The event subscribers, null of no subscribers - - - Raises the AvatarGroupsReply Event - A AvatarGroupsReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the group membership an agent is a member of - - - The event subscribers, null of no subscribers - - - Raises the AvatarPickerReply Event - A AvatarPickerReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - name/id pair - - - The event subscribers, null of no subscribers - - - Raises the ViewerEffectPointAt Event - A ViewerEffectPointAtEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the objects and effect when an agent is pointing at - - - The event subscribers, null of no subscribers - - - Raises the ViewerEffectLookAt Event - A ViewerEffectLookAtEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the objects and effect when an agent is looking at - - - The event subscribers, null of no subscribers - - - Raises the ViewerEffect Event - A ViewerEffectEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - an agents viewer effect information - - - The event subscribers, null of no subscribers - - - Raises the AvatarPicksReply Event - A AvatarPicksReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the top picks from an agents profile - - - The event subscribers, null of no subscribers - - - Raises the PickInfoReply Event - A PickInfoReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the Pick details - - - The event subscribers, null of no subscribers - - - Raises the AvatarClassifiedReply Event - A AvatarClassifiedReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the classified ads an agent has placed - - - The event subscribers, null of no subscribers - - - Raises the ClassifiedInfoReply Event - A ClassifiedInfoReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the details of a classified ad - - - The event subscribers, null of no subscribers - - - Raises the DisplayNameUpdate Event - A DisplayNameUpdateEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - the details of display name change - - - - Callback giving results when fetching display names - - If the request was successful - Array of display names - Array of UUIDs that could not be fetched - - - - Represents other avatars - - - - - Tracks the specified avatar on your map - Avatar ID to track - - - - Request a single avatar name - - The avatar key to retrieve a name for - - - - Request a list of avatar names - - The avatar keys to retrieve names for - - - - Check if Display Names functionality is available - - True if Display name functionality is available - - - - Request retrieval of display names (max 90 names per request) - - List of UUIDs to lookup - Callback to report result of the operation - - - - Start a request for Avatar Properties - - - - - - Search for an avatar (first name, last name) - - The name to search for - An ID to associate with this query - - - - Start a request for Avatar Picks - - UUID of the avatar - - - - Start a request for Avatar Classifieds - - UUID of the avatar - - - - Start a request for details of a specific profile pick - - UUID of the avatar - UUID of the profile pick - - - - Start a request for details of a specific profile classified - - UUID of the avatar - UUID of the profile classified - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - EQ Message fired when someone nearby changes their display name - - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - - - Crossed region handler for message that comes across the EventQueue. Sent to an agent - when the agent crosses a sim border into a new region. - - The message key - the IMessage object containing the deserialized data sent from the simulator - The which originated the packet - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Provides data for the event - The event occurs when the simulator sends - the animation playlist for an agent - - The following code example uses the and - properties to display the animation playlist of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAnimation += Avatars_AvatarAnimation; - - private void Avatars_AvatarAnimation(object sender, AvatarAnimationEventArgs e) - { - // create a dictionary of "known" animations from the Animations class using System.Reflection - Dictionary<UUID, string> systemAnimations = new Dictionary<UUID, string>(); - Type type = typeof(Animations); - System.Reflection.FieldInfo[] fields = type.GetFields(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Static); - foreach (System.Reflection.FieldInfo field in fields) - { - systemAnimations.Add((UUID)field.GetValue(type), field.Name); - } - - // find out which animations being played are known animations and which are assets - foreach (Animation animation in e.Animations) - { - if (systemAnimations.ContainsKey(animation.AnimationID)) - { - Console.WriteLine("{0} is playing {1} ({2}) sequence {3}", e.AvatarID, - systemAnimations[animation.AnimationID], animation.AnimationSequence); - } - else - { - Console.WriteLine("{0} is playing {1} (Asset) sequence {2}", e.AvatarID, - animation.AnimationID, animation.AnimationSequence); - } - } - } - - - - - Get the ID of the agent - - - Get the list of animations to start - - - - Construct a new instance of the AvatarAnimationEventArgs class - - The ID of the agent - The list of animations to start - - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - - - - - Get the Simulator this request is from of the agent - - - Get the ID of the agent - - - true if the agent is a trial account - - - Get the default agent texture - - - Get the agents appearance layer textures - - - Get the for the agent - - - Version of the appearance system used. - Value greater than 0 indicates that server side baking is used - - - Version of the Current Outfit Folder the appearance is based on - - - Appearance flags, introduced with server side baking, currently unused - - - - Construct a new instance of the AvatarAppearanceEventArgs class - - The simulator request was from - The ID of the agent - true of the agent is a trial account - The default agent texture - The agents appearance layer textures - The for the agent - - - Represents the interests from the profile of an agent - - - Get the ID of the agent - - - The properties of an agent - - - Get the ID of the agent - - - Get the ID of the agent - - - Get the ID of the agent - - - Get the ID of the avatar - - - - Event args class for display name notification messages - - - - - Wrapper around a byte array that allows bit to be packed and unpacked - one at a time or by a variable amount. Useful for very tightly packed - data like LayerData packets - - - - - - - - - - - - - - Default constructor, initialize the bit packer / bit unpacker - with a byte array and starting position - - Byte array to pack bits in to or unpack from - Starting position in the byte array - - - - Pack a floating point value in to the data - - Floating point value to pack - - - - Pack part or all of an integer in to the data - - Integer containing the data to pack - Number of bits of the integer to pack - - - - Pack part or all of an unsigned integer in to the data - - Unsigned integer containing the data to pack - Number of bits of the integer to pack - - - - Pack a single bit in to the data - - Bit to pack - - - - - - - - - - - - - - - - - - - - - - - - - Unpacking a floating point value from the data - - Unpacked floating point value - - - - Unpack a variable number of bits from the data in to integer format - - Number of bits to unpack - An integer containing the unpacked bits - This function is only useful up to 32 bits - - - - Unpack a variable number of bits from the data in to unsigned - integer format - - Number of bits to unpack - An unsigned integer containing the unpacked bits - This function is only useful up to 32 bits - - - - Unpack a 16-bit signed integer - - 16-bit signed integer - - - - Unpack a 16-bit unsigned integer - - 16-bit unsigned integer - - - - Unpack a 32-bit signed integer - - 32-bit signed integer - - - - Unpack a 32-bit unsigned integer - - 32-bit unsigned integer - - - - Reads in a byte array of an Animation Asset created by the SecondLife(tm) client. - - - - - Rotation Keyframe count (used internally) - - - - - Position Keyframe count (used internally) - - - - - Animation Priority - - - - - The animation length in seconds. - - - - - Expression set in the client. Null if [None] is selected - - - - - The time in seconds to start the animation - - - - - The time in seconds to end the animation - - - - - Loop the animation - - - - - Meta data. Ease in Seconds. - - - - - Meta data. Ease out seconds. - - - - - Meta Data for the Hand Pose - - - - - Number of joints defined in the animation - - - - - Contains an array of joints - - - - - Searialize an animation asset into it's joints/keyframes/meta data - - - - - - Variable length strings seem to be null terminated in the animation asset.. but.. - use with caution, home grown. - advances the index. - - The animation asset byte array - The offset to start reading - a string - - - - Read in a Joint from an animation asset byte array - Variable length Joint fields, yay! - Advances the index - - animation asset byte array - Byte Offset of the start of the joint - The Joint data serialized into the binBVHJoint structure - - - - Read Keyframes of a certain type - advance i - - Animation Byte array - Offset in the Byte Array. Will be advanced - Number of Keyframes - Scaling Min to pass to the Uint16ToFloat method - Scaling Max to pass to the Uint16ToFloat method - - - - - Determines whether the specified is equal to the current . - - - true if the specified is equal to the current ; otherwise, false. - - The to compare with the current . - The parameter is null. - 2 - - - - Serves as a hash function for a particular type. - - - A hash code for the current . - - 2 - - - - A Joint and it's associated meta data and keyframes - - - - - Indicates whether this instance and a specified object are equal. - - - true if and this instance are the same type and represent the same value; otherwise, false. - - Another object to compare to. - 2 - - - - Returns the hash code for this instance. - - - A 32-bit signed integer that is the hash code for this instance. - - 2 - - - - Name of the Joint. Matches the avatar_skeleton.xml in client distros - - - - - Joint Animation Override? Was the same as the Priority in testing.. - - - - - Array of Rotation Keyframes in order from earliest to latest - - - - - Array of Position Keyframes in order from earliest to latest - This seems to only be for the Pelvis? - - - - - Custom application data that can be attached to a joint - - - - - A Joint Keyframe. This is either a position or a rotation. - - - - - Either a Vector3 position or a Vector3 Euler rotation - - - - - Poses set in the animation metadata for the hands. - - - - - Capabilities is the name of the bi-directional HTTP REST protocol - used to communicate non real-time transactions such as teleporting or - group messaging - - - - - Triggered when an event is received via the EventQueueGet - capability - - Event name - Decoded event data - The simulator that generated the event - - - Reference to the simulator this system is connected to - - - Capabilities URI this system was initialized with - - - Whether the capabilities event queue is connected and - listening for incoming events - - - - Default constructor - - - - - - - Request the URI of a named capability - - Name of the capability to request - The URI of the requested capability, or String.Empty if - the capability does not exist - - - - Process any incoming events, check to see if we have a message created for the event, - - - - - - - Attempts to convert an LLSD structure to a known Packet type - - Event name, this must match an actual - packet name for a Packet to be successfully built - LLSD to convert to a Packet - A Packet on success, otherwise null - - - - A custom decoder callback - - The key of the object - the data to decode - A string represending the fieldData - - - - Add a custom decoder callback - - The key of the field to decode - The custom decode handler - - - - Remove a custom decoder callback - - The key of the field to decode - The custom decode handler - - - - Creates a formatted string containing the values of a Packet - - The Packet - A formatted string of values of the nested items in the Packet object - - - - Decode an IMessage object into a beautifully formatted string - - The IMessage object - Recursion level (used for indenting) - A formatted string containing the names and values of the source object - - - - Thrown when a packet could not be successfully deserialized - - - - - Default constructor - - - - - Constructor that takes an additional error message - - An error message to attach to this exception - - - - The header of a message template packet. Holds packet flags, sequence - number, packet ID, and any ACKs that will be appended at the end of - the packet - - - - - Convert the AckList to a byte array, used for packet serializing - - Reference to the target byte array - Beginning position to start writing to in the byte - array, will be updated with the ending position of the ACK list - - - - - - - - - - - - - - - - - - - - - A block of data in a packet. Packets are composed of one or more blocks, - each block containing one or more fields - - - - Current length of the data in this packet - - - - Create a block from a byte array - - Byte array containing the serialized block - Starting position of the block in the byte array. - This will point to the data after the end of the block when the - call returns - - - - Serialize this block into a byte array - - Byte array to serialize this block into - Starting position in the byte array to serialize to. - This will point to the position directly after the end of the - serialized block when the call returns - - - A generic value, not an actual packet type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Origin position of this coordinate frame - - - X axis of this coordinate frame, or Forward/At in grid terms - - - Y axis of this coordinate frame, or Left in grid terms - - - Z axis of this coordinate frame, or Up in grid terms - - - - - - Looking direction, must be a normalized vector - Up direction, must be a normalized vector - - - - Align the coordinate frame X and Y axis with a given rotation - around the Z axis in radians - - Absolute rotation around the Z axis in - radians - - - - Access to the data server which allows searching for land, events, people, etc - - - - Classified Ad categories - - - Classified is listed in the Any category - - - Classified is shopping related - - - Classified is - - - - - - - - - - - - - - - - - - - - - - - - Event Categories - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Query Flags used in many of the DirectoryManager methods to specify which query to execute and how to return the results. - - Flags can be combined using the | (pipe) character, not all flags are available in all queries - - - - Query the People database - - - - - - - - - Query the Groups database - - - Query the Events database - - - Query the land holdings database for land owned by the currently connected agent - - - - - - Query the land holdings database for land which is owned by a Group - - - Specifies the query should pre sort the results based upon traffic - when searching the Places database - - - - - - - - - - - - - - - Specifies the query should pre sort the results in an ascending order when searching the land sales database. - This flag is only used when searching the land sales database - - - Specifies the query should pre sort the results using the SalePrice field when searching the land sales database. - This flag is only used when searching the land sales database - - - Specifies the query should pre sort the results by calculating the average price/sq.m (SalePrice / Area) when searching the land sales database. - This flag is only used when searching the land sales database - - - Specifies the query should pre sort the results using the ParcelSize field when searching the land sales database. - This flag is only used when searching the land sales database - - - Specifies the query should pre sort the results using the Name field when searching the land sales database. - This flag is only used when searching the land sales database - - - When set, only parcels less than the specified Price will be included when searching the land sales database. - This flag is only used when searching the land sales database - - - When set, only parcels greater than the specified Size will be included when searching the land sales database. - This flag is only used when searching the land sales database - - - - - - - - - Include PG land in results. This flag is used when searching both the Groups, Events and Land sales databases - - - Include Mature land in results. This flag is used when searching both the Groups, Events and Land sales databases - - - Include Adult land in results. This flag is used when searching both the Groups, Events and Land sales databases - - - - - - - Land types to search dataserver for - - - - Search Auction, Mainland and Estate - - - Land which is currently up for auction - - - Parcels which are on the mainland (Linden owned) continents - - - Parcels which are on privately owned simulators - - - - The content rating of the event - - - - Event is PG - - - Event is Mature - - - Event is Adult - - - - Classified Ad Options - - There appear to be two formats the flags are packed in. - This set of flags is for the newer style - - - - - - - - - - - - - - - - - - - Classified ad query options - - - - Include all ads in results - - - Include PG ads in results - - - Include Mature ads in results - - - Include Adult ads in results - - - - The For Sale flag in PlacesReplyData - - - - Parcel is not listed for sale - - - Parcel is For Sale - - - - A classified ad on the grid - - - - UUID for this ad, useful for looking up detailed - information about it - - - The title of this classified ad - - - Flags that show certain options applied to the classified - - - Creation date of the ad - - - Expiration date of the ad - - - Price that was paid for this ad - - - Print the struct data as a string - A string containing the field name, and field value - - - - A parcel retrieved from the dataserver such as results from the - "For-Sale" listings or "Places" Search - - - - The unique dataserver parcel ID - This id is used to obtain additional information from the entry - by using the method - - - A string containing the name of the parcel - - - The size of the parcel - This field is not returned for Places searches - - - The price of the parcel - This field is not returned for Places searches - - - If True, this parcel is flagged to be auctioned - - - If true, this parcel is currently set for sale - - - Parcel traffic - - - Print the struct data as a string - A string containing the field name, and field value - - - - An Avatar returned from the dataserver - - - - Online status of agent - This field appears to be obsolete and always returns false - - - The agents first name - - - The agents last name - - - The agents - - - Print the struct data as a string - A string containing the field name, and field value - - - - Response to a "Groups" Search - - - - The Group ID - - - The name of the group - - - The current number of members - - - Print the struct data as a string - A string containing the field name, and field value - - - - Parcel information returned from a request - - Represents one of the following: - A parcel of land on the grid that has its Show In Search flag set - A parcel of land owned by the agent making the request - A parcel of land owned by a group the agent making the request is a member of - - - In a request for Group Land, the First record will contain an empty record - - Note: This is not the same as searching the land for sale data source - - - - The ID of the Agent of Group that owns the parcel - - - The name - - - The description - - - The Size of the parcel - - - The billable Size of the parcel, for mainland - parcels this will match the ActualArea field. For Group owned land this will be 10 percent smaller - than the ActualArea. For Estate land this will always be 0 - - - Indicates the ForSale status of the parcel - - - The Gridwide X position - - - The Gridwide Y position - - - The Z position of the parcel, or 0 if no landing point set - - - The name of the Region the parcel is located in - - - The Asset ID of the parcels Snapshot texture - - - The calculated visitor traffic - - - The billing product SKU - Known values are: - - 023Mainland / Full Region - 024Estate / Full Region - 027Estate / Openspace - 029Estate / Homestead - 129Mainland / Homestead (Linden Owned) - - - - - No longer used, will always be 0 - - - Get a SL URL for the parcel - A string, containing a standard SLURL - - - Print the struct data as a string - A string containing the field name, and field value - - - - An "Event" Listing summary - - - - The ID of the event creator - - - The name of the event - - - The events ID - - - A string containing the short date/time the event will begin - - - The event start time in Unixtime (seconds since epoch) - - - The events maturity rating - - - Print the struct data as a string - A string containing the field name, and field value - - - - The details of an "Event" - - - - The events ID - - - The ID of the event creator - - - The name of the event - - - The category - - - The events description - - - The short date/time the event will begin - - - The event start time in Unixtime (seconds since epoch) UTC adjusted - - - The length of the event in minutes - - - 0 if no cover charge applies - - - The cover charge amount in L$ if applicable - - - The name of the region where the event is being held - - - The gridwide location of the event - - - The maturity rating - - - Get a SL URL for the parcel where the event is hosted - A string, containing a standard SLURL - - - Print the struct data as a string - A string containing the field name, and field value - - - The event subscribers. null if no subcribers - - - Raises the EventInfoReply event - An EventInfoReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the DirEventsReply event - An DirEventsReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the PlacesReply event - A PlacesReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the DirPlacesReply event - A DirPlacesReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the DirClassifiedsReply event - A DirClassifiedsReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the DirGroupsReply event - A DirGroupsReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the DirPeopleReply event - A DirPeopleReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the DirLandReply event - A DirLandReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - - Constructs a new instance of the DirectoryManager class - - An instance of GridClient - - - - Query the data server for a list of classified ads containing the specified string. - Defaults to searching for classified placed in any category, and includes PG, Adult and Mature - results. - - Responses are sent 16 per response packet, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - - The event is raised when a response is received from the simulator - - A string containing a list of keywords to search for - A UUID to correlate the results when the event is raised - - - - Query the data server for a list of classified ads which contain specified keywords (Overload) - - The event is raised when a response is received from the simulator - - A string containing a list of keywords to search for - The category to search - A set of flags which can be ORed to modify query options - such as classified maturity rating. - A UUID to correlate the results when the event is raised - - Search classified ads containing the key words "foo" and "bar" in the "Any" category that are either PG or Mature - - UUID searchID = StartClassifiedSearch("foo bar", ClassifiedCategories.Any, ClassifiedQueryFlags.PG | ClassifiedQueryFlags.Mature); - - - - Responses are sent 16 at a time, there is no way to know how many results a query reply will contain however assuming - the reply packets arrived ordered, a response with less than 16 entries would indicate all results have been received - - - - - Starts search for places (Overloaded) - - The event is raised when a response is received from the simulator - - Search text - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised - - - - Queries the dataserver for parcels of land which are flagged to be shown in search - - The event is raised when a response is received from the simulator - - A string containing a list of keywords to search for separated by a space character - A set of flags which can be ORed to modify query options - such as classified maturity rating. - The category to search - Each request is limited to 100 places - being returned. To get the first 100 result entries of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - A UUID to correlate the results when the event is raised - - Search places containing the key words "foo" and "bar" in the "Any" category that are either PG or Adult - - UUID searchID = StartDirPlacesSearch("foo bar", DirFindFlags.DwellSort | DirFindFlags.IncludePG | DirFindFlags.IncludeAdult, ParcelCategory.Any, 0); - - - - Additional information on the results can be obtained by using the ParcelManager.InfoRequest method - - - - - Starts a search for land sales using the directory - - The event is raised when a response is received from the simulator - - What type of land to search for. Auction, - estate, mainland, "first land", etc - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. - - - - Starts a search for land sales using the directory - - The event is raised when a response is received from the simulator - - What type of land to search for. Auction, - estate, mainland, "first land", etc - Maximum price to search for - Maximum area to search for - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 1, 200-299 use 2, etc. - The OnDirLandReply event handler must be registered before - calling this function. There is no way to determine how many - results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each query. - - - - Send a request to the data server for land sales listings - - - Flags sent to specify query options - - Available flags: - Specify the parcel rating with one or more of the following: - IncludePG IncludeMature IncludeAdult - - Specify the field to pre sort the results with ONLY ONE of the following: - PerMeterSort NameSort AreaSort PricesSort - - Specify the order the results are returned in, if not specified the results are pre sorted in a Descending Order - SortAsc - - Specify additional filters to limit the results with one or both of the following: - LimitByPrice LimitByArea - - Flags can be combined by separating them with the | (pipe) character - - Additional details can be found in - - What type of land to search for. Auction, - Estate or Mainland - Maximum price to search for when the - DirFindFlags.LimitByPrice flag is specified in findFlags - Maximum area to search for when the - DirFindFlags.LimitByArea flag is specified in findFlags - Each request is limited to 100 parcels - being returned. To get the first 100 parcels of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - The event will be raised with the response from the simulator - - There is no way to determine how many results will be returned, or how many times the callback will be - fired other than you won't get more than 100 total parcels from - each reply. - - Any land set for sale to either anybody or specific to the connected agent will be included in the - results if the land is included in the query - - - // request all mainland, any maturity rating that is larger than 512 sq.m - StartLandSearch(DirFindFlags.SortAsc | DirFindFlags.PerMeterSort | DirFindFlags.LimitByArea | DirFindFlags.IncludePG | DirFindFlags.IncludeMature | DirFindFlags.IncludeAdult, SearchTypeFlags.Mainland, 0, 512, 0); - - - - - Search for Groups - - The name or portion of the name of the group you wish to search for - Start from the match number - - - - - Search for Groups - - The name or portion of the name of the group you wish to search for - Start from the match number - Search flags - - - - - Search the People directory for other avatars - - The name or portion of the name of the avatar you wish to search for - - - - - - Search Places for parcels of land you personally own - - - - - Searches Places for land owned by the specified group - - ID of the group you want to recieve land list for (You must be a member of the group) - Transaction (Query) ID which can be associated with results from your request. - - - - Search the Places directory for parcels that are listed in search and contain the specified keywords - - A string containing the keywords to search for - Transaction (Query) ID which can be associated with results from your request. - - - - Search Places - All Options - - One of the Values from the DirFindFlags struct, ie: AgentOwned, GroupOwned, etc. - One of the values from the SearchCategory Struct, ie: Any, Linden, Newcomer - A string containing a list of keywords to search for separated by a space character - String Simulator Name to search in - LLUID of group you want to recieve results for - Transaction (Query) ID which can be associated with results from your request. - Transaction (Query) ID which can be associated with results from your request. - - - - Search All Events with specifid searchText in all categories, includes PG, Mature and Adult - - A string containing a list of keywords to search for separated by a space character - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - UUID of query to correlate results in callback. - - - - Search Events - - A string containing a list of keywords to search for separated by a space character - One or more of the following flags: DateEvents, IncludePG, IncludeMature, IncludeAdult - from the Enum - - Multiple flags can be combined by separating the flags with the | (pipe) character - "u" for in-progress and upcoming events, -or- number of days since/until event is scheduled - For example "0" = Today, "1" = tomorrow, "2" = following day, "-1" = yesterday, etc. - Each request is limited to 100 entries - being returned. To get the first group of entries of a request use 0, - from 100-199 use 100, 200-299 use 200, etc. - EventCategory event is listed under. - UUID of query to correlate results in callback. - - - Requests Event Details - ID of Event returned from the method - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming event message - The Unique Capabilities Key - The event message containing the data - The simulator the message originated from - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Contains the Event data returned from the data server from an EventInfoRequest - - - - A single EventInfo object containing the details of an event - - - - Construct a new instance of the EventInfoReplyEventArgs class - A single EventInfo object containing the details of an event - - - Contains the "Event" detail data returned from the data server - - - The ID returned by - - - A list of "Events" returned by the data server - - - Construct a new instance of the DirEventsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Events" returned by the search query - - - Contains the "Event" list data returned from the data server - - - The ID returned by - - - A list of "Places" returned by the data server - - - Construct a new instance of PlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing the "Places" returned by the data server query - - - Contains the places data returned from the data server - - - The ID returned by - - - A list containing Places data returned by the data server - - - Construct a new instance of the DirPlacesReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list containing land data returned by the data server - - - Contains the classified data returned from the data server - - - A list containing Classified Ads returned by the data server - - - Construct a new instance of the DirClassifiedsReplyEventArgs class - A list of classified ad data returned from the data server - - - Contains the group data returned from the data server - - - The ID returned by - - - A list containing Groups data returned by the data server - - - Construct a new instance of the DirGroupsReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of groups data returned by the data server - - - Contains the people data returned from the data server - - - The ID returned by - - - A list containing People data returned by the data server - - - Construct a new instance of the DirPeopleReplyEventArgs class - The ID of the query returned by the data server. - This will correlate to the ID returned by the method - A list of people data returned by the data server - - - Contains the land sales data returned from the data server - - - A list containing land forsale data returned by the data server - - - Construct a new instance of the DirLandReplyEventArgs class - A list of parcels for sale returned by the data server - - - - Represends individual HTTP Download request - - - - URI of the item to fetch - - - Timout specified in milliseconds - - - Download progress callback - - - Download completed callback - - - Accept the following content type - - - How many times will this request be retried - - - Current fetch attempt - - - Default constructor - - - Constructor - - - - Manages async HTTP downloads with a limit on maximum - concurrent downloads - - - - Maximum number of parallel downloads from a single endpoint - - - Client certificate - - - Default constructor - - - Cleanup method - - - Setup http download request - - - Check the queue for pending work - - - Enqueue a new HTTP download - - - Describes tasks returned in LandStatReply - - - - Estate level administration and utilities - - - - Textures for each of the four terrain height levels - - - Upper/lower texture boundaries for each corner of the sim - - - - Constructor for EstateTools class - - - - - Used in the ReportType field of a LandStatRequest - - - Used by EstateOwnerMessage packets - - - Used by EstateOwnerMessage packets - - - - - - - - No flags set - - - Only return targets scripted objects - - - Only return targets objects if on others land - - - Returns target's scripted objects and objects on other parcels - - - Ground texture settings for each corner of the region - - - Used by GroundTextureHeightSettings - - - The high and low texture thresholds for each corner of the sim - - - The event subscribers. null if no subcribers - - - Raises the TopCollidersReply event - A TopCollidersReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the TopScriptsReply event - A TopScriptsReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the EstateUsersReply event - A EstateUsersReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the EstateGroupsReply event - A EstateGroupsReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the EstateManagersReply event - A EstateManagersReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the EstateBansReply event - A EstateBansReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the EstateCovenantReply event - A EstateCovenantReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - The event subscribers. null if no subcribers - - - Raises the EstateUpdateInfoReply event - A EstateUpdateInfoReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the data server responds to a request. - - - - Requests estate information such as top scripts and colliders - - - - - - - - Requests estate settings, including estate manager and access/ban lists - - - Requests the "Top Scripts" list for the current region - - - Requests the "Top Colliders" list for the current region - - - - Set several estate specific configuration variables - - The Height of the waterlevel over the entire estate. Defaults to 20 - The maximum height change allowed above the baked terrain. Defaults to 4 - The minimum height change allowed below the baked terrain. Defaults to -4 - true to use - if True forces the sun position to the position in SunPosition - The current position of the sun on the estate, or when FixedSun is true the static position - the sun will remain. 6.0 = Sunrise, 30.0 = Sunset - - - - Request return of objects owned by specified avatar - - The Agents owning the primitives to return - specify the coverage and type of objects to be included in the return - true to perform return on entire estate - - - - - - - - - Used for setting and retrieving various estate panel settings - - EstateOwnerMessage Method field - List of parameters to include - - - - Kick an avatar from an estate - - Key of Agent to remove - - - - Ban an avatar from an estate - Key of Agent to remove - Ban user from this estate and all others owned by the estate owner - - - Unban an avatar from an estate - Key of Agent to remove - /// Unban user from this estate and all others owned by the estate owner - - - - Send a message dialog to everyone in an entire estate - - Message to send all users in the estate - - - - Send a message dialog to everyone in a simulator - - Message to send all users in the simulator - - - - Send an avatar back to their home location - - Key of avatar to send home - - - - Begin the region restart process - - - - - Cancels a region restart - - - - Estate panel "Region" tab settings - - - Estate panel "Debug" tab settings - - - Used for setting the region's terrain textures for its four height levels - - - - - - - Used for setting sim terrain texture heights - - - Requests the estate covenant - - - - Upload a terrain RAW file - - A byte array containing the encoded terrain data - The name of the file being uploaded - The Id of the transfer request - - - - Teleports all users home in current Estate - - - - - Remove estate manager - Key of Agent to Remove - removes manager to this estate and all others owned by the estate owner - - - - Add estate manager - Key of Agent to Add - Add agent as manager to this estate and all others owned by the estate owner - - - - Add's an agent to the estate Allowed list - Key of Agent to Add - Add agent as an allowed reisdent to All estates if true - - - - Removes an agent from the estate Allowed list - Key of Agent to Remove - Removes agent as an allowed reisdent from All estates if true - - - - - Add's a group to the estate Allowed list - Key of Group to Add - Add Group as an allowed group to All estates if true - - - - - Removes a group from the estate Allowed list - Key of Group to Remove - Removes Group as an allowed Group from All estates if true - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Raised on LandStatReply when the report type is for "top colliders" - - - - The number of returned items in LandStatReply - - - - - A Dictionary of Object UUIDs to tasks returned in LandStatReply - - - - Construct a new instance of the TopCollidersReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply - - - Raised on LandStatReply when the report type is for "top Scripts" - - - - The number of scripts returned in LandStatReply - - - - - A Dictionary of Object UUIDs to tasks returned in LandStatReply - - - - Construct a new instance of the TopScriptsReplyEventArgs class - The number of returned items in LandStatReply - Dictionary of Object UUIDs to tasks returned in LandStatReply - - - Returned, along with other info, upon a successful .RequestInfo() - - - - The identifier of the estate - - - - - The number of returned itmes - - - - - List of UUIDs of Banned Users - - - - Construct a new instance of the EstateBansReplyEventArgs class - The estate's identifier on the grid - The number of returned items in LandStatReply - User UUIDs banned - - - Returned, along with other info, upon a successful .RequestInfo() - - - - The identifier of the estate - - - - - The number of returned items - - - - - List of UUIDs of Allowed Users - - - - Construct a new instance of the EstateUsersReplyEventArgs class - The estate's identifier on the grid - The number of users - Allowed users UUIDs - - - Returned, along with other info, upon a successful .RequestInfo() - - - - The identifier of the estate - - - - - The number of returned items - - - - - List of UUIDs of Allowed Groups - - - - Construct a new instance of the EstateGroupsReplyEventArgs class - The estate's identifier on the grid - The number of Groups - Allowed Groups UUIDs - - - Returned, along with other info, upon a successful .RequestInfo() - - - - The identifier of the estate - - - - - The number of returned items - - - - - List of UUIDs of the Estate's Managers - - - - Construct a new instance of the EstateManagersReplyEventArgs class - The estate's identifier on the grid - The number of Managers - Managers UUIDs - - - Returned, along with other info, upon a successful .RequestInfo() - - - - The Covenant - - - - - The timestamp - - - - - The Estate name - - - - - The Estate Owner's ID (can be a GroupID) - - - - Construct a new instance of the EstateCovenantReplyEventArgs class - The Covenant ID - The timestamp - The estate's name - The Estate Owner's ID (can be a GroupID) - - - Returned, along with other info, upon a successful .RequestInfo() - - - - The estate's name - - - - - The Estate Owner's ID (can be a GroupID) - - - - - The identifier of the estate on the grid - - - - - - - Construct a new instance of the EstateUpdateInfoReplyEventArgs class - The estate's name - The Estate Owners ID (can be a GroupID) - The estate's identifier on the grid - - - - - Registers, unregisters, and fires events generated by incoming packets - - - - - Object that is passed to worker threads in the ThreadPool for - firing packet callbacks - - - - Callback to fire for this packet - - - Reference to the simulator that this packet came from - - - The packet that needs to be processed - - - Reference to the GridClient object - - - - Default constructor - - - - - - Register an event handler - - Use PacketType.Default to fire this event on every - incoming packet - Packet type to register the handler for - Callback to be fired - True if this callback should be ran - asynchronously, false to run it synchronous - - - - Unregister an event handler - - Packet type to unregister the handler for - Callback to be unregistered - - - - Fire the events registered for this packet type - - Incoming packet type - Incoming packet - Simulator this packet was received from - - - - Registers, unregisters, and fires events generated by the Capabilities - event queue - - - - - Object that is passed to worker threads in the ThreadPool for - firing CAPS callbacks - - - - Callback to fire for this packet - - - Name of the CAPS event - - - Strongly typed decoded data - - - Reference to the simulator that generated this event - - - Reference to the GridClient object - - - - Default constructor - - Reference to the GridClient object - - - - Register an new event handler for a capabilities event sent via the EventQueue - - Use String.Empty to fire this event on every CAPS event - Capability event name to register the - handler for - Callback to fire - - - - Unregister a previously registered capabilities handler - - Capability event name unregister the - handler for - Callback to unregister - - - - Fire the events registered for this event type synchronously - - Capability name - Decoded event body - Reference to the simulator that - generated this event - - - - Fire the events registered for this event type asynchronously - - Capability name - Decoded event body - Reference to the simulator that - generated this event - - - - - - - - The avatar has no rights - - - The avatar can see the online status of the target avatar - - - The avatar can see the location of the target avatar on the map - - - The avatar can modify the ojects of the target avatar - - - - This class holds information about an avatar in the friends list. There are two ways - to interface to this class. The first is through the set of boolean properties. This is the typical - way clients of this class will use it. The second interface is through two bitflag properties, - TheirFriendsRights and MyFriendsRights - - - - - System ID of the avatar - - - - - full name of the avatar - - - - - True if the avatar is online - - - - - True if the friend can see if I am online - - - - - True if the friend can see me on the map - - - - - True if the freind can modify my objects - - - - - True if I can see if my friend is online - - - - - True if I can see if my friend is on the map - - - - - True if I can modify my friend's objects - - - - - My friend's rights represented as bitmapped flags - - - - - My rights represented as bitmapped flags - - - - - Used internally when building the initial list of friends at login time - - System ID of the avatar being prepesented - Rights the friend has to see you online and to modify your objects - Rights you have to see your friend online and to modify their objects - - - - FriendInfo represented as a string - - A string reprentation of both my rights and my friends rights - - - - This class is used to add and remove avatars from your friends list and to manage their permission. - - - - The event subscribers. null if no subcribers - - - Raises the FriendOnline event - A FriendInfoEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator sends notification one of the members in our friends list comes online - - - The event subscribers. null if no subcribers - - - Raises the FriendOffline event - A FriendInfoEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator sends notification one of the members in our friends list goes offline - - - The event subscribers. null if no subcribers - - - Raises the FriendRightsUpdate event - A FriendInfoEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator sends notification one of the members in our friends list grants or revokes permissions - - - The event subscribers. null if no subcribers - - - Raises the FriendNames event - A FriendNamesEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator sends us the names on our friends list - - - The event subscribers. null if no subcribers - - - Raises the FriendshipOffered event - A FriendshipOfferedEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator sends notification another agent is offering us friendship - - - The event subscribers. null if no subcribers - - - Raises the FriendshipResponse event - A FriendshipResponseEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when a request we sent to friend another agent is accepted or declined - - - The event subscribers. null if no subcribers - - - Raises the FriendshipTerminated event - A FriendshipTerminatedEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator sends notification one of the members in our friends list has terminated - our friendship - - - The event subscribers. null if no subcribers - - - Raises the FriendFoundReply event - A FriendFoundReplyEventArgs object containing the - data returned from the data server - - - Thread sync lock object - - - Raised when the simulator sends the location of a friend we have - requested map location info for - - - - A dictionary of key/value pairs containing known friends of this avatar. - - The Key is the of the friend, the value is a - object that contains detailed information including permissions you have and have given to the friend - - - - - A Dictionary of key/value pairs containing current pending frienship offers. - - The key is the of the avatar making the request, - the value is the of the request which is used to accept - or decline the friendship offer - - - - - Internal constructor - - A reference to the GridClient Object - - - - Accept a friendship request - - agentID of avatatar to form friendship with - imSessionID of the friendship request message - - - - Decline a friendship request - - of friend - imSessionID of the friendship request message - - - - Overload: Offer friendship to an avatar. - - System ID of the avatar you are offering friendship to - - - - Offer friendship to an avatar. - - System ID of the avatar you are offering friendship to - A message to send with the request - - - - Terminate a friendship with an avatar - - System ID of the avatar you are terminating the friendship with - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - Change the rights of a friend avatar. - - the of the friend - the new rights to give the friend - This method will implicitly set the rights to those passed in the rights parameter. - - - - Use to map a friends location on the grid. - - Friends UUID to find - - - - - Use to track a friends movement on the grid - - Friends Key - - - - Ask for a notification of friend's online status - - Friend's UUID - - - - This handles the asynchronous response of a RequestAvatarNames call. - - - names cooresponding to the the list of IDs sent the the RequestAvatarNames call. - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - Populate FriendList with data from the login reply - - true if login was successful - true if login request is requiring a redirect - A string containing the response to the login request - A string containing the reason for the request - A object containing the decoded - reply from the login server - - - Contains information on a member of our friends list - - - Get the FriendInfo - - - - Construct a new instance of the FriendInfoEventArgs class - - The FriendInfo - - - Contains Friend Names - - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name - - - - Construct a new instance of the FriendNamesEventArgs class - - A dictionary where the Key is the ID of the Agent, - and the Value is a string containing their name - - - Sent when another agent requests a friendship with our agent - - - Get the ID of the agent requesting friendship - - - Get the name of the agent requesting friendship - - - Get the ID of the session, used in accepting or declining the - friendship offer - - - - Construct a new instance of the FriendshipOfferedEventArgs class - - The ID of the agent requesting friendship - The name of the agent requesting friendship - The ID of the session, used in accepting or declining the - friendship offer - - - A response containing the results of our request to form a friendship with another agent - - - Get the ID of the agent we requested a friendship with - - - Get the name of the agent we requested a friendship with - - - true if the agent accepted our friendship offer - - - - Construct a new instance of the FriendShipResponseEventArgs class - - The ID of the agent we requested a friendship with - The name of the agent we requested a friendship with - true if the agent accepted our friendship offer - - - Contains data sent when a friend terminates a friendship with us - - - Get the ID of the agent that terminated the friendship with us - - - Get the name of the agent that terminated the friendship with us - - - - Construct a new instance of the FrindshipTerminatedEventArgs class - - The ID of the friend who terminated the friendship with us - The name of the friend who terminated the friendship with us - - - - Data sent in response to a request which contains the information to allow us to map the friends location - - - - Get the ID of the agent we have received location information for - - - Get the region handle where our mapped friend is located - - - Get the simulator local position where our friend is located - - - - Construct a new instance of the FriendFoundReplyEventArgs class - - The ID of the agent we have requested location information for - The region handle where our friend is located - The simulator local position our friend is located - - - - Main class to expose grid functionality to clients. All of the - classes needed for sending and receiving data are accessible through - this class. - - - - // Example minimum code required to instantiate class and - // connect to a simulator. - using System; - using System.Collections.Generic; - using System.Text; - using OpenMetaverse; - - namespace FirstBot - { - class Bot - { - public static GridClient Client; - static void Main(string[] args) - { - Client = new GridClient(); // instantiates the GridClient class - // to the global Client object - // Login to Simulator - Client.Network.Login("FirstName", "LastName", "Password", "FirstBot", "1.0"); - // Wait for a Keypress - Console.ReadLine(); - // Logout of simulator - Client.Network.Logout(); - } - } - } - - - - - Networking subsystem - - - Settings class including constant values and changeable - parameters for everything - - - Parcel (subdivided simulator lots) subsystem - - - Our own avatars subsystem - - - Other avatars subsystem - - - Estate subsystem - - - Friends list subsystem - - - Grid (aka simulator group) subsystem - - - Object subsystem - - - Group subsystem - - - Asset subsystem - - - Appearance subsystem - - - Inventory subsystem - - - Directory searches including classifieds, people, land - sales, etc - - - Handles land, wind, and cloud heightmaps - - - Handles sound-related networking - - - Throttling total bandwidth usage, or allocating bandwidth - for specific data stream types - - - - Default constructor - - - - - Return the full name of this instance - - Client avatars full name - - - - Map layer request type - - - - Objects and terrain are shown - - - Only the terrain is shown, no objects - - - Overlay showing land for sale and for auction - - - - Type of grid item, such as telehub, event, populator location, etc. - - - - Telehub - - - PG rated event - - - Mature rated event - - - Popular location - - - Locations of avatar groups in a region - - - Land for sale - - - Classified ad - - - Adult rated event - - - Adult land for sale - - - - Information about a region on the grid map - - - - Sim X position on World Map - - - Sim Y position on World Map - - - Sim Name (NOTE: In lowercase!) - - - - - - Appears to always be zero (None) - - - Sim's defined Water Height - - - - - - UUID of the World Map image - - - Unique identifier for this region, a combination of the X - and Y position - - - - - - - - - - - - - - - - - - - - - - - Visual chunk of the grid map - - - - - Base class for Map Items - - - - The Global X position of the item - - - The Global Y position of the item - - - Get the Local X position of the item - - - Get the Local Y position of the item - - - Get the Handle of the region - - - - Represents an agent or group of agents location - - - - - Represents a Telehub location - - - - - Represents a non-adult parcel of land for sale - - - - - Represents an Adult parcel of land for sale - - - - - Represents a PG Event - - - - - Represents a Mature event - - - - - Represents an Adult event - - - - - Manages grid-wide tasks such as the world map - - - - The event subscribers. null if no subcribers - - - Raises the CoarseLocationUpdate event - A CoarseLocationUpdateEventArgs object containing the - data sent by simulator - - - Thread sync lock object - - - Raised when the simulator sends a - containing the location of agents in the simulator - - - The event subscribers. null if no subcribers - - - Raises the GridRegion event - A GridRegionEventArgs object containing the - data sent by simulator - - - Thread sync lock object - - - Raised when the simulator sends a Region Data in response to - a Map request - - - The event subscribers. null if no subcribers - - - Raises the GridLayer event - A GridLayerEventArgs object containing the - data sent by simulator - - - Thread sync lock object - - - Raised when the simulator sends GridLayer object containing - a map tile coordinates and texture information - - - The event subscribers. null if no subcribers - - - Raises the GridItems event - A GridItemEventArgs object containing the - data sent by simulator - - - Thread sync lock object - - - Raised when the simulator sends GridItems object containing - details on events, land sales at a specific location - - - The event subscribers. null if no subcribers - - - Raises the RegionHandleReply event - A RegionHandleReplyEventArgs object containing the - data sent by simulator - - - Thread sync lock object - - - Raised in response to a Region lookup - - - Unknown - - - Current direction of the sun - - - Current angular velocity of the sun - - - Microseconds since the start of SL 4-hour day - - - A dictionary of all the regions, indexed by region name - - - A dictionary of all the regions, indexed by region handle - - - - Constructor - - Instance of GridClient object to associate with this GridManager instance - - - - - - - - - - Request a map layer - - The name of the region - The type of layer - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Request data for all mainland (Linden managed) simulators - - - - - Request the region handle for the specified region UUID - - UUID of the region to look up - - - - Get grid region information using the region name, this function - will block until it can find the region or gives up - - Name of sim you're looking for - Layer that you are requesting - Will contain a GridRegion for the sim you're - looking for if successful, otherwise an empty structure - True if the GridRegion was successfully fetched, otherwise - false - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - Avatar group management - - - - Key of Group Member - - - Total land contribution - - - Online status information - - - Abilities that the Group Member has - - - Current group title - - - Is a group owner - - - - Role manager for a group - - - - Key of the group - - - Key of Role - - - Name of Role - - - Group Title associated with Role - - - Description of Role - - - Abilities Associated with Role - - - Returns the role's title - The role's title - - - - Class to represent Group Title - - - - Key of the group - - - ID of the role title belongs to - - - Group Title - - - Whether title is Active - - - Returns group title - - - - Represents a group on the grid - - - - Key of Group - - - Key of Group Insignia - - - Key of Group Founder - - - Key of Group Role for Owners - - - Name of Group - - - Text of Group Charter - - - Title of "everyone" role - - - Is the group open for enrolement to everyone - - - Will group show up in search - - - - - - - - - - - - Is the group Mature - - - Cost of group membership - - - - - - - - - The total number of current members this group has - - - The number of roles this group has configured - - - Show this group in agent's profile - - - Returns the name of the group - A string containing the name of the group - - - - A group Vote - - - - Key of Avatar who created Vote - - - Text of the Vote proposal - - - Total number of votes - - - - A group proposal - - - - The Text of the proposal - - - The minimum number of members that must vote before proposal passes or failes - - - The required ration of yes/no votes required for vote to pass - The three options are Simple Majority, 2/3 Majority, and Unanimous - TODO: this should be an enum - - - The duration in days votes are accepted - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Struct representing a group notice - - - - - - - - - - - - - - - - - - - - - - - Struct representing a group notice list entry - - - - Notice ID - - - Creation timestamp of notice - - - Agent name who created notice - - - Notice subject - - - Is there an attachment? - - - Attachment Type - - - - Struct representing a member of a group chat session and their settings - - - - The of the Avatar - - - True if user has voice chat enabled - - - True of Avatar has moderator abilities - - - True if a moderator has muted this avatars chat - - - True if a moderator has muted this avatars voice - - - - Role update flags - - - - - - - - - - - - - - - - - - - - - - - - - Can send invitations to groups default role - - - Can eject members from group - - - Can toggle 'Open Enrollment' and change 'Signup fee' - - - Member is visible in the public member list - - - Can create new roles - - - Can delete existing roles - - - Can change Role names, titles and descriptions - - - Can assign other members to assigners role - - - Can assign other members to any role - - - Can remove members from roles - - - Can assign and remove abilities in roles - - - Can change group Charter, Insignia, 'Publish on the web' and which - members are publicly visible in group member listings - - - Can buy land or deed land to group - - - Can abandon group owned land to Governor Linden on mainland, or Estate owner for - private estates - - - Can set land for-sale information on group owned parcels - - - Can subdivide and join parcels - - - Can change music and media settings - - - Can toggle 'Edit Terrain' option in Land settings - - - Can toggle various About Land > Options settings - - - Can toggle "Show in Find Places" and set search category - - - Can change parcel name, description, and 'Publish on web' settings - - - Can set the landing point and teleport routing on group land - - - Can always terraform land, even if parcel settings have it turned off - - - Can always fly while over group owned land - - - Can always rez objects on group owned land - - - Can always create landmarks for group owned parcels - - - Can set home location on any group owned parcel - - - Allowed to hold events on group-owned land - - - Can modify public access settings for group owned parcels - - - Can manager parcel ban lists on group owned land - - - Can manage pass list sales information - - - Can eject and freeze other avatars on group owned land - - - Can return objects set to group - - - Can return non-group owned/set objects - - - Can return group owned objects - - - Can landscape using Linden plants - - - Can deed objects to group - - - Can move group owned objects - - - Can set group owned objects for-sale - - - Pay group liabilities and receive group dividends - - - Can send group notices - - - Can receive group notices - - - Can create group proposals - - - Can vote on group proposals - - - Can join group chat sessions - - - Can use voice chat in Group Chat sessions - - - Can moderate group chat sessions - - - Has admin rights to any experiences owned by this group - - - Can sign scripts for experiences owned by this group - - - Allows access to ban / un-ban agents from a group - - - - Ban actions available for group members - - - - Ban agent from joining a group - - - Remove restriction on agent jointing a group - - - - Handles all network traffic related to reading and writing group - information - - - - The event subscribers. null if no subcribers - - - Raises the CurrentGroups event - A CurrentGroupsEventArgs object containing the - data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - our current group membership - - - The event subscribers. null if no subcribers - - - Raises the GroupNamesReply event - A GroupNamesEventArgs object containing the - data response from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a RequestGroupName - or RequestGroupNames request - - - The event subscribers. null if no subcribers - - - Raises the GroupProfile event - An GroupProfileEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the GroupMembers event - A GroupMembersEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the GroupRolesDataReply event - A GroupRolesDataReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the GroupRoleMembersReply event - A GroupRolesRoleMembersReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the GroupTitlesReply event - A GroupTitlesReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the GroupAccountSummary event - A GroupAccountSummaryReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when a response to a RequestGroupAccountSummary is returned - by the simulator - - - The event subscribers. null if no subcribers - - - Raises the GroupCreated event - An GroupCreatedEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when a request to create a group is successful - - - The event subscribers. null if no subcribers - - - Raises the GroupJoined event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator - - - Thread sync lock object - - - Raised when a request to join a group either - fails or succeeds - - - The event subscribers. null if no subcribers - - - Raises the GroupLeft event - A GroupOperationEventArgs object containing the - result of the operation returned from the simulator - - - Thread sync lock object - - - Raised when a request to leave a group either - fails or succeeds - - - The event subscribers. null if no subcribers - - - Raises the GroupDropped event - An GroupDroppedEventArgs object containing the - the group your agent left - - - Thread sync lock object - - - Raised when A group is removed from the group server - - - The event subscribers. null if no subcribers - - - Raises the GroupMemberEjected event - An GroupMemberEjectedEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when a request to eject a member from a group either - fails or succeeds - - - The event subscribers. null if no subcribers - - - Raises the GroupNoticesListReply event - An GroupNoticesListReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us group notices - - - - The event subscribers. null if no subcribers - - - Raises the GroupInvitation event - An GroupInvitationEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when another agent invites our avatar to join a group - - - The event subscribers. null if no subcribers - - - Raises the BannedAgents event - An BannedAgentsEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when another agent invites our avatar to join a group - - - A reference to the current instance - - - Currently-active group members requests - - - Currently-active group roles requests - - - Currently-active group role-member requests - - - Dictionary keeping group members while request is in progress - - - Dictionary keeping mebmer/role mapping while request is in progress - - - Dictionary keeping GroupRole information while request is in progress - - - Caches group name lookups - - - - Construct a new instance of the GroupManager class - - A reference to the current instance - - - - Request a current list of groups the avatar is a member of. - - CAPS Event Queue must be running for this to work since the results - come across CAPS. - - - - Lookup name of group based on groupID - - groupID of group to lookup name for. - - - - Request lookup of multiple group names - - List of group IDs to request. - - - Lookup group profile data such as name, enrollment, founder, logo, etc - Subscribe to OnGroupProfile event to receive the results. - group ID (UUID) - - - Request a list of group members. - Subscribe to OnGroupMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache - - - Request group roles - Subscribe to OnGroupRoles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache - - - Request members (members,role) role mapping for a group. - Subscribe to OnGroupRolesMembers event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache - - - Request a groups Titles - Subscribe to OnGroupTitles event to receive the results. - group ID (UUID) - UUID of the request, use to index into cache - - - Begin to get the group account summary - Subscribe to the OnGroupAccountSummary event to receive the results. - group ID (UUID) - How long of an interval - Which interval (0 for current, 1 for last) - - - Invites a user to a group - The group to invite to - A list of roles to invite a person to - Key of person to invite - - - Set a group as the current active group - group ID (UUID) - - - Change the role that determines your active title - Group ID to use - Role ID to change to - - - Set this avatar's tier contribution - Group ID to change tier in - amount of tier to donate - - - - Save wheather agent wants to accept group notices and list this group in their profile - - Group - Accept notices from this group - List this group in the profile - - - Request to join a group - Subscribe to OnGroupJoined event for confirmation. - group ID (UUID) to join. - - - - Request to create a new group. If the group is successfully - created, L$100 will automatically be deducted - - Subscribe to OnGroupCreated event to receive confirmation. - Group struct containing the new group info - - - Update a group's profile and other information - Groups ID (UUID) to update. - Group struct to update. - - - Eject a user from a group - Group ID to eject the user from - Avatar's key to eject - - - Update role information - Modified role to be updated - - - Create a new group role - Group ID to update - Role to create - - - Delete a group role - Group ID to update - Role to delete - - - Remove an avatar from a role - Group ID to update - Role ID to be removed from - Avatar's Key to remove - - - Assign an avatar to a role - Group ID to update - Role ID to assign to - Avatar's ID to assign to role - - - Request the group notices list - Group ID to fetch notices for - - - Request a group notice by key - ID of group notice - - - Send out a group notice - Group ID to update - GroupNotice structure containing notice data - - - Start a group proposal (vote) - The Group ID to send proposal to - GroupProposal structure containing the proposal - - - Request to leave a group - Subscribe to OnGroupLeft event to receive confirmation - The group to leave - - - - Gets the URI of the cpability for handling group bans - - Group ID - null, if the feature is not supported, or URI of the capability - - - - Request a list of residents banned from joining a group - - UUID of the group - - - - Request a list of residents banned from joining a group - - UUID of the group - Callback on request completition - - - - Request that group of agents be banned or unbanned from the group - - Group ID - Ban/Unban action - Array of agents UUIDs to ban - - - - Request that group of agents be banned or unbanned from the group - - Group ID - Ban/Unban action - Array of agents UUIDs to ban - Callback - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Contains the current groups your agent is a member of - - - Get the current groups your agent is a member of - - - Construct a new instance of the CurrentGroupsEventArgs class - The current groups your agent is a member of - - - A Dictionary of group names, where the Key is the groups ID and the value is the groups name - - - Get the Group Names dictionary - - - Construct a new instance of the GroupNamesEventArgs class - The Group names dictionary - - - Represents the members of a group - - - Get the ID as returned by the request to correlate - this result set and the request - - - Get the ID of the group - - - Get the dictionary of members - - - - Construct a new instance of the GroupMembersReplyEventArgs class - - The ID of the request - The ID of the group - The membership list of the group - - - Represents the roles associated with a group - - - Get the ID as returned by the request to correlate - this result set and the request - - - Get the ID of the group - - - Get the dictionary containing the roles - - - Construct a new instance of the GroupRolesDataReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The dictionary containing the roles - - - Represents the Role to Member mappings for a group - - - Get the ID as returned by the request to correlate - this result set and the request - - - Get the ID of the group - - - Get the member to roles map - - - Construct a new instance of the GroupRolesMembersReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The member to roles map - - - Represents the titles for a group - - - Get the ID as returned by the request to correlate - this result set and the request - - - Get the ID of the group - - - Get the titles - - - Construct a new instance of the GroupTitlesReplyEventArgs class - The ID as returned by the request to correlate - this result set and the request - The ID of the group - The titles - - - Represents the summary data for a group - - - Get the ID of the group - - - Get the summary data - - - Construct a new instance of the GroupAccountSummaryReplyEventArgs class - The ID of the group - The summary data - - - A response to a group create request - - - Get the ID of the group - - - true of the group was created successfully - - - A string containing the message - - - Construct a new instance of the GroupCreatedReplyEventArgs class - The ID of the group - the success or faulure of the request - A string containing additional information - - - Represents a response to a request - - - Get the ID of the group - - - true of the request was successful - - - Construct a new instance of the GroupOperationEventArgs class - The ID of the group - true of the request was successful - - - Represents your agent leaving a group - - - Get the ID of the group - - - Construct a new instance of the GroupDroppedEventArgs class - The ID of the group - - - Represents a list of active group notices - - - Get the ID of the group - - - Get the notices list - - - Construct a new instance of the GroupNoticesListReplyEventArgs class - The ID of the group - The list containing active notices - - - Represents the profile of a group - - - Get the group profile - - - Construct a new instance of the GroupProfileEventArgs class - The group profile - - - - Provides notification of a group invitation request sent by another Avatar - - The invitation is raised when another avatar makes an offer for our avatar - to join a group. - - - The ID of the Avatar sending the group invitation - - - The name of the Avatar sending the group invitation - - - A message containing the request information which includes - the name of the group, the groups charter and the fee to join details - - - The Simulator - - - Set to true to accept invitation, false to decline - - - - Result of the request for list of agents banned from a group - - - - Indicates if list of banned agents for a group was successfully retrieved - - - Indicates if list of banned agents for a group was successfully retrieved - - - Array containing a list of UUIDs of the agents banned from a group - - - - Static helper functions and global variables - - - - This header flag signals that ACKs are appended to the packet - - - This header flag signals that this packet has been sent before - - - This header flags signals that an ACK is expected for this packet - - - This header flag signals that the message is compressed using zerocoding - - - - Passed to Logger.Log() to identify the severity of a log entry - - - - No logging information will be output - - - Non-noisy useful information, may be helpful in - debugging a problem - - - A non-critical error occurred. A warning will not - prevent the rest of the library from operating as usual, - although it may be indicative of an underlying issue - - - A critical error has occurred. Generally this will - be followed by the network layer shutting down, although the - stability of the library after an error is uncertain - - - Used for internal testing, this logging level can - generate very noisy (long and/or repetitive) messages. Don't - pass this to the Log() function, use DebugLog() instead. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Given an X/Y location in absolute (grid-relative) terms, a region - handle is returned along with the local X/Y location in that region - - The absolute X location, a number such as - 255360.35 - The absolute Y location, a number such as - 255360.35 - The sim-local X position of the global X - position, a value from 0.0 to 256.0 - The sim-local Y position of the global Y - position, a value from 0.0 to 256.0 - A 64-bit region handle that can be used to teleport to - - - - Converts a floating point number to a terse string format used for - transmitting numbers in wearable asset files - - Floating point number to convert to a string - A terse string representation of the input number - - - - Convert a variable length field (byte array) to a string, with a - field name prepended to each line of the output - - If the byte array has unprintable characters in it, a - hex dump will be written instead - The StringBuilder object to write to - The byte array to convert to a string - A field name to prepend to each line of output - - - - Decode a zerocoded byte array, used to decompress packets marked - with the zerocoded flag - - Any time a zero is encountered, the next byte is a count - of how many zeroes to expand. One zero is encoded with 0x00 0x01, - two zeroes is 0x00 0x02, three zeroes is 0x00 0x03, etc. The - first four bytes are copied directly to the output buffer. - - The byte array to decode - The length of the byte array to decode. This - would be the length of the packet up to (but not including) any - appended ACKs - The output byte array to decode to - The length of the output buffer - - - - Encode a byte array with zerocoding. Used to compress packets marked - with the zerocoded flag. Any zeroes in the array are compressed down - to a single zero byte followed by a count of how many zeroes to expand - out. A single zero becomes 0x00 0x01, two zeroes becomes 0x00 0x02, - three zeroes becomes 0x00 0x03, etc. The first four bytes are copied - directly to the output buffer. - - The byte array to encode - The length of the byte array to encode - The output byte array to encode to - The length of the output buffer - - - - Calculates the CRC (cyclic redundancy check) needed to upload inventory. - - Creation date - Sale type - Inventory type - Type - Asset ID - Group ID - Sale price - Owner ID - Creator ID - Item ID - Folder ID - Everyone mask (permissions) - Flags - Next owner mask (permissions) - Group mask (permissions) - Owner mask (permissions) - The calculated CRC - - - - Attempts to load a file embedded in the assembly - - The filename of the resource to load - A Stream for the requested file, or null if the resource - was not successfully loaded - - - - Attempts to load a file either embedded in the assembly or found in - a given search path - - The filename of the resource to load - An optional path that will be searched if - the asset is not found embedded in the assembly - A Stream for the requested file, or null if the resource - was not successfully loaded - - - - Converts a list of primitives to an object that can be serialized - with the LLSD system - - Primitives to convert to a serializable object - An object that can be serialized with LLSD - - - - Deserializes OSD in to a list of primitives - - Structure holding the serialized primitive list, - must be of the SDMap type - A list of deserialized primitives - - - - Converts a struct or class object containing fields only into a key value separated string - - The struct object - A string containing the struct fields as the keys, and the field value as the value separated - - - // Add the following code to any struct or class containing only fields to override the ToString() - // method to display the values of the passed object - - /// Print the struct data as a string - ///A string containing the field name, and field value - public override string ToString() - { - return Helpers.StructToString(this); - } - - - - - - The InternalDictionary class is used through the library for storing key/value pairs. - It is intended to be a replacement for the generic Dictionary class and should - be used in its place. It contains several methods for allowing access to the data from - outside the library that are read only and thread safe. - - - Key - Value - - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking - on this member - - - - Gets the number of Key/Value pairs contained in the - - - - - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. - - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(); - - - - - - Initializes a new instance of the Class - with the specified key/value, has its initial valies copied from the specified - - - - to copy initial values from - - - // initialize a new InternalDictionary named testAvName with a UUID as the key and an string as the value. - // populates with copied values from example KeyNameCache Dictionary. - - // create source dictionary - Dictionary<UUID, string> KeyNameCache = new Dictionary<UUID, string>(); - KeyNameCache.Add("8300f94a-7970-7810-cf2c-fc9aa6cdda24", "Jack Avatar"); - KeyNameCache.Add("27ba1e40-13f7-0708-3e98-5819d780bd62", "Jill Avatar"); - - // Initialize new dictionary. - public InternalDictionary<UUID, string> testAvName = new InternalDictionary<UUID, string>(KeyNameCache); - - - - - - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. - - Initial size of dictionary - - - // initialize a new InternalDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public InternalDictionary<string, int> testDict = new InternalDictionary<string, int>(10); - - - - - - Try to get entry from with specified key - - Key to use for lookup - Value returned - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars InternalDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - - - - - Finds the specified match. - - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives InternalDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - - - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - - - - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - - - - - Perform an on each entry in an - to perform - - - // Iterates over the ObjectsPrimitives InternalDictionary and prints out some information. - Client.Network.CurrentSim.ObjectsPrimitives.ForEach( - delegate(Primitive prim) - { - if (prim.Text != null) - { - Console.WriteLine("NAME={0} ID = {1} TEXT = '{2}'", - prim.PropertiesFamily.Name, prim.ID, prim.Text); - } - }); - - - - - Perform an on each key of an - to perform - - - - Perform an on each KeyValuePair of an - - to perform - - - Check if Key exists in Dictionary - Key to check for - if found, otherwise - - - Check if Value exists in Dictionary - Value to check for - if found, otherwise - - - - Adds the specified key to the dictionary, dictionary locking is not performed, - - - The key - The value - - - - Removes the specified key, dictionary locking is not performed - - The key. - if successful, otherwise - - - - Indexer for the dictionary - - The key - The value - - - - Exception class to identify inventory exceptions - - - - - Responsible for maintaining inventory structure. Inventory constructs nodes - and manages node children as is necessary to maintain a coherant hirarchy. - Other classes should not manipulate or create InventoryNodes explicitly. When - A node's parent changes (when a folder is moved, for example) simply pass - Inventory the updated InventoryFolder and it will make the appropriate changes - to its internal representation. - - - - The event subscribers, null of no subscribers - - - Raises the InventoryObjectUpdated Event - A InventoryObjectUpdatedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the InventoryObjectRemoved Event - A InventoryObjectRemovedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the InventoryObjectAdded Event - A InventoryObjectAddedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - - The root folder of this avatars inventory - - - - - The default shared library folder - - - - - The root node of the avatars inventory - - - - - The root node of the default shared library - - - - - Returns the contents of the specified folder - - A folder's UUID - The contents of the folder corresponding to folder - When folder does not exist in the inventory - - - - Updates the state of the InventoryNode and inventory data structure that - is responsible for the InventoryObject. If the item was previously not added to inventory, - it adds the item, and updates structure accordingly. If it was, it updates the - InventoryNode, changing the parent node if item.parentUUID does - not match node.Parent.Data.UUID. - - You can not set the inventory root folder using this method - - The InventoryObject to store - - - - Removes the InventoryObject and all related node data from Inventory. - - The InventoryObject to remove. - - - - Used to find out if Inventory contains the InventoryObject - specified by uuid. - - The UUID to check. - true if inventory contains uuid, false otherwise - - - - Saves the current inventory structure to a cache file - - Name of the cache file to save to - - - - Loads in inventory cache file into the inventory structure. Note only valid to call after login has been successful. - - Name of the cache file to load - The number of inventory items sucessfully reconstructed into the inventory node tree - - - - By using the bracket operator on this class, the program can get the - InventoryObject designated by the specified uuid. If the value for the corresponding - UUID is null, the call is equivelant to a call to RemoveNodeFor(this[uuid]). - If the value is non-null, it is equivelant to a call to UpdateNodeFor(value), - the uuid parameter is ignored. - - The UUID of the InventoryObject to get or set, ignored if set to non-null value. - The InventoryObject corresponding to uuid. - - - Sort by name - - - Sort by date - - - Sort folders by name, regardless of whether items are - sorted by name or date - - - Place system folders at the top - - - - Possible destinations for DeRezObject request - - - - - - - Copy from in-world to agent inventory - - - Derez to TaskInventory - - - - - - Take Object - - - - - - Delete Object - - - Put an avatar attachment into agent inventory - - - - - - Return an object back to the owner's inventory - - - Return a deeded object back to the last owner's inventory - - - - Upper half of the Flags field for inventory items - - - - Indicates that the NextOwner permission will be set to the - most restrictive set of permissions found in the object set - (including linkset items and object inventory items) on next rez - - - Indicates that the object sale information has been - changed - - - If set, and a slam bit is set, indicates BaseMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates OwnerMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates GroupMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates EveryoneMask will be overwritten on Rez - - - If set, and a slam bit is set, indicates NextOwnerMask will be overwritten on Rez - - - Indicates whether this object is composed of multiple - items or not - - - Indicates that the asset is only referenced by this - inventory item. If this item is deleted or updated to reference a - new assetID, the asset can be deleted - - - - Base Class for Inventory Items - - - - of item/folder - - - of parent folder - - - Name of item/folder - - - Item/Folder Owners - - - - Constructor, takes an itemID as a parameter - - The of the item - - - - - - - - - - - - - - - - Generates a number corresponding to the value of the object to support the use of a hash table, - suitable for use in hashing algorithms and data structures such as a hash table - - A Hashcode of all the combined InventoryBase fields - - - - Determine whether the specified object is equal to the current object - - InventoryBase object to compare against - true if objects are the same - - - - Determine whether the specified object is equal to the current object - - InventoryBase object to compare against - true if objects are the same - - - - Convert inventory to OSD - - OSD representation - - - - An Item in Inventory - - - - The of this item - - - The combined of this item - - - The type of item from - - - The type of item from the enum - - - The of the creator of this item - - - A Description of this item - - - The s this item is set to or owned by - - - If true, item is owned by a group - - - The price this item can be purchased for - - - The type of sale from the enum - - - Combined flags from - - - Time and date this inventory item was created, stored as - UTC (Coordinated Universal Time) - - - Used to update the AssetID in requests sent to the server - - - The of the previous owner of the item - - - - Construct a new InventoryItem object - - The of the item - - - - Construct a new InventoryItem object of a specific Type - - The type of item from - of the item - - - - Indicates inventory item is a link - - True if inventory item is a link to another inventory item - - - - - - - - - - - - - - - - Generates a number corresponding to the value of the object to support the use of a hash table. - Suitable for use in hashing algorithms and data structures such as a hash table - - A Hashcode of all the combined InventoryItem fields - - - - Compares an object - - The object to compare - true if comparison object matches - - - - Determine whether the specified object is equal to the current object - - The object to compare against - true if objects are the same - - - - Determine whether the specified object is equal to the current object - - The object to compare against - true if objects are the same - - - - Create InventoryItem from OSD - - OSD Data that makes up InventoryItem - Inventory item created - - - - Convert InventoryItem to OSD - - OSD representation of InventoryItem - - - - InventoryTexture Class representing a graphical image - - - - - - Construct an InventoryTexture object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryTexture object from a serialization stream - - - - - InventorySound Class representing a playable sound - - - - - Construct an InventorySound object - - A which becomes the - objects AssetUUID - - - - Construct an InventorySound object from a serialization stream - - - - - InventoryCallingCard Class, contains information on another avatar - - - - - Construct an InventoryCallingCard object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryCallingCard object from a serialization stream - - - - - InventoryLandmark Class, contains details on a specific location - - - - - Construct an InventoryLandmark object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryLandmark object from a serialization stream - - - - - Landmarks use the InventoryItemFlags struct and will have a flag of 1 set if they have been visited - - - - - InventoryObject Class contains details on a primitive or coalesced set of primitives - - - - - Construct an InventoryObject object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryObject object from a serialization stream - - - - - Gets or sets the upper byte of the Flags value - - - - - Gets or sets the object attachment point, the lower byte of the Flags value - - - - - InventoryNotecard Class, contains details on an encoded text document - - - - - Construct an InventoryNotecard object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryNotecard object from a serialization stream - - - - - InventoryCategory Class - - TODO: Is this even used for anything? - - - - Construct an InventoryCategory object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryCategory object from a serialization stream - - - - - InventoryLSL Class, represents a Linden Scripting Language object - - - - - Construct an InventoryLSL object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryLSL object from a serialization stream - - - - - InventorySnapshot Class, an image taken with the viewer - - - - - Construct an InventorySnapshot object - - A which becomes the - objects AssetUUID - - - - Construct an InventorySnapshot object from a serialization stream - - - - - InventoryAttachment Class, contains details on an attachable object - - - - - Construct an InventoryAttachment object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryAttachment object from a serialization stream - - - - - Get the last AttachmentPoint this object was attached to - - - - - InventoryWearable Class, details on a clothing item or body part - - - - - Construct an InventoryWearable object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryWearable object from a serialization stream - - - - - The , Skin, Shape, Skirt, Etc - - - - - InventoryAnimation Class, A bvh encoded object which animates an avatar - - - - - Construct an InventoryAnimation object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryAnimation object from a serialization stream - - - - - InventoryGesture Class, details on a series of animations, sounds, and actions - - - - - Construct an InventoryGesture object - - A which becomes the - objects AssetUUID - - - - Construct an InventoryGesture object from a serialization stream - - - - - A folder contains s and has certain attributes specific - to itself - - - - The Preferred for a folder. - - - The Version of this folder - - - Number of child items this folder contains. - - - - Constructor - - UUID of the folder - - - - - - - - - - Get Serilization data for this InventoryFolder object - - - - - Construct an InventoryFolder object from a serialization stream - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Create InventoryFolder from OSD - - OSD Data that makes up InventoryFolder - Inventory folder created - - - - Convert InventoryItem to OSD - - OSD representation of InventoryItem - - - - Tools for dealing with agents inventory - - - - Used for converting shadow_id to asset_id - - - - Callback for inventory item creation finishing - - Whether the request to create an inventory - item succeeded or not - Inventory item being created. If success is - false this will be null - - - - Callback for an inventory item being create from an uploaded asset - - true if inventory item creation was successful - - - - - - - - - - - - The event subscribers, null of no subscribers - - - Raises the ItemReceived Event - A ItemReceivedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the FolderUpdated Event - A FolderUpdatedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the InventoryObjectOffered Event - A InventoryObjectOfferedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - an inventory object sent by another avatar or primitive - - - The event subscribers, null of no subscribers - - - Raises the TaskItemReceived Event - A TaskItemReceivedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the FindObjectByPath Event - A FindObjectByPathEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the TaskInventoryReply Event - A TaskInventoryReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - - Reply received when uploading an inventory asset - - Has upload been successful - Error message if upload failed - Inventory asset UUID - New asset UUID - - - The event subscribers, null of no subscribers - - - Raises the SaveAssetToInventory Event - A SaveAssetToInventoryEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - - Delegate that is invoked when script upload is completed - - Has upload succeded (note, there still might be compile errors) - Upload status message - Is compilation successful - If compilation failed, list of error messages, null on compilation success - Script inventory UUID - Script's new asset UUID - - - The event subscribers, null of no subscribers - - - Raises the ScriptRunningReply Event - A ScriptRunningReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - Partial mapping of FolderTypes to folder names - - - - Get this agents Inventory data - - - - - Default constructor - - Reference to the GridClient object - - - - Fetch an inventory item from the dataserver - - The items - The item Owners - a integer representing the number of milliseconds to wait for results - An object on success, or null if no item was found - Items will also be sent to the event - - - - Request A single inventory item - - The items - The item Owners - - - - - Request inventory items - - Inventory items to request - Owners of the inventory items - - - - - Request inventory items via Capabilities - - Inventory items to request - Owners of the inventory items - - - - - Get contents of a folder - - The of the folder to search - The of the folders owner - true to retrieve folders - true to retrieve items - sort order to return results in - a integer representing the number of milliseconds to wait for results - A list of inventory items matching search criteria within folder - - InventoryFolder.DescendentCount will only be accurate if both folders and items are - requested - - - - Request the contents of an inventory folder - - The folder to search - The folder owners - true to return s contained in folder - true to return s containd in folder - the sort order to return items in - - - - - Request the contents of an inventory folder using HTTP capabilities - - The folder to search - The folder owners - true to return s contained in folder - true to return s containd in folder - the sort order to return items in - - - - - Returns the UUID of the folder (category) that defaults to - containing 'type'. The folder is not necessarily only for that - type - - This will return the root folder if one does not exist - - The UUID of the desired folder if found, the UUID of the RootFolder - if not found, or UUID.Zero on failure - - - - Find an object in inventory using a specific path to search - - The folder to begin the search in - The object owners - A string path to search - milliseconds to wait for a reply - Found items or if - timeout occurs or item is not found - - - - Find inventory items by path - - The folder to begin the search in - The object owners - A string path to search, folders/objects separated by a '/' - Results are sent to the event - - - - Search inventory Store object for an item or folder - - The folder to begin the search in - An array which creates a path to search - Number of levels below baseFolder to conduct searches - if True, will stop searching after first match is found - A list of inventory items found - - - - Move an inventory item or folder to a new location - - The item or folder to move - The to move item or folder to - - - - Move an inventory item or folder to a new location and change its name - - The item or folder to move - The to move item or folder to - The name to change the item or folder to - - - - Move and rename a folder - - The source folders - The destination folders - The name to change the folder to - - - - Update folder properties - - of the folder to update - Sets folder's parent to - Folder name - Folder type - - - - Move a folder - - The source folders - The destination folders - - - - Move multiple folders, the keys in the Dictionary parameter, - to a new parents, the value of that folder's key. - - A Dictionary containing the - of the source as the key, and the - of the destination as the value - - - - Move an inventory item to a new folder - - The of the source item to move - The of the destination folder - - - - Move and rename an inventory item - - The of the source item to move - The of the destination folder - The name to change the folder to - - - - Move multiple inventory items to new locations - - A Dictionary containing the - of the source item as the key, and the - of the destination folder as the value - - - - Remove descendants of a folder - - The of the folder - - - - Remove a single item from inventory - - The of the inventory item to remove - - - - Remove a folder from inventory - - The of the folder to remove - - - - Remove multiple items or folders from inventory - - A List containing the s of items to remove - A List containing the s of the folders to remove - - - - Empty the Lost and Found folder - - - - - Empty the Trash folder - - - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - - - - - - - - - - - Proper use is to upload the inventory's asset first, then provide the Asset's TransactionID here. - - - - - - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - The UUID of the newly created folder - - - - Creates a new inventory folder - - ID of the folder to put this folder in - Name of the folder to create - Sets this folder as the default folder - for new assets of the specified type. Use FolderType.None - to create a normal folder, otherwise it will likely create a - duplicate of an existing folder type - The UUID of the newly created folder - If you specify a preferred type of AsseType.Folder - it will create a new root folder which may likely cause all sorts - of strange problems - - - - Create an inventory item and upload asset data - - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Delegate that will receive feedback on success or failure - - - - Create an inventory item and upload asset data - - Asset data - Inventory item name - Inventory item description - Asset type - Inventory type - Put newly created inventory in this folder - Permission of the newly created item - (EveryoneMask, GroupMask, and NextOwnerMask of Permissions struct are supported) - Delegate that will receive feedback on success or failure - - - - Creates inventory link to another inventory item or folder - - Put newly created link in folder with this UUID - Inventory item or folder - Method to call upon creation of the link - - - - Creates inventory link to another inventory item - - Put newly created link in folder with this UUID - Original inventory item - Method to call upon creation of the link - - - - Creates inventory link to another inventory folder - - Put newly created link in folder with this UUID - Original inventory folder - Method to call upon creation of the link - - - - Creates inventory link to another inventory item or folder - - Put newly created link in folder with this UUID - Original item's UUID - Name - Description - Asset Type - Inventory Type - Transaction UUID - Method to call upon creation of the link - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Request a copy of an asset embedded within a notecard - - Usually UUID.Zero for copying an asset from a notecard - UUID of the notecard to request an asset from - Target folder for asset to go to in your inventory - UUID of the embedded asset - callback to run when item is copied to inventory - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Save changes to notecard embedded in object contents - - Encoded notecard asset data - Notecard UUID - Object's UUID - Called upon finish of the upload with status information - - - - Upload new gesture asset for an inventory gesture item - - Encoded gesture asset - Gesture inventory UUID - Callback whick will be called when upload is complete - - - - Update an existing script in an agents Inventory - - A byte[] array containing the encoded scripts contents - the itemID of the script - if true, sets the script content to run on the mono interpreter - - - - - Update an existing script in an task Inventory - - A byte[] array containing the encoded scripts contents - the itemID of the script - UUID of the prim containting the script - if true, sets the script content to run on the mono interpreter - if true, sets the script to running - - - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object - - - - Rez an object from inventory - - Simulator to place object in - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object - User defined queryID to correlate replies - If set to true, the CreateSelected flag - will be set on the rezzed object - - - - Rez an object from inventory - - Simulator to place object in - TaskID object when rezzed - Rotation of the object when rezzed - Vector of where to place object - InventoryItem object containing item details - UUID of group to own the object - User defined queryID to correlate replies - If set to true, the CreateSelected flag - will be set on the rezzed object - - - - DeRez an object from the simulator to the agents Objects folder in the agents Inventory - - The simulator Local ID of the object - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed - - - - DeRez an object from the simulator and return to inventory - - The simulator Local ID of the object - The type of destination from the enum - The destination inventory folders -or- - if DeRezzing object to a tasks Inventory, the Tasks - The transaction ID for this request which - can be used to correlate this request with other packets - If objectLocalID is a child primitive in a linkset, the entire linkset will be derezzed - - - - Rez an item from inventory to its previous simulator location - - - - - - - - - Give an inventory item to another avatar - - The of the item to give - The name of the item - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer - - - - Give an inventory Folder with contents to another avatar - - The of the Folder to give - The name of the folder - The type of the item from the enum - The of the recipient - true to generate a beameffect during transfer - - - - Copy or move an from agent inventory to a task (primitive) inventory - - The target object - The item to copy or move from inventory - - For items with copy permissions a copy of the item is placed in the tasks inventory, - for no-copy items the object is moved to the tasks inventory - - - - Retrieve a listing of the items contained in a task (Primitive) - - The tasks - The tasks simulator local ID - milliseconds to wait for reply from simulator - A list containing the inventory items inside the task or null - if a timeout occurs - This request blocks until the response from the simulator arrives - or timeoutMS is exceeded - - - - Request the contents of a tasks (primitives) inventory from the - current simulator - - The LocalID of the object - - - - - Request the contents of a tasks (primitives) inventory - - The simulator Local ID of the object - A reference to the simulator object that contains the object - - - - - Move an item from a tasks (Primitive) inventory to the specified folder in the avatars inventory - - LocalID of the object in the simulator - UUID of the task item to move - The ID of the destination folder in this agents inventory - Simulator Object - Raises the event - - - - Remove an item from an objects (Prim) Inventory - - LocalID of the object in the simulator - UUID of the task item to remove - Simulator Object - You can confirm the removal by comparing the tasks inventory serial before and after the - request with the request combined with - the event - - - - Copy an InventoryScript item from the Agents Inventory into a primitives task inventory - - An unsigned integer representing a primitive being simulated - An which represents a script object from the agents inventory - true to set the scripts running state to enabled - A Unique Transaction ID - - The following example shows the basic steps necessary to copy a script from the agents inventory into a tasks inventory - and assumes the script exists in the agents inventory. - - uint primID = 95899503; // Fake prim ID - UUID scriptID = UUID.Parse("92a7fe8a-e949-dd39-a8d8-1681d8673232"); // Fake Script UUID in Inventory - - Client.Inventory.FolderContents(Client.Inventory.FindFolderForType(AssetType.LSLText), Client.Self.AgentID, - false, true, InventorySortOrder.ByName, 10000); - - Client.Inventory.RezScript(primID, (InventoryItem)Client.Inventory.Store[scriptID]); - - - - - - Request the running status of a script contained in a task (primitive) inventory - - The ID of the primitive containing the script - The ID of the script - The event can be used to obtain the results of the - request - - - - - Send a request to set the running state of a script contained in a task (primitive) inventory - - The ID of the primitive containing the script - The ID of the script - true to set the script running, false to stop a running script - To verify the change you can use the method combined - with the event - - - - Create a CRC from an InventoryItem - - The source InventoryItem - A uint representing the source InventoryItem as a CRC - - - - Reverses a cheesy XORing with a fixed UUID to convert a shadow_id to an asset_id - - Obfuscated shadow_id value - Deobfuscated asset_id value - - - - Does a cheesy XORing with a fixed UUID to convert an asset_id to a shadow_id - - asset_id value to obfuscate - Obfuscated shadow_id value - - - - Wrapper for creating a new object - - The type of item from the enum - The of the newly created object - An object with the type and id passed - - - - Parse the results of a RequestTaskInventory() response - - A string which contains the data from the task reply - A List containing the items contained within the tasks inventory - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - UpdateCreateInventoryItem packets are received when a new inventory item - is created. This may occur when an object that's rezzed in world is - taken into inventory, when an item is created using the CreateInventoryItem - packet, or when an object is purchased - - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Set to true to accept offer, false to decline it - - - The folder to accept the inventory into, if null default folder for will be used - - - - Callback when an inventory object is accepted and received from a - task inventory. This is the callback in which you actually get - the ItemID, as in ObjectOfferedCallback it is null when received - from a task. - - - - - - - User data - - - - - - - - - - - - - For inventory folder nodes specifies weather the folder needs to be - refreshed from the server - - - - - - - - - - - - - - - - De-serialization constructor for the InventoryNode Class - - - - - Serialization handler for the InventoryNode Class - - - - - De-serialization handler for the InventoryNode Class - - - - - - - - - - - Singleton logging class for the entire library - - - - - Callback used for client apps to receive log messages from - the library - - Data being logged - The severity of the log entry from - - - Triggered whenever a message is logged. If this is left - null, log messages will go to the console - - - log4net logging engine - - - - Default constructor - - - - - Send a log message to the logging engine - - The log message - The severity of the log entry - - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Instance of the client - - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Exception that was raised - - - - Send a log message to the logging engine - - The log message - The severity of the log entry - Instance of the client - Exception that was raised - - - - If the library is compiled with DEBUG defined, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - - The message to log at the DEBUG level to the - current logging engine - - - - If the library is compiled with DEBUG defined and - GridClient.Settings.DEBUG is true, an event will be - fired if an OnLogMessage handler is registered and the - message will be sent to the logging engine - - The message to log at the DEBUG level to the - current logging engine - Instance of the client - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Status of the last application run. - Used for error reporting to the grid login service for statistical purposes. - - - - Application exited normally - - - Application froze - - - Application detected error and exited abnormally - - - Other crash - - - Application froze during logout - - - Application crashed during logout - - - - Login Request Parameters - - - - The URL of the Login Server - - - The number of milliseconds to wait before a login is considered - failed due to timeout - - - The request method - login_to_simulator is currently the only supported method - - - The Agents First name - - - The Agents Last name - - - A md5 hashed password - plaintext password will be automatically hashed - - - The agents starting location once logged in - Either "last", "home", or a string encoded URI - containing the simulator name and x/y/z coordinates e.g: uri:hooper&128&152&17 - - - A string containing the client software channel information - Second Life Release - - - The client software version information - The official viewer uses: Second Life Release n.n.n.n - where n is replaced with the current version of the viewer - - - A string containing the platform information the agent is running on - - - A string containing version number for OS the agent is running on - - - A string hash of the network cards Mac Address - - - Unknown or deprecated - - - A string hash of the first disk drives ID used to identify this clients uniqueness - - - A string containing the viewers Software, this is not directly sent to the login server but - instead is used to generate the Version string - - - A string representing the software creator. This is not directly sent to the login server but - is used by the library to generate the Version information - - - If true, this agent agrees to the Terms of Service of the grid its connecting to - - - Unknown - - - Status of the last application run sent to the grid login server for statistical purposes - - - An array of string sent to the login server to enable various options - - - A randomly generated ID to distinguish between login attempts. This value is only used - internally in the library and is never sent over the wire - - - - Default constuctor, initializes sane default values - - - - - Instantiates new LoginParams object and fills in the values - - Instance of GridClient to read settings from - Login first name - Login last name - Password - Login channnel (application name) - Client version, should be application name + version number - - - - Instantiates new LoginParams object and fills in the values - - Instance of GridClient to read settings from - Login first name - Login last name - Password - Login channnel (application name) - Client version, should be application name + version number - URI of the login server - - - - The decoded data returned from the login server after a successful login - - - - true, false, indeterminate - - - Login message of the day - - - M or PG, also agent_region_access and agent_access_max - - - - Parse LLSD Login Reply Data - - An - contaning the login response data - XML-RPC logins do not require this as XML-RPC.NET - automatically populates the struct properly using attributes - - - - Login Routines - - - NetworkManager is responsible for managing the network layer of - OpenMetaverse. It tracks all the server connections, serializes - outgoing traffic and deserializes incoming traffic, and provides - instances of delegates for network-related events. - - - - The event subscribers, null of no subscribers - - - Raises the LoginProgress Event - A LoginProgressEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - - - - - - - - - - - Called when a reply is received from the login server, the - login sequence will block until this event returns - - - Seed CAPS URL returned from the login server - - - Current state of logging in - - - Upon login failure, contains a short string key for the - type of login error that occurred - - - The raw XML-RPC reply from the login server, exactly as it - was received (minus the HTTP header) - - - During login this contains a descriptive version of - LoginStatusCode. After a successful login this will contain the - message of the day, and after a failed login a descriptive error - message will be returned - - - Maximum number of groups an agent can belong to, -1 for unlimited - - - Server side baking service URL - - - Parsed login response data - - - A list of packets obtained during the login process which - networkmanager will log but not process - - - - Generate sane default values for a login request - - Account first name - Account last name - Account password - Client application name (channel) - Client application name + version - A populated struct containing - sane defaults - - - - Simplified login that takes the most common and required fields - - Account first name - Account last name - Account password - Client application name (channel) - Client application name + version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - - - - Simplified login that takes the most common fields along with a - starting location URI, and can accept an MD5 string instead of a - plaintext password - - Account first name - Account last name - Account password or MD5 hash of the password - such as $1$1682a1e45e9f957dcdf0bb56eb43319c - Client application name (channel) - Starting location URI that can be built with - StartLocation() - Client application name + version - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - - - - Login that takes a struct of all the values that will be passed to - the login server - - The values that will be passed to the login - server, all fields must be set even if they are String.Empty - Whether the login was successful or not. On failure the - LoginErrorKey string will contain the error code and LoginMessage - will contain a description of the error - - - - Build a start location URI for passing to the Login function - - Name of the simulator to start in - X coordinate to start at - Y coordinate to start at - Z coordinate to start at - String with a URI that can be used to login to a specified - location - - - - LoginParams and the initial login XmlRpcRequest were made on a remote machine. - This method now initializes libomv with the results. - - - - - Handles response from XML-RPC login replies - - - - - Handles response from XML-RPC login replies with already parsed LoginResponseData - - - - - Handle response from LLSD login replies - - - - - - - - Get current OS - - Either "Win" or "Linux" - - - - Gets the current OS version number - - The platform version. - - - - Get clients default Mac Address - - A string containing the first found Mac Address - - - - Explains why a simulator or the grid disconnected from us - - - - The client requested the logout or simulator disconnect - - - The server notified us that it is disconnecting - - - Either a socket was closed or network traffic timed out - - - The last active simulator shut down - - - - Holds a simulator reference and a decoded packet, these structs are put in - the packet inbox for event handling - - - - Reference to the simulator that this packet came from - - - Packet that needs to be processed - - - - Holds a simulator reference and a serialized packet, these structs are put in - the packet outbox for sending - - - - Reference to the simulator this packet is destined for - - - Packet that needs to be sent - - - Sequence number of the wrapped packet - - - Number of times this packet has been resent - - - Environment.TickCount when this packet was last sent over the wire - - - Type of the packet - - - The event subscribers, null of no subscribers - - - Raises the PacketSent Event - A PacketSentEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the LoggedOut Event - A LoggedOutEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the SimConnecting Event - A SimConnectingEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the SimConnected Event - A SimConnectedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the SimDisconnected Event - A SimDisconnectedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the Disconnected Event - A DisconnectedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the SimChanged Event - A SimChangedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the EventQueueRunning Event - A EventQueueRunningEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - Unique identifier associated with our connections to - simulators - - - The simulator that the logged in avatar is currently - occupying - - - Shows whether the network layer is logged in to the - grid or not - - - Number of packets in the incoming queue - - - Number of packets in the outgoing queue - - - All of the simulators we are currently connected to - - - Handlers for incoming capability events - - - Handlers for incoming packets - - - Incoming packets that are awaiting handling - - - Outgoing packets that are awaiting handling - - - - Default constructor - - Reference to the GridClient object - - - - Register an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library - - Packet type to trigger events for - Callback to fire when a packet of this type - is received - - - - Register an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library - - Packet type to trigger events for - Callback to fire when a packet of this type - is received - True if the callback should be ran - asynchronously. Only set this to false (synchronous for callbacks - that will always complete quickly) - If any callback for a packet type is marked as - asynchronous, all callbacks for that packet type will be fired - asynchronously - - - - Unregister an event handler for a packet. This is a low level event - interface and should only be used if you are doing something not - supported in the library - - Packet type this callback is registered with - Callback to stop firing events for - - - - Register a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library - - Name of the CAPS event to register a handler for - Callback to fire when a CAPS event is received - - - - Unregister a CAPS event handler. This is a low level event interface - and should only be used if you are doing something not supported in - the library - - Name of the CAPS event this callback is - registered with - Callback to stop firing events for - - - - Send a packet to the simulator the avatar is currently occupying - - Packet to send - - - - Send a packet to a specified simulator - - Packet to send - Simulator to send the packet to - - - - Connect to a simulator - - IP address to connect to - Port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null - - - - Connect to a simulator - - IP address and port to connect to - Handle for this simulator, to identify its - location in the grid - Whether to set CurrentSim to this new - connection, use this if the avatar is moving in to this simulator - URL of the capabilities server to use for - this sim connection - A Simulator object on success, otherwise null - - - - Begins the non-blocking logout. Makes sure that the LoggedOut event is - called even if the server does not send a logout reply, and Shutdown() - is properly called. - - - - - Initiate a blocking logout request. This will return when the logout - handshake has completed or when Settings.LOGOUT_TIMEOUT - has expired and the network layer is manually shut down - - - - - Initiate the logout process. The Shutdown() function - needs to be manually called. - - - - - Close a connection to the given simulator - - - - - - - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout - - Type of shutdown - - - - Shutdown will disconnect all the sims except for the current sim - first, and then kill the connection to CurrentSim. This should only - be called if the logout process times out on RequestLogout - - Type of shutdown - Shutdown message - - - - Searches through the list of currently connected simulators to find - one attached to the given IPEndPoint - - IPEndPoint of the Simulator to search for - A Simulator reference on success, otherwise null - - - - Fire an event when an event queue connects for capabilities - - Simulator the event queue is attached to - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - A Name Value pair with additional settings, used in the protocol - primarily to transmit avatar names and active group in object packets - - - - Type of the value - - - Unknown - - - String value - - - - - - - - - - - - - - - Deprecated - - - String value, but designated as an asset - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Constructor that takes all the fields as parameters - - - - - - - - - - Constructor that takes a single line from a NameValue field - - - - - - - - - - No report - - - Unknown report type - - - Bug report - - - Complaint report - - - Customer service report - - - - Bitflag field for ObjectUpdateCompressed data blocks, describing - which options are present for each object - - - - Unknown - - - Whether the object has a TreeSpecies - - - Whether the object has floating text ala llSetText - - - Whether the object has an active particle system - - - Whether the object has sound attached to it - - - Whether the object is attached to a root object or not - - - Whether the object has texture animation settings - - - Whether the object has an angular velocity - - - Whether the object has a name value pairs string - - - Whether the object has a Media URL set - - - - Specific Flags for MultipleObjectUpdate requests - - - - None - - - Change position of prims - - - Change rotation of prims - - - Change size of prims - - - Perform operation on link set - - - Scale prims uniformly, same as selecing ctrl+shift in the - viewer. Used in conjunction with Scale - - - - Special values in PayPriceReply. If the price is not one of these - literal value of the price should be use - - - - - Indicates that this pay option should be hidden - - - - - Indicates that this pay option should have the default value - - - - - Contains the variables sent in an object update packet for objects. - Used to track position and movement of prims and avatars - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Handles all network traffic related to prims and avatar positions and - movement. - - - - The event subscribers, null of no subscribers - - - Thread sync lock object - - - Raised when the simulator sends us data containing - A , Foliage or Attachment - - - - - The event subscribers, null of no subscribers - - - Raises the ObjectProperties Event - A ObjectPropertiesEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - additional information - - - - - The event subscribers, null of no subscribers - - - Raises the ObjectPropertiesUpdated Event - A ObjectPropertiesUpdatedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - Primitive.ObjectProperties for an object we are currently tracking - - - The event subscribers, null of no subscribers - - - Raises the ObjectPropertiesFamily Event - A ObjectPropertiesFamilyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - additional and details - - - - The event subscribers, null of no subscribers - - - Raises the AvatarUpdate Event - A AvatarUpdateEventArgs object containing - the data sent from the simulator - - - - Raises the ParticleUpdate Event - - A ParticleUpdateEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - updated information for an - - - The event subscribers, null of no subscribers - - - Thread sync lock object - - - Raised when the simulator sends us data containing - and movement changes - - - The event subscribers, null of no subscribers - - - Raises the ObjectDataBlockUpdate Event - A ObjectDataBlockUpdateEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - updates to an Objects DataBlock - - - The event subscribers, null of no subscribers - - - Raises the KillObject Event - A KillObjectEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator informs us an - or is no longer within view - - - The event subscribers, null of no subscribers - - - Raises the KillObjects Event - A KillObjectsEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator informs us when a group of - or is no longer within view - - - The event subscribers, null of no subscribers - - - Raises the AvatarSitChanged Event - A AvatarSitChangedEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - updated sit information for our - - - The event subscribers, null of no subscribers - - - Raises the PayPriceReply Event - A PayPriceReplyEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - purchase price information for a - - - - Callback for getting object media data via CAP - - Indicates if the operation was succesfull - Object media version string - Array indexed on prim face of media entry data - - - The event subscribers, null of no subscribers - - - Raises the PhysicsProperties Event - A PhysicsPropertiesEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - additional information - - - - - Reference to the GridClient object - - - Does periodic dead reckoning calculation to convert - velocity and acceleration to new positions for objects - - - - Construct a new instance of the ObjectManager class - - A reference to the instance - - - - Request information for a single object from a - you are currently connected to - - The the object is located - The Local ID of the object - - - - Request information for multiple objects contained in - the same simulator - - The the objects are located - An array containing the Local IDs of the objects - - - - Attempt to purchase an original object, a copy, or the contents of - an object - - The the object is located - The Local ID of the object - Whether the original, a copy, or the object - contents are on sale. This is used for verification, if the this - sale type is not valid for the object the purchase will fail - Price of the object. This is used for - verification, if it does not match the actual price the purchase - will fail - Group ID that will be associated with the new - purchase - Inventory folder UUID where the object or objects - purchased should be placed - - - BuyObject(Client.Network.CurrentSim, 500, SaleType.Copy, - 100, UUID.Zero, Client.Self.InventoryRootFolderUUID); - - - - - - Request prices that should be displayed in pay dialog. This will triggger the simulator - to send us back a PayPriceReply which can be handled by OnPayPriceReply event - - The the object is located - The ID of the object - The result is raised in the event - - - - Select a single object. This will cause the to send us - an which will raise the event - - The the object is located - The Local ID of the object - - - - - Select a single object. This will cause the to send us - an which will raise the event - - The the object is located - The Local ID of the object - if true, a call to is - made immediately following the request - - - - - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - Should objects be deselected immediately after selection - - - - - Select multiple objects. This will cause the to send us - an which will raise the event - - The the objects are located - An array containing the Local IDs of the objects - - - - - Update the properties of an object - - The the object is located - The Local ID of the object - true to turn the objects physical property on - true to turn the objects temporary property on - true to turn the objects phantom property on - true to turn the objects cast shadows property on - - - - Update the properties of an object - - The the object is located - The Local ID of the object - true to turn the objects physical property on - true to turn the objects temporary property on - true to turn the objects phantom property on - true to turn the objects cast shadows property on - Type of the represetnation prim will have in the physics engine - Density - normal value 1000 - Friction - normal value 0.6 - Restitution - standard value 0.5 - Gravity multiplier - standar value 1.0 - - - - Sets the sale properties of a single object - - The the object is located - The Local ID of the object - One of the options from the enum - The price of the object - - - - Sets the sale properties of multiple objects - - The the objects are located - An array containing the Local IDs of the objects - One of the options from the enum - The price of the object - - - - Deselect a single object - - The the object is located - The Local ID of the object - - - - Deselect multiple objects. - - The the objects are located - An array containing the Local IDs of the objects - - - - Perform a click action on an object - - The the object is located - The Local ID of the object - - - - Perform a click action (Grab) on a single object - - The the object is located - The Local ID of the object - The texture coordinates to touch - The surface coordinates to touch - The face of the position to touch - The region coordinates of the position to touch - The surface normal of the position to touch (A normal is a vector perpindicular to the surface) - The surface binormal of the position to touch (A binormal is a vector tangen to the surface - pointing along the U direction of the tangent space - - - - Create (rez) a new prim object in a simulator - - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties - - - - Create (rez) a new prim object in a simulator - - A reference to the object to place the object in - Data describing the prim object to rez - Group ID that this prim will be set to, or UUID.Zero if you - do not want the object to be associated with a specific group - An approximation of the position at which to rez the prim - Scale vector to size this prim - Rotation quaternion to rotate this prim - Specify the - Due to the way client prim rezzing is done on the server, - the requested position for an object is only close to where the prim - actually ends up. If you desire exact placement you'll need to - follow up by moving the object after it has been created. This - function will not set textures, light and flexible data, or other - extended primitive properties - - - - Rez a Linden tree - - A reference to the object where the object resides - The size of the tree - The rotation of the tree - The position of the tree - The Type of tree - The of the group to set the tree to, - or UUID.Zero if no group is to be set - true to use the "new" Linden trees, false to use the old - - - - Rez grass and ground cover - - A reference to the object where the object resides - The size of the grass - The rotation of the grass - The position of the grass - The type of grass from the enum - The of the group to set the tree to, - or UUID.Zero if no group is to be set - - - - Set the textures to apply to the faces of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply - - - - Set the textures to apply to the faces of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The texture data to apply - A media URL (not used) - - - - Set the Light data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set - - - - Set the flexible data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set - - - - Set the sculptie texture and data on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A object containing the data to set - - - - Unset additional primitive parameters on an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The extra parameters to set - - - - Link multiple prims into a linkset - - A reference to the object where the objects reside - An array which contains the IDs of the objects to link - The last object in the array will be the root object of the linkset TODO: Is this true? - - - - Delink/Unlink multiple prims from a linkset - - A reference to the object where the objects reside - An array which contains the IDs of the objects to delink - - - - Change the rotation of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation of the object - - - - Set the name of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new name of the object - - - - Set the name of multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the name of - An array which contains the new names of the objects - - - - Set the description of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - A string containing the new description of the object - - - - Set the descriptions of multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to change the description of - An array which contains the new descriptions of the objects - - - - Attach an object to this avatar - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The point on the avatar the object will be attached - The rotation of the attached object - - - - Drop an attached object from this avatar - - A reference to the - object where the objects reside. This will always be the simulator the avatar is currently in - - The object's ID which is local to the simulator the object is in - - - - Detach an object from yourself - - A reference to the - object where the objects reside - - This will always be the simulator the avatar is currently in - - An array which contains the IDs of the objects to detach - - - - Change the position of an object, Will change position of entire linkset - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object - - - - Change the position of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new position of the object - if true, will change position of (this) child prim only, not entire linkset - - - - Change the Scale (size) of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change scale of this prim only, not entire linkset - True to resize prims uniformly - - - - Change the Rotation of an object that is either a child or a whole linkset - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new scale of the object - If true, will change rotation of this prim only, not entire linkset - - - - Send a Multiple Object Update packet to change the size, scale or rotation of a primitive - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new rotation, size, or position of the target object - The flags from the Enum - - - - Deed an object (prim) to a group, Object must be shared with group which - can be accomplished with SetPermissions() - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The of the group to deed the object to - - - - Deed multiple objects (prims) to a group, Objects must be shared with group which - can be accomplished with SetPermissions() - - A reference to the object where the object resides - An array which contains the IDs of the objects to deed - The of the group to deed the object to - - - - Set the permissions on multiple objects - - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the permissions on - The new Who mask to set - Which permission to modify - The new state of permission - - - - Request additional properties for an object - - A reference to the object where the object resides - - - - - Request additional properties for an object - - A reference to the object where the object resides - Absolute UUID of the object - Whether to require server acknowledgement of this request - - - - Set the ownership of a list of objects to the specified group - - A reference to the object where the objects reside - An array which contains the IDs of the objects to set the group id on - The Groups ID - - - - Update current URL of the previously set prim media - - UUID of the prim - Set current URL to this - Prim face number - Simulator in which prim is located - - - - Set object media - - UUID of the prim - Array the length of prims number of faces. Null on face indexes where there is - no media, on faces which contain the media - Simulatior in which prim is located - - - - Retrieve information about object media - - UUID of the primitive - Simulator where prim is located - Call this callback when done - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - A terse object update, used when a transformation matrix or - velocity/acceleration for an object changes but nothing else - (scale/position/rotation/acceleration/velocity) - - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - - - - - - - - - Setup construction data for a basic primitive shape - - Primitive shape to construct - Construction data that can be plugged into a - - - - - - - - - - - - - - - - - - - - Set the Shape data of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - Data describing the prim shape - - - - Set the Material data of an object - - A reference to the object where the object resides - The objects ID which is local to the simulator the object is in - The new material of the object - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Provides data for the event - The event occurs when the simulator sends - an containing a Primitive, Foliage or Attachment data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same object if for example the primitive moved to a new simulator, then returned to the current simulator or - if an Avatar crosses the border into a new simulator and returns to the current simulator - - - The following code example uses the , , and - properties to display new Primitives and Attachments on the window. - - // Subscribe to the event that gives us prim and foliage information - Client.Objects.ObjectUpdate += Objects_ObjectUpdate; - - - private void Objects_ObjectUpdate(object sender, PrimEventArgs e) - { - Console.WriteLine("Primitive {0} {1} in {2} is an attachment {3}", e.Prim.ID, e.Prim.LocalID, e.Simulator.Name, e.IsAttachment); - } - - - - - - - - Get the simulator the originated from - - - Get the details - - - true if the did not exist in the dictionary before this update (always true if object tracking has been disabled) - - - true if the is attached to an - - - Get the simulator Time Dilation - - - - Construct a new instance of the PrimEventArgs class - - The simulator the object originated from - The Primitive - The simulator time dilation - The prim was not in the dictionary before this update - true if the primitive represents an attachment to an agent - - - Provides data for the event - The event occurs when the simulator sends - an containing Avatar data - Note 1: The event will not be raised when the object is an Avatar - Note 2: It is possible for the to be - raised twice for the same avatar if for example the avatar moved to a new simulator, then returned to the current simulator - - - The following code example uses the property to make a request for the top picks - using the method in the class to display the names - of our own agents picks listings on the window. - - // subscribe to the AvatarUpdate event to get our information - Client.Objects.AvatarUpdate += Objects_AvatarUpdate; - Client.Avatars.AvatarPicksReply += Avatars_AvatarPicksReply; - - private void Objects_AvatarUpdate(object sender, AvatarUpdateEventArgs e) - { - // we only want our own data - if (e.Avatar.LocalID == Client.Self.LocalID) - { - // Unsubscribe from the avatar update event to prevent a loop - // where we continually request the picks every time we get an update for ourselves - Client.Objects.AvatarUpdate -= Objects_AvatarUpdate; - // make the top picks request through AvatarManager - Client.Avatars.RequestAvatarPicks(e.Avatar.ID); - } - } - - private void Avatars_AvatarPicksReply(object sender, AvatarPicksReplyEventArgs e) - { - // we'll unsubscribe from the AvatarPicksReply event since we now have the data - // we were looking for - Client.Avatars.AvatarPicksReply -= Avatars_AvatarPicksReply; - // loop through the dictionary and extract the names of the top picks from our profile - foreach (var pickName in e.Picks.Values) - { - Console.WriteLine(pickName); - } - } - - - - - - - Get the simulator the object originated from - - - Get the data - - - Get the simulator time dilation - - - true if the did not exist in the dictionary before this update (always true if avatar tracking has been disabled) - - - - Construct a new instance of the AvatarUpdateEventArgs class - - The simulator the packet originated from - The data - The simulator time dilation - The avatar was not in the dictionary before this update - - - Get the simulator the object originated from - - - Get the data - - - Get source - - - - Construct a new instance of the ParticleUpdateEventArgs class - - The simulator the packet originated from - The ParticleSystem data - The Primitive source - - - Provides additional primitive data for the event - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment data - The event is also raised when a request is - made. - - - The following code example uses the , and - - properties to display new attachments and send a request for additional properties containing the name of the - attachment then display it on the window. - - // Subscribe to the event that provides additional primitive details - Client.Objects.ObjectProperties += Objects_ObjectProperties; - - // handle the properties data that arrives - private void Objects_ObjectProperties(object sender, ObjectPropertiesEventArgs e) - { - Console.WriteLine("Primitive Properties: {0} Name is {1}", e.Properties.ObjectID, e.Properties.Name); - } - - - - - Get the simulator the object is located - - - Get the primitive properties - - - - Construct a new instance of the ObjectPropertiesEventArgs class - - The simulator the object is located - The primitive Properties - - - Provides additional primitive data for the event - The event occurs when the simulator sends - an containing additional details for a Primitive or Foliage data that is currently - being tracked in the dictionary - The event is also raised when a request is - made and is enabled - - - - Get the primitive details - - - - Construct a new instance of the ObjectPropertiesUpdatedEvenrArgs class - - The simulator the object is located - The Primitive - The primitive Properties - - - Provides additional primitive data, permissions and sale info for the event - The event occurs when the simulator sends - an containing additional details for a Primitive, Foliage data or Attachment. This includes - Permissions, Sale info, and other basic details on an object - The event is also raised when a request is - made, the viewer equivalent is hovering the mouse cursor over an object - - - - Get the simulator the object is located - - - - - - - - - Provides primitive data containing updated location, velocity, rotation, textures for the event - The event occurs when the simulator sends updated location, velocity, rotation, etc - - - - Get the simulator the object is located - - - Get the primitive details - - - - - - - - - - - - - - Get the simulator the object is located - - - Get the primitive details - - - - - - - - - - - - - - - Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the - event - - - Get the simulator the object is located - - - The LocalID of the object - - - Provides notification when an Avatar, Object or Attachment is DeRezzed or moves out of the avatars view for the - event - - - Get the simulator the object is located - - - The LocalID of the object - - - - Provides updates sit position data - - - - Get the simulator the object is located - - - - - - - - - - - - - - - - - Get the simulator the object is located - - - - - - - - - - - - - Indicates if the operation was successful - - - - - Media version string - - - - - Array of media entries indexed by face number - - - - - Set when simulator sends us infomation on primitive's physical properties - - - - Simulator where the message originated - - - Updated physical properties - - - - Constructor - - Simulator where the message originated - Updated physical properties - - - Size of the byte array used to store raw packet data - - - Raw packet data buffer - - - Length of the data to transmit - - - EndPoint of the remote host - - - - Create an allocated UDP packet buffer for receiving a packet - - - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host - - - - Create an allocated UDP packet buffer for sending a packet - - EndPoint of the remote host - Size of the buffer to allocate for packet data - - - - Object pool for packet buffers. This is used to allocate memory for all - incoming and outgoing packets, and zerocoding buffers for those packets - - - - - Initialize the object pool in client mode - - Server to connect to - - - - - - Initialize the object pool in server mode - - - - - - - Returns a packet buffer with EndPoint set if the buffer is in - client mode, or with EndPoint set to null in server mode - - Initialized UDPPacketBuffer object - - - - Default constructor - - - - - Check a packet buffer out of the pool - - A packet buffer object - - - - Returns an instance of the class that has been checked out of the Object Pool. - - - - - Checks the instance back into the object pool - - - - - Creates a new instance of the ObjectPoolBase class. Initialize MUST be called - after using this constructor. - - - - - Creates a new instance of the ObjectPool Base class. - - The object pool is composed of segments, which - are allocated whenever the size of the pool is exceeded. The number of items - in a segment should be large enough that allocating a new segmeng is a rare - thing. For example, on a server that will have 10k people logged in at once, - the receive buffer object pool should have segment sizes of at least 1000 - byte arrays per segment. - - The minimun number of segments that may exist. - Perform a full GC.Collect whenever a segment is allocated, and then again after allocation to compact the heap. - The frequency which segments are checked to see if they're eligible for cleanup. - - - - Forces the segment cleanup algorithm to be run. This method is intended - primarly for use from the Unit Test libraries. - - - - - Responsible for allocate 1 instance of an object that will be stored in a segment. - - An instance of whatever objec the pool is pooling. - - - - Checks in an instance of T owned by the object pool. This method is only intended to be called - by the WrappedObject class. - - The segment from which the instance is checked out. - The instance of T to check back into the segment. - - - - Checks an instance of T from the pool. If the pool is not sufficient to - allow the checkout, a new segment is created. - - A WrappedObject around the instance of T. To check - the instance back into the segment, be sureto dispose the WrappedObject - when finished. - - - - The total number of segments created. Intended to be used by the Unit Tests. - - - - - The number of items that are in a segment. Items in a segment - are all allocated at the same time, and are hopefully close to - each other in the managed heap. - - - - - The minimum number of segments. When segments are reclaimed, - this number of segments will always be left alone. These - segments are allocated at startup. - - - - - The age a segment must be before it's eligible for cleanup. - This is used to prevent thrash, and typical values are in - the 5 minute range. - - - - - The frequence which the cleanup thread runs. This is typically - expected to be in the 5 minute range. - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The ObservableDictionary class is used for storing key/value pairs. It has methods for firing - events to subscribers when items are added, removed, or changed. - - Key - Value - - - - A dictionary of callbacks to fire when specified action occurs - - - - - Register a callback to be fired when an action occurs - - The action - The callback to fire - - - - Unregister a callback - - The action - The callback to fire - - - - - - - - - - Internal dictionary that this class wraps around. Do not - modify or enumerate the contents of this dictionary without locking - - - - Gets the number of Key/Value pairs contained in the - - - - - Initializes a new instance of the Class - with the specified key/value, has the default initial capacity. - - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(); - - - - - - Initializes a new instance of the Class - with the specified key/value, With its initial capacity specified. - - Initial size of dictionary - - - // initialize a new ObservableDictionary named testDict with a string as the key and an int as the value, - // initially allocated room for 10 entries. - public ObservableDictionary<string, int> testDict = new ObservableDictionary<string, int>(10); - - - - - - Try to get entry from the with specified key - - Key to use for lookup - Value returned - if specified key exists, if not found - - - // find your avatar using the Simulator.ObjectsAvatars ObservableDictionary: - Avatar av; - if (Client.Network.CurrentSim.ObjectsAvatars.TryGetValue(Client.Self.AgentID, out av)) - Console.WriteLine("Found Avatar {0}", av.Name); - - - - - - - Finds the specified match. - - The match. - Matched value - - - // use a delegate to find a prim in the ObjectsPrimitives ObservableDictionary - // with the ID 95683496 - uint findID = 95683496; - Primitive findPrim = sim.ObjectsPrimitives.Find( - delegate(Primitive prim) { return prim.ID == findID; }); - - - - - Find All items in an - return matching items. - a containing found items. - - Find All prims within 20 meters and store them in a List - - int radius = 20; - List<Primitive> prims = Client.Network.CurrentSim.ObjectsPrimitives.FindAll( - delegate(Primitive prim) { - Vector3 pos = prim.Position; - return ((prim.ParentID == 0) && (pos != Vector3.Zero) && (Vector3.Distance(pos, location) < radius)); - } - ); - - - - - Find All items in an - return matching keys. - a containing found keys. - - Find All keys which also exist in another dictionary - - List<UUID> matches = myDict.FindAll( - delegate(UUID id) { - return myOtherDict.ContainsKey(id); - } - ); - - - - - Check if Key exists in Dictionary - Key to check for - if found, otherwise - - - Check if Value exists in Dictionary - Value to check for - if found, otherwise - - - - Adds the specified key to the dictionary, dictionary locking is not performed, - - - The key - The value - - - - Removes the specified key, dictionary locking is not performed - - The key. - if successful, otherwise - - - - Indexer for the dictionary - - The key - The value - - - - Clear the contents of the dictionary - - - - - Enumerator for iterating dictionary entries - - - - - - Provides helper methods for parallelizing loops - - - - - Executes a for loop in which iterations may run in parallel - - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop - - - - Executes a for loop in which iterations may run in parallel - - The number of concurrent execution threads to run - The loop will be started at this index - The loop will be terminated before this index is reached - Method body to run for each iteration of the loop - - - - Executes a foreach loop in which iterations may run in parallel - - Object type that the collection wraps - An enumerable collection to iterate over - Method body to run for each object in the collection - - - - Executes a foreach loop in which iterations may run in parallel - - Object type that the collection wraps - The number of concurrent execution threads to run - An enumerable collection to iterate over - Method body to run for each object in the collection - - - - Executes a series of tasks in parallel - - A series of method bodies to execute - - - - Executes a series of tasks in parallel - - The number of concurrent execution threads to run - A series of method bodies to execute - - - - Type of return to use when returning objects from a parcel - - - - - - - Return objects owned by parcel owner - - - Return objects set to group - - - Return objects not owned by parcel owner or set to group - - - Return a specific list of objects on parcel - - - Return objects that are marked for-sale - - - - Blacklist/Whitelist flags used in parcels Access List - - - - Agent is denied access - - - Agent is granted access - - - - The result of a request for parcel properties - - - - No matches were found for the request - - - Request matched a single parcel - - - Request matched multiple parcels - - - - Flags used in the ParcelAccessListRequest packet to specify whether - we want the access list (whitelist), ban list (blacklist), or both - - - - Request the access list - - - Request the ban list - - - Request both White and Black lists - - - - Sequence ID in ParcelPropertiesReply packets (sent when avatar - tries to cross a parcel border) - - - - Parcel is currently selected - - - Parcel restricted to a group the avatar is not a - member of - - - Avatar is banned from the parcel - - - Parcel is restricted to an access list that the - avatar is not on - - - Response to hovering over a parcel - - - - The tool to use when modifying terrain levels - - - - Level the terrain - - - Raise the terrain - - - Lower the terrain - - - Smooth the terrain - - - Add random noise to the terrain - - - Revert terrain to simulator default - - - - The tool size to use when changing terrain levels - - - - Small - - - Medium - - - Large - - - - Reasons agent is denied access to a parcel on the simulator - - - - Agent is not denied, access is granted - - - Agent is not a member of the group set for the parcel, or which owns the parcel - - - Agent is not on the parcels specific allow list - - - Agent is on the parcels ban list - - - Unknown - - - Agent is not age verified and parcel settings deny access to non age verified avatars - - - - Parcel overlay type. This is used primarily for highlighting and - coloring which is why it is a single integer instead of a set of - flags - - These values seem to be poorly thought out. The first three - bits represent a single value, not flags. For example Auction (0x05) is - not a combination of OwnedByOther (0x01) and ForSale(0x04). However, - the BorderWest and BorderSouth values are bit flags that get attached - to the value stored in the first three bits. Bits four, five, and six - are unused - - - Public land - - - Land is owned by another avatar - - - Land is owned by a group - - - Land is owned by the current avatar - - - Land is for sale - - - Land is being auctioned - - - Land is private - - - To the west of this area is a parcel border - - - To the south of this area is a parcel border - - - - Various parcel properties - - - - No flags set - - - Allow avatars to fly (a client-side only restriction) - - - Allow foreign scripts to run - - - This parcel is for sale - - - Allow avatars to create a landmark on this parcel - - - Allows all avatars to edit the terrain on this parcel - - - Avatars have health and can take damage on this parcel. - If set, avatars can be killed and sent home here - - - Foreign avatars can create objects here - - - All objects on this parcel can be purchased - - - Access is restricted to a group - - - Access is restricted to a whitelist - - - Ban blacklist is enabled - - - Unknown - - - List this parcel in the search directory - - - Allow personally owned parcels to be deeded to group - - - If Deeded, owner contributes required tier to group parcel is deeded to - - - Restrict sounds originating on this parcel to the - parcel boundaries - - - Objects on this parcel are sold when the land is - purchsaed - - - Allow this parcel to be published on the web - - - The information for this parcel is mature content - - - The media URL is an HTML page - - - The media URL is a raw HTML string - - - Restrict foreign object pushes - - - Ban all non identified/transacted avatars - - - Allow group-owned scripts to run - - - Allow object creation by group members or group - objects - - - Allow all objects to enter this parcel - - - Only allow group and owner objects to enter this parcel - - - Voice Enabled on this parcel - - - Use Estate Voice channel for Voice on this parcel - - - Deny Age Unverified Users - - - - Parcel ownership status - - - - Placeholder - - - Parcel is leased (owned) by an avatar or group - - - Parcel is in process of being leased (purchased) by an avatar or group - - - Parcel has been abandoned back to Governor Linden - - - - Category parcel is listed in under search - - - - No assigned category - - - Linden Infohub or public area - - - Adult themed area - - - Arts and Culture - - - Business - - - Educational - - - Gaming - - - Hangout or Club - - - Newcomer friendly - - - Parks and Nature - - - Residential - - - Shopping - - - Not Used? - - - Other - - - Not an actual category, only used for queries - - - - Type of teleport landing for a parcel - - - - Unset, simulator default - - - Specific landing point set for this parcel - - - No landing point set, direct teleports enabled for - this parcel - - - - Parcel Media Command used in ParcelMediaCommandMessage - - - - Stop the media stream and go back to the first frame - - - Pause the media stream (stop playing but stay on current frame) - - - Start the current media stream playing and stop when the end is reached - - - Start the current media stream playing, - loop to the beginning when the end is reached and continue to play - - - Specifies the texture to replace with video - If passing the key of a texture, it must be explicitly typecast as a key, - not just passed within double quotes. - - - Specifies the movie URL (254 characters max) - - - Specifies the time index at which to begin playing - - - Specifies a single agent to apply the media command to - - - Unloads the stream. While the stop command sets the texture to the first frame of the movie, - unload resets it to the real texture that the movie was replacing. - - - Turn on/off the auto align feature, similar to the auto align checkbox in the parcel media properties - (NOT to be confused with the "align" function in the textures view of the editor!) Takes TRUE or FALSE as parameter. - - - Allows a Web page or image to be placed on a prim (1.19.1 RC0 and later only). - Use "text/html" for HTML. - - - Resizes a Web page to fit on x, y pixels (1.19.1 RC0 and later only). - This might still not be working - - - Sets a description for the media being displayed (1.19.1 RC0 and later only). - - - - Some information about a parcel of land returned from a DirectoryManager search - - - - Global Key of record - - - Parcel Owners - - - Name field of parcel, limited to 128 characters - - - Description field of parcel, limited to 256 characters - - - Total Square meters of parcel - - - Total area billable as Tier, for group owned land this will be 10% less than ActualArea - - - True of parcel is in Mature simulator - - - Grid global X position of parcel - - - Grid global Y position of parcel - - - Grid global Z position of parcel (not used) - - - Name of simulator parcel is located in - - - Texture of parcels display picture - - - Float representing calculated traffic based on time spent on parcel by avatars - - - Sale price of parcel (not used) - - - Auction ID of parcel - - - - Parcel Media Information - - - - A byte, if 0x1 viewer should auto scale media to fit object - - - A boolean, if true the viewer should loop the media - - - The Asset UUID of the Texture which when applied to a - primitive will display the media - - - A URL which points to any Quicktime supported media type - - - A description of the media - - - An Integer which represents the height of the media - - - An integer which represents the width of the media - - - A string which contains the mime type of the media - - - - Parcel of land, a portion of virtual real estate in a simulator - - - - The total number of contiguous 4x4 meter blocks your agent owns within this parcel - - - The total number of contiguous 4x4 meter blocks contained in this parcel owned by a group or agent other than your own - - - Deprecated, Value appears to always be 0 - - - Simulator-local ID of this parcel - - - UUID of the owner of this parcel - - - Whether the land is deeded to a group or not - - - - - - Date land was claimed - - - Appears to always be zero - - - This field is no longer used - - - Minimum corner of the axis-aligned bounding box for this - parcel - - - Maximum corner of the axis-aligned bounding box for this - parcel - - - Bitmap describing land layout in 4x4m squares across the - entire region - - - Total parcel land area - - - - - - Maximum primitives across the entire simulator owned by the same agent or group that owns this parcel that can be used - - - Total primitives across the entire simulator calculated by combining the allowed prim counts for each parcel - owned by the agent or group that owns this parcel - - - Maximum number of primitives this parcel supports - - - Total number of primitives on this parcel - - - For group-owned parcels this indicates the total number of prims deeded to the group, - for parcels owned by an individual this inicates the number of prims owned by the individual - - - Total number of primitives owned by the parcel group on - this parcel, or for parcels owned by an individual with a group set the - total number of prims set to that group. - - - Total number of prims owned by other avatars that are not set to group, or not the parcel owner - - - A bonus multiplier which allows parcel prim counts to go over times this amount, this does not affect - the max prims per simulator. e.g: 117 prim parcel limit x 1.5 bonus = 175 allowed - - - Autoreturn value in minutes for others' objects - - - - - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it - - - Parcel Name - - - Parcel Description - - - URL For Music Stream - - - - - - Price for a temporary pass - - - How long is pass valid for - - - - - - Key of authorized buyer - - - Key of parcel snapshot - - - The landing point location - - - The landing point LookAt - - - The type of landing enforced from the enum - - - - - - - - - - - - Access list of who is whitelisted on this - parcel - - - Access list of who is blacklisted on this - parcel - - - TRUE of region denies access to age unverified users - - - true to obscure (hide) media url - - - true to obscure (hide) music url - - - A struct containing media details - - - - Displays a parcel object in string format - - string containing key=value pairs of a parcel object - - - - Defalt constructor - - Local ID of this parcel - - - - Update the simulator with any local changes to this Parcel object - - Simulator to send updates to - Whether we want the simulator to confirm - the update with a reply packet or not - - - - Set Autoreturn time - - Simulator to send the update to - - - - Parcel (subdivided simulator lots) subsystem - - - - - Parcel Accesslist - - - - Agents - - - - - - Flags for specific entry in white/black lists - - - - Owners of primitives on parcel - - - - Prim Owners - - - True of owner is group - - - Total count of prims owned by OwnerID - - - true of OwnerID is currently online and is not a group - - - The date of the most recent prim left by OwnerID - - - - Called once parcel resource usage information has been collected - - Indicates if operation was successfull - Parcel resource usage information - - - The event subscribers. null if no subcribers - - - Raises the ParcelDwellReply event - A ParcelDwellReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the ParcelInfoReply event - A ParcelInfoReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the ParcelProperties event - A ParcelPropertiesEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the ParcelAccessListReply event - A ParcelAccessListReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the ParcelObjectOwnersReply event - A ParcelObjectOwnersReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the SimParcelsDownloaded event - A SimParcelsDownloadedEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the ForceSelectObjectsReply event - A ForceSelectObjectsReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a request - - - The event subscribers. null if no subcribers - - - Raises the ParcelMediaUpdateReply event - A ParcelMediaUpdateReplyEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds to a Parcel Update request - - - The event subscribers. null if no subcribers - - - Raises the ParcelMediaCommand event - A ParcelMediaCommandEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the parcel your agent is located sends a ParcelMediaCommand - - - - Default constructor - - A reference to the GridClient object - - - - Request basic information for a single parcel - - Simulator-local ID of the parcel - - - - Request properties of a single parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - multiple simultaneous requests - - - - Request the access list for a single parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - An arbitrary integer that will be returned - with the ParcelAccessList reply, useful for distinguishing between - multiple simultaneous requests - - - - - Request properties of parcels using a bounding box selection - - Simulator containing the parcel - Northern boundary of the parcel selection - Eastern boundary of the parcel selection - Southern boundary of the parcel selection - Western boundary of the parcel selection - An arbitrary integer that will be returned - with the ParcelProperties reply, useful for distinguishing between - different types of parcel property requests - A boolean that is returned with the - ParcelProperties reply, useful for snapping focus to a single - parcel - - - - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - - Simulator to request parcels from (must be connected) - - - - Request all simulator parcel properties (used for populating the Simulator.Parcels - dictionary) - - Simulator to request parcels from (must be connected) - If TRUE, will force a full refresh - Number of milliseconds to pause in between each request - - - - Request the dwell value for a parcel - - Simulator containing the parcel - Simulator-local ID of the parcel - - - - Send a request to Purchase a parcel of land - - The Simulator the parcel is located in - The parcels region specific local ID - true if this parcel is being purchased by a group - The groups - true to remove tier contribution if purchase is successful - The parcels size - The purchase price of the parcel - - - - - Reclaim a parcel of land - - The simulator the parcel is in - The parcels region specific local ID - - - - Deed a parcel to a group - - The simulator the parcel is in - The parcels region specific local ID - The groups - - - - Request prim owners of a parcel of land. - - Simulator parcel is in - The parcels region specific local ID - - - - Return objects from a parcel - - Simulator parcel is in - The parcels region specific local ID - the type of objects to return, - A list containing object owners s to return - - - - Subdivide (split) a parcel - - - - - - - - - - Join two parcels of land creating a single parcel - - - - - - - - - - Get a parcels LocalID - - Simulator parcel is in - Vector3 position in simulator (Z not used) - 0 on failure, or parcel LocalID on success. - A call to Parcels.RequestAllSimParcels is required to populate map and - dictionary. - - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() - - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() - - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - true on successful request sent. - Settings.STORE_LAND_PATCHES must be true, - Parcel information must be downloaded using RequestAllSimParcels() - - - - Terraform (raise, lower, etc) an area or whole parcel of land - - Simulator land area is in. - LocalID of parcel, or -1 if using bounding box - west border of area to modify - south border of area to modify - east border of area to modify - north border of area to modify - From Enum, Raise, Lower, Level, Smooth, Etc. - Size of area to modify - How many meters + or - to lower, 1 = 1 meter - Height at which the terraform operation is acting at - - - - Sends a request to the simulator to return a list of objects owned by specific owners - - Simulator local ID of parcel - Owners, Others, Etc - List containing keys of avatars objects to select; - if List is null will return Objects of type selectType - Response data is returned in the event - - - - Eject and optionally ban a user from a parcel - - target key of avatar to eject - true to also ban target - - - - Freeze or unfreeze an avatar over your land - - target key to freeze - true to freeze, false to unfreeze - - - - Abandon a parcel of land - - Simulator parcel is in - Simulator local ID of parcel - - - - Requests the UUID of the parcel in a remote region at a specified location - - Location of the parcel in the remote region - Remote region handle - Remote region UUID - If successful UUID of the remote parcel, UUID.Zero otherwise - - - - Retrieves information on resources used by the parcel - - UUID of the parcel - Should per object resource usage be requested - Callback invoked when the request is complete - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - Raises the event - - - Contains a parcels dwell data returned from the simulator in response to an - - - Get the global ID of the parcel - - - Get the simulator specific ID of the parcel - - - Get the calculated dwell - - - - Construct a new instance of the ParcelDwellReplyEventArgs class - - The global ID of the parcel - The simulator specific ID of the parcel - The calculated dwell for the parcel - - - Contains basic parcel information data returned from the - simulator in response to an request - - - Get the object containing basic parcel info - - - - Construct a new instance of the ParcelInfoReplyEventArgs class - - The object containing basic parcel info - - - Contains basic parcel information data returned from the simulator in response to an request - - - Get the simulator the parcel is located in - - - Get the object containing the details - If Result is NoData, this object will not contain valid data - - - Get the result of the request - - - Get the number of primitieves your agent is - currently selecting and or sitting on in this parcel - - - Get the user assigned ID used to correlate a request with - these results - - - TODO: - - - - Construct a new instance of the ParcelPropertiesEventArgs class - - The object containing the details - The object containing the details - The result of the request - The number of primitieves your agent is - currently selecting and or sitting on in this parcel - The user assigned ID used to correlate a request with - these results - TODO: - - - Contains blacklist and whitelist data returned from the simulator in response to an request - - - Get the simulator the parcel is located in - - - Get the user assigned ID used to correlate a request with - these results - - - Get the simulator specific ID of the parcel - - - TODO: - - - Get the list containing the white/blacklisted agents for the parcel - - - - Construct a new instance of the ParcelAccessListReplyEventArgs class - - The simulator the parcel is located in - The user assigned ID used to correlate a request with - these results - The simulator specific ID of the parcel - TODO: - The list containing the white/blacklisted agents for the parcel - - - Contains blacklist and whitelist data returned from the - simulator in response to an request - - - Get the simulator the parcel is located in - - - Get the list containing prim ownership counts - - - - Construct a new instance of the ParcelObjectOwnersReplyEventArgs class - - The simulator the parcel is located in - The list containing prim ownership counts - - - Contains the data returned when all parcel data has been retrieved from a simulator - - - Get the simulator the parcel data was retrieved from - - - A dictionary containing the parcel data where the key correlates to the ParcelMap entry - - - Get the multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. - - - - Construct a new instance of the SimParcelsDownloadedEventArgs class - - The simulator the parcel data was retrieved from - The dictionary containing the parcel data - The multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. - - - Contains the data returned when a request - - - Get the simulator the parcel data was retrieved from - - - Get the list of primitive IDs - - - true if the list is clean and contains the information - only for a given request - - - - Construct a new instance of the ForceSelectObjectsReplyEventArgs class - - The simulator the parcel data was retrieved from - The list of primitive IDs - true if the list is clean and contains the information - only for a given request - - - Contains data when the media data for a parcel the avatar is on changes - - - Get the simulator the parcel media data was updated in - - - Get the updated media information - - - - Construct a new instance of the ParcelMediaUpdateReplyEventArgs class - - the simulator the parcel media data was updated in - The updated media information - - - Contains the media command for a parcel the agent is currently on - - - Get the simulator the parcel media command was issued in - - - - - - - - - Get the media command that was sent - - - - - - - Construct a new instance of the ParcelMediaCommandEventArgs class - - The simulator the parcel media command was issued in - - - The media command that was sent - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Class for controlling various system settings. - - Some values are readonly because they affect things that - happen when the GridClient object is initialized, so changing them at - runtime won't do any good. Non-readonly values may affect things that - happen at login or dynamically - - - Main grid login server - - - Beta grid login server - - - The relative directory where external resources are kept - - - Login server to connect to - - - IP Address the client will bind to - - - Use XML-RPC Login or LLSD Login, default is XML-RPC Login - - - - Maximum number of HTTP connections to open to a particular endpoint. - - - An endpoint is defined as a commbination of network address and port. This is used for Caps. - This is a static variable which applies to all instances. - - - - - InventoryManager requests inventory information on login, - GridClient initializes an Inventory store for main inventory. - - - - - InventoryManager requests library information on login, - GridClient initializes an Inventory store for the library. - - - - - Use Caps for fetching inventory where available - - - - Number of milliseconds before an asset transfer will time - out - - - Number of milliseconds before a teleport attempt will time - out - - - Number of milliseconds before NetworkManager.Logout() will - time out - - - Number of milliseconds before a CAPS call will time out - Setting this too low will cause web requests time out and - possibly retry repeatedly - - - Number of milliseconds for xml-rpc to timeout - - - Milliseconds before a packet is assumed lost and resent - - - Milliseconds without receiving a packet before the - connection to a simulator is assumed lost - - - Milliseconds to wait for a simulator info request through - the grid interface - - - Number of milliseconds between sending pings to each sim - - - Number of milliseconds between sending camera updates - - - Number of milliseconds between updating the current - positions of moving, non-accelerating and non-colliding objects - - - Millisecond interval between ticks, where all ACKs are - sent out and the age of unACKed packets is checked - - - The initial size of the packet inbox, where packets are - stored before processing - - - Maximum size of packet that we want to send over the wire - - - The maximum value of a packet sequence number before it - rolls over back to one - - - The maximum size of the sequence number archive, used to - check for resent and/or duplicate packets - - - Maximum number of queued ACKs to be sent before SendAcks() - is forced - - - Network stats queue length (seconds) - - - - Primitives will be reused when falling in/out of interest list (and shared between clients) - prims returning to interest list do not need re-requested - Helps also in not re-requesting prim.Properties for code that checks for a Properties == null per client - - - - - Pool parcel data between clients (saves on requesting multiple times when all clients may need it) - - - - - How long to preserve cached data when no client is connected to a simulator - The reason for setting it to something like 2 minutes is in case a client - is running back and forth between region edges or a sim is comming and going - - - - Enable/disable storing terrain heightmaps in the - TerrainManager - - - Enable/disable sending periodic camera updates - - - Enable/disable automatically setting agent appearance at - login and after sim crossing - - - Enable/disable automatically setting the bandwidth throttle - after connecting to each simulator - The default throttle uses the equivalent of the maximum - bandwidth setting in the official client. If you do not set a - throttle your connection will by default be throttled well below - the minimum values and you may experience connection problems - - - Enable/disable the sending of pings to monitor lag and - packet loss - - - Should we connect to multiple sims? This will allow - viewing in to neighboring simulators and sim crossings - (Experimental) - - - If true, all object update packets will be decoded in to - native objects. If false, only updates for our own agent will be - decoded. Registering an event handler will force objects for that - type to always be decoded. If this is disabled the object tracking - will have missing or partial prim and avatar information - - - If true, when a cached object check is received from the - server the full object info will automatically be requested - - - Whether to establish connections to HTTP capabilities - servers for simulators - - - Whether to decode sim stats - - - The capabilities servers are currently designed to - periodically return a 502 error which signals for the client to - re-establish a connection. Set this to true to log those 502 errors - - - If true, any reference received for a folder or item - the library is not aware of will automatically be fetched - - - If true, and SEND_AGENT_UPDATES is true, - AgentUpdate packets will continuously be sent out to give the bot - smoother movement and autopiloting - - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectAvatars. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received - - - If true, currently visible avatars will be stored - in dictionaries inside Simulator.ObjectPrimitives. - If false, a new Avatar or Primitive object will be created - each time an object update packet is received - - - If true, position and velocity will periodically be - interpolated (extrapolated, technically) for objects and - avatars that are being tracked by the library. This is - necessary to increase the accuracy of speed and position - estimates for simulated objects - - - - If true, utilization statistics will be tracked. There is a minor penalty - in CPU time for enabling this option. - - - - If true, parcel details will be stored in the - Simulator.Parcels dictionary as they are received - - - - If true, an incoming parcel properties reply will automatically send - a request for the parcel access list - - - - - if true, an incoming parcel properties reply will automatically send - a request for the traffic count. - - - - - If true, images, and other assets downloaded from the server - will be cached in a local directory - - - - Path to store cached texture data - - - Maximum size cached files are allowed to take on disk (bytes) - - - Default color used for viewer particle effects - - - Cost of uploading an asset - Read-only since this value is dynamically fetched at login - - - Maximum number of times to resend a failed packet - - - Throttle outgoing packet rate - - - UUID of a texture used by some viewers to indentify type of client used - - - - Download textures using GetTexture capability when available - - - - The maximum number of concurrent texture downloads allowed - Increasing this number will not necessarily increase texture retrieval times due to - simulator throttles - - - - The Refresh timer inteval is used to set the delay between checks for stalled texture downloads - - This is a static variable which applies to all instances - - - - Textures taking longer than this value will be flagged as timed out and removed from the pipeline - - - - - Get or set the minimum log level to output to the console by default - - If the library is not compiled with DEBUG defined and this level is set to DEBUG - You will get no output on the console. This behavior can be overriden by creating - a logger configuration file for log4net - - - - Attach avatar names to log messages - - - Log packet retransmission info - - - Log disk cache misses and other info - - - Constructor - Reference to a GridClient object - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - - Simulator (region) properties - - - - No flags set - - - Agents can take damage and be killed - - - Landmarks can be created here - - - Home position can be set in this sim - - - Home position is reset when an agent teleports away - - - Sun does not move - - - No object, land, etc. taxes - - - Disable heightmap alterations (agents can still plant - foliage) - - - Land cannot be released, sold, or purchased - - - All content is wiped nightly - - - Unknown: Related to the availability of an overview world map tile.(Think mainland images when zoomed out.) - - - Unknown: Related to region debug flags. Possibly to skip processing of agent interaction with world. - - - Region does not update agent prim interest lists. Internal debugging option. - - - No collision detection for non-agent objects - - - No scripts are ran - - - All physics processing is turned off - - - Region can be seen from other regions on world map. (Legacy world map option?) - - - Region can be seen from mainland on world map. (Legacy world map option?) - - - Agents not explicitly on the access list can visit the region. - - - Traffic calculations are not run across entire region, overrides parcel settings. - - - Flight is disabled (not currently enforced by the sim) - - - Allow direct (p2p) teleporting - - - Estate owner has temporarily disabled scripting - - - Restricts the usage of the LSL llPushObject function, applies to whole region. - - - Deny agents with no payment info on file - - - Deny agents with payment info on file - - - Deny agents who have made a monetary transaction - - - Parcels within the region may be joined or divided by anyone, not just estate owners/managers. - - - Abuse reports sent from within this region are sent to the estate owner defined email. - - - Region is Voice Enabled - - - Removes the ability from parcel owners to set their parcels to show in search. - - - Deny agents who have not been age verified from entering the region. - - - - Region protocol flags - - - - Nothing special - - - Region supports Server side Appearance - - - Viewer supports Server side Appearance - - - - Access level for a simulator - - - - Unknown or invalid access level - - - Trial accounts allowed - - - PG rating - - - Mature rating - - - Adult rating - - - Simulator is offline - - - Simulator does not exist - - - - - - - - - Simulator Statistics - - - - Total number of packets sent by this simulator to this agent - - - Total number of packets received by this simulator to this agent - - - Total number of bytes sent by this simulator to this agent - - - Total number of bytes received by this simulator to this agent - - - Time in seconds agent has been connected to simulator - - - Total number of packets that have been resent - - - Total number of resent packets recieved - - - Total number of pings sent to this simulator by this agent - - - Total number of ping replies sent to this agent by this simulator - - - - Incoming bytes per second - - It would be nice to have this claculated on the fly, but - this is far, far easier - - - - Outgoing bytes per second - - It would be nice to have this claculated on the fly, but - this is far, far easier - - - Time last ping was sent - - - ID of last Ping sent - - - - - - - - - Current time dilation of this simulator - - - Current Frames per second of simulator - - - Current Physics frames per second of simulator - - - - - - - - - - - - - - - - - - - - - - - - - - - Total number of objects Simulator is simulating - - - Total number of Active (Scripted) objects running - - - Number of agents currently in this simulator - - - Number of agents in neighbor simulators - - - Number of Active scripts running in this simulator - - - - - - - - - - - - Number of downloads pending - - - Number of uploads pending - - - - - - - - - Number of local uploads pending - - - Unacknowledged bytes in queue - - - A public reference to the client that this Simulator object - is attached to - - - A Unique Cache identifier for this simulator - - - The capabilities for this simulator - - - - - - The current version of software this simulator is running - - - - - - A 64x64 grid of parcel coloring values. The values stored - in this array are of the type - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true if your agent has Estate Manager rights on this region - - - - - - - - - - - - Statistics information for this simulator and the - connection to the simulator, calculated by the simulator itself - and the library - - - The regions Unique ID - - - The physical data center the simulator is located - Known values are: - - Dallas - Chandler - SF - - - - - The CPU Class of the simulator - Most full mainland/estate sims appear to be 5, - Homesteads and Openspace appear to be 501 - - - The number of regions sharing the same CPU as this one - "Full Sims" appear to be 1, Homesteads appear to be 4 - - - The billing product name - Known values are: - - Mainland / Full Region (Sku: 023) - Estate / Full Region (Sku: 024) - Estate / Openspace (Sku: 027) - Estate / Homestead (Sku: 029) - Mainland / Homestead (Sku: 129) (Linden Owned) - Mainland / Linden Homes (Sku: 131) - - - - - The billing product SKU - Known values are: - - 023 Mainland / Full Region - 024 Estate / Full Region - 027 Estate / Openspace - 029 Estate / Homestead - 129 Mainland / Homestead (Linden Owned) - 131 Linden Homes / Full Region - - - - - - Flags indicating which protocols this region supports - - - - The current sequence number for packets sent to this - simulator. Must be Interlocked before modifying. Only - useful for applications manipulating sequence numbers - - - - A thread-safe dictionary containing avatars in a simulator - - - - - A thread-safe dictionary containing primitives in a simulator - - - - - Provides access to an internal thread-safe dictionary containing parcel - information found in this simulator - - - - - Provides access to an internal thread-safe multidimensional array containing a x,y grid mapped - to each 64x64 parcel's LocalID. - - - - - Checks simulator parcel map to make sure it has downloaded all data successfully - - true if map is full (contains no 0's) - - - - Is it safe to send agent updates to this sim - AgentMovementComplete message received - - - - The IP address and port of the server - - - Whether there is a working connection to the simulator or - not - - - Coarse locations of avatars in this simulator - - - AvatarPositions key representing TrackAgent target - - - Indicates if UDP connection to the sim is fully established - - - Used internally to track sim disconnections - - - Event that is triggered when the simulator successfully - establishes a connection - - - Whether this sim is currently connected or not. Hooked up - to the property Connected - - - Coarse locations of avatars in this simulator - - - AvatarPositions key representing TrackAgent target - - - Sequence numbers of packets we've received - (for duplicate checking) - - - Packets we sent out that need ACKs from the simulator - - - Sequence number for pause/resume - - - Indicates if UDP connection to the sim is fully established - - - - - - Reference to the GridClient object - IPEndPoint of the simulator - handle of the simulator - - - - Called when this Simulator object is being destroyed - - - - - Attempt to connect to this simulator - - Whether to move our agent in to this sim or not - True if the connection succeeded or connection status is - unknown, false if there was a failure - - - - Initiates connection to the simulator - - Should we block until ack for this packet is recieved - - - - Disconnect from this simulator - - - - - Instructs the simulator to stop sending update (and possibly other) packets - - - - - Instructs the simulator to resume sending update packets (unpause) - - - - - Retrieve the terrain height at a given coordinate - - Sim X coordinate, valid range is from 0 to 255 - Sim Y coordinate, valid range is from 0 to 255 - The terrain height at the given point if the - lookup was successful, otherwise 0.0f - True if the lookup was successful, otherwise false - - - - Sends a packet - - Packet to be sent - - - - - - - - - Returns Simulator Name as a String - - - - - - - - - - - - - - - - - - - Sends out pending acknowledgements - - Number of ACKs sent - - - - Resend unacknowledged packets - - - - - Simulator handle - - - - - Number of GridClients using this datapool - - - - - Time that the last client disconnected from the simulator - - - - - The cache of prims used and unused in this simulator - - - - - Shared parcel info only when POOL_PARCEL_DATA == true - - - - - - - - - The event subscribers, null of no subscribers - - - Raises the AttachedSound Event - A AttachedSoundEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - sound - - - The event subscribers, null of no subscribers - - - Raises the AttachedSoundGainChange Event - A AttachedSoundGainChangeEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the SoundTrigger Event - A SoundTriggerEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - The event subscribers, null of no subscribers - - - Raises the PreloadSound Event - A PreloadSoundEventArgs object containing - the data sent from the simulator - - - Thread sync lock object - - - Raised when the simulator sends us data containing - ... - - - - Construct a new instance of the SoundManager class, used for playing and receiving - sound assets - - A reference to the current GridClient instance - - - - Plays a sound in the current region at full volume from avatar position - - UUID of the sound to be played - - - - Plays a sound in the current region at full volume - - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - - - - Plays a sound in the current region - - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 - - - - Plays a sound in the specified sim - - UUID of the sound to be played. - UUID of the sound to be played. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 - - - - Play a sound asset - - UUID of the sound to be played. - handle id for the sim to be played in. - position for the sound to be played at. Normally the avatar. - volume of the sound, from 0.0 to 1.0 - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Process an incoming packet and raise the appropriate events - The sender - The EventArgs object containing the packet data - - - Provides data for the event - The event occurs when the simulator sends - the sound data which emits from an agents attachment - - The following code example shows the process to subscribe to the event - and a stub to handle the data passed from the simulator - - // Subscribe to the AttachedSound event - Client.Sound.AttachedSound += Sound_AttachedSound; - - // process the data raised in the event here - private void Sound_AttachedSound(object sender, AttachedSoundEventArgs e) - { - // ... Process AttachedSoundEventArgs here ... - } - - - - - Simulator where the event originated - - - Get the sound asset id - - - Get the ID of the owner - - - Get the ID of the Object - - - Get the volume level - - - Get the - - - - Construct a new instance of the SoundTriggerEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object - The volume level - The - - - Provides data for the event - The event occurs when an attached sound - changes its volume level - - - Simulator where the event originated - - - Get the ID of the Object - - - Get the volume level - - - - Construct a new instance of the AttachedSoundGainChangedEventArgs class - - Simulator where the event originated - The ID of the Object - The new volume level - - - Provides data for the event - The event occurs when the simulator forwards - a request made by yourself or another agent to play either an asset sound or a built in sound - - Requests to play sounds where the is not one of the built-in - will require sending a request to download the sound asset before it can be played - - - The following code example uses the , - and - properties to display some information on a sound request on the window. - - // subscribe to the event - Client.Sound.SoundTrigger += Sound_SoundTrigger; - - // play the pre-defined BELL_TING sound - Client.Sound.SendSoundTrigger(Sounds.BELL_TING); - - // handle the response data - private void Sound_SoundTrigger(object sender, SoundTriggerEventArgs e) - { - Console.WriteLine("{0} played the sound {1} at volume {2}", - e.OwnerID, e.SoundID, e.Gain); - } - - - - - Simulator where the event originated - - - Get the sound asset id - - - Get the ID of the owner - - - Get the ID of the Object - - - Get the ID of the objects parent - - - Get the volume level - - - Get the regionhandle - - - Get the source position - - - - Construct a new instance of the SoundTriggerEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object - The ID of the objects parent - The volume level - The regionhandle - The source position - - - Provides data for the event - The event occurs when the simulator sends - the appearance data for an avatar - - The following code example uses the and - properties to display the selected shape of an avatar on the window. - - // subscribe to the event - Client.Avatars.AvatarAppearance += Avatars_AvatarAppearance; - - // handle the data when the event is raised - void Avatars_AvatarAppearance(object sender, AvatarAppearanceEventArgs e) - { - Console.WriteLine("The Agent {0} is using a {1} shape.", e.AvatarID, (e.VisualParams[31] > 0) : "male" ? "female") - } - - - - - Simulator where the event originated - - - Get the sound asset id - - - Get the ID of the owner - - - Get the ID of the Object - - - - Construct a new instance of the PreloadSoundEventArgs class - - Simulator where the event originated - The sound asset id - The ID of the owner - The ID of the object - - - - pre-defined built in sounds - - - - - - - - - - - - - - - - - - - - - - - - - - - - coins - - - cash register bell - - - - - - - - - rubber - - - plastic - - - flesh - - - wood splintering? - - - glass break - - - metal clunk - - - whoosh - - - shake - - - - - - ding - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - A dictionary containing all pre-defined sounds - - A dictionary containing the pre-defined sounds, - where the key is the sounds ID, and the value is a string - containing a name to identify the purpose of the sound - - - X position of this patch - - - Y position of this patch - - - A 16x16 array of floats holding decompressed layer data - - - - Creates a LayerData packet for compressed land data given a full - simulator heightmap and an array of indices of patches to compress - - A 256 * 256 array of floating point values - specifying the height at each meter in the simulator - Array of indexes in the 16x16 grid of patches - for this simulator. For example if 1 and 17 are specified, patches - x=1,y=0 and x=1,y=1 are sent - - - - - Add a patch of terrain to a BitPacker - - BitPacker to write the patch to - Heightmap of the simulator, must be a 256 * - 256 float array - X offset of the patch to create, valid values are - from 0 to 15 - Y offset of the patch to create, valid values are - from 0 to 15 - - - The event subscribers. null if no subcribers - - - Raises the LandPatchReceived event - A LandPatchReceivedEventArgs object containing the - data returned from the simulator - - - Thread sync lock object - - - Raised when the simulator responds sends - - - - Default constructor - - - - - Simulator from that sent tha data - - - Sim coordinate of the patch - - - Sim coordinate of the patch - - - Size of tha patch - - - Heightmap for the patch - - - - The current status of a texture request as it moves through the pipeline or final result of a texture request. - - - - The initial state given to a request. Requests in this state - are waiting for an available slot in the pipeline - - - A request that has been added to the pipeline and the request packet - has been sent to the simulator - - - A request that has received one or more packets back from the simulator - - - A request that has received all packets back from the simulator - - - A request that has taken longer than - to download OR the initial packet containing the packet information was never received - - - The texture request was aborted by request of the agent - - - The simulator replied to the request that it was not able to find the requested texture - - - - A callback fired to indicate the status or final state of the requested texture. For progressive - downloads this will fire each time new asset data is returned from the simulator. - - The indicating either Progress for textures not fully downloaded, - or the final result of the request after it has been processed through the TexturePipeline - The object containing the Assets ID, raw data - and other information. For progressive rendering the will contain - the data from the beginning of the file. For failed, aborted and timed out requests it will contain - an empty byte array. - - - - Texture request download handler, allows a configurable number of download slots which manage multiple - concurrent texture downloads from the - - This class makes full use of the internal - system for full texture downloads. - - - - A request task containing information and status of a request as it is processed through the - - - - The current which identifies the current status of the request - - - The Unique Request ID, This is also the Asset ID of the texture being requested - - - The slot this request is occupying in the threadpoolSlots array - - - The ImageType of the request. - - - The callback to fire when the request is complete, will include - the and the - object containing the result data - - - If true, indicates the callback will be fired whenever new data is returned from the simulator. - This is used to progressively render textures as portions of the texture are received. - - - An object that maintains the data of an request thats in-process. - - - A dictionary containing all pending and in-process transfer requests where the Key is both the RequestID - and also the Asset Texture ID, and the value is an object containing the current state of the request and also - the asset data as it is being re-assembled - - - Holds the reference to the client object - - - Maximum concurrent texture requests allowed at a time - - - An array of objects used to manage worker request threads - - - An array of worker slots which shows the availablity status of the slot - - - The primary thread which manages the requests. - - - true if the TexturePipeline is currently running - - - A synchronization object used by the primary thread - - - A refresh timer used to increase the priority of stalled requests - - - Current number of pending and in-process transfers - - - - Default constructor, Instantiates a new copy of the TexturePipeline class - - Reference to the instantiated object - - - - Initialize callbacks required for the TexturePipeline to operate - - - - - Shutdown the TexturePipeline and cleanup any callbacks or transfers - - - - - Request a texture asset from the simulator using the system to - manage the requests and re-assemble the image from the packets received from the simulator - - The of the texture asset to download - The of the texture asset. - Use for most textures, or for baked layer texture assets - A float indicating the requested priority for the transfer. Higher priority values tell the simulator - to prioritize the request before lower valued requests. An image already being transferred using the can have - its priority changed by resending the request with the new priority value - Number of quality layers to discard. - This controls the end marker of the data sent - The packet number to begin the request at. A value of 0 begins the request - from the start of the asset texture - The callback to fire when the image is retrieved. The callback - will contain the result of the request and the texture asset data - If true, the callback will be fired for each chunk of the downloaded image. - The callback asset parameter will contain all previously received chunks of the texture asset starting - from the beginning of the request - - - - Sends the actual request packet to the simulator - - The image to download - Type of the image to download, either a baked - avatar texture or a normal texture - Priority level of the download. Default is - 1,013,000.0f - Number of quality layers to discard. - This controls the end marker of the data sent - Packet number to start the download at. - This controls the start marker of the data sent - Sending a priority of 0 and a discardlevel of -1 aborts - download - - - - Cancel a pending or in process texture request - - The texture assets unique ID - - - - Master Download Thread, Queues up downloads in the threadpool - - - - - The worker thread that sends the request and handles timeouts - - A object containing the request details - - - - Handle responses from the simulator that tell us a texture we have requested is unable to be located - or no longer exists. This will remove the request from the pipeline and free up a slot if one is in use - - The sender - The EventArgs object containing the packet data - - - - Handles the remaining Image data that did not fit in the initial ImageData packet - - The sender - The EventArgs object containing the packet data - - - - Handle the initial ImageDataPacket sent from the simulator - - The sender - The EventArgs object containing the packet data - - - - - - - - - Initialize the UDP packet handler in server mode - - Port to listening for incoming UDP packets on - - - - Initialize the UDP packet handler in client mode - - Remote UDP server to connect to - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Operation to apply when applying color to texture - - - - - Information needed to translate visual param value to RGBA color - - - - - Construct VisualColorParam - - Operation to apply when applying color to texture - Colors - - - - Represents alpha blending and bump infor for a visual parameter - such as sleive length - - - - Stregth of the alpha to apply - - - File containing the alpha channel - - - Skip blending if parameter value is 0 - - - Use miltiply insted of alpha blending - - - - Create new alhpa information for a visual param - - Stregth of the alpha to apply - File containing the alpha channel - Skip blending if parameter value is 0 - Use miltiply insted of alpha blending - - - - A single visual characteristic of an avatar mesh, such as eyebrow height - - - - Index of this visual param - - - Internal name - - - Group ID this parameter belongs to - - - Name of the wearable this parameter belongs to - - - Displayable label of this characteristic - - - Displayable label for the minimum value of this characteristic - - - Displayable label for the maximum value of this characteristic - - - Default value - - - Minimum value - - - Maximum value - - - Is this param used for creation of bump layer? - - - Alpha blending/bump info - - - Color information - - - Array of param IDs that are drivers for this parameter - - - - Set all the values through the constructor - - Index of this visual param - Internal name - - - Displayable label of this characteristic - Displayable label for the minimum value of this characteristic - Displayable label for the maximum value of this characteristic - Default value - Minimum value - Maximum value - Is this param used for creation of bump layer? - Array of param IDs that are drivers for this parameter - Alpha blending/bump info - Color information - - - - Holds the Params array of all the avatar appearance parameters - - - - - Base class for all Asset types - - - - A byte array containing the raw asset data - - - True if the asset it only stored on the server temporarily - - - A unique ID - - - The assets unique ID - - - - The "type" of asset, Notecard, Animation, etc - - - - - Construct a new Asset object - - - - - Construct a new Asset object - - A unique specific to this asset - A byte array containing the raw asset data - - - - Regenerates the AssetData byte array from the properties - of the derived class. - - - - - Decodes the AssetData, placing it in appropriate properties of the derived - class. - - True if the asset decoding succeeded, otherwise false - - - - Constants for the archiving module - - - - - The location of the archive control file - - - - - Path for the assets held in an archive - - - - - Path for the prims file - - - - - Path for terrains. Technically these may be assets, but I think it's quite nice to split them out. - - - - - Path for region settings. - - - - - Path for region settings. - - - - - The character the separates the uuid from extension information in an archived asset filename - - - - - Extensions used for asset types in the archive - - - - - Archives assets - - - - - Archive assets - - - - - Archive the assets given to this archiver to the given archive. - - - - - - Write an assets metadata file to the given archive - - - - - - Write asset data files to the given archive - - - - - - Temporary code to do the bare minimum required to read a tar archive for our purposes - - - - - Binary reader for the underlying stream - - - - - Used to trim off null chars - - - - - Used to trim off space chars - - - - - Generate a tar reader which reads from the given stream. - - - - - - Read the next entry in the tar file. - - - - the data for the entry. Returns null if there are no more entries - - - - Read the next 512 byte chunk of data as a tar header. - - A tar header struct. null if we have reached the end of the archive. - - - - Read data following a header - - - - - - - Convert octal bytes to a decimal representation - - - - - - - - - Temporary code to produce a tar archive in tar v7 format - - - - - Binary writer for the underlying stream - - - - - Write a directory entry to the tar archive. We can only handle one path level right now! - - - - - - Write a file to the tar archive - - - - - - - Write a file to the tar archive - - - - - - - Finish writing the raw tar archive data to a stream. The stream will be closed on completion. - - - - - Write a particular entry - - - - - - - - Represents an Animation - - - - Override the base classes AssetType - - - Default Constructor - - - - Construct an Asset object of type Animation - - A unique specific to this asset - A byte array containing the raw asset data - - - - Represents an that represents an avatars body ie: Hair, Etc. - - - - Override the base classes AssetType - - - Initializes a new instance of an AssetBodyPart object - - - Initializes a new instance of an AssetBodyPart object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - - Represents a Callingcard with AvatarID and Position vector - - - - Override the base classes AssetType - - - UUID of the Callingcard target avatar - - - Construct an Asset of type Callingcard - - - - Construct an Asset object of type Callingcard - - A unique specific to this asset - A byte array containing the raw asset data - - - - Constuct an asset of type Callingcard - - UUID of the target avatar - - - - Encode the raw contents of a string with the specific Callingcard format - - - - - Decode the raw asset data, populating the AvatarID and Position - - true if the AssetData was successfully decoded to a UUID and Vector - - - - Represents an that can be worn on an avatar - such as a Shirt, Pants, etc. - - - - Override the base classes AssetType - - - Initializes a new instance of an AssetScriptBinary object - - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - - Type of gesture step - - - - - Base class for gesture steps - - - - - Retururns what kind of gesture step this is - - - - - Describes animation step of a gesture - - - - - Returns what kind of gesture step this is - - - - - If true, this step represents start of animation, otherwise animation stop - - - - - Animation asset - - - - - Animation inventory name - - - - - Describes sound step of a gesture - - - - - Returns what kind of gesture step this is - - - - - Sound asset - - - - - Sound inventory name - - - - - Describes sound step of a gesture - - - - - Returns what kind of gesture step this is - - - - - Text to output in chat - - - - - Describes sound step of a gesture - - - - - Returns what kind of gesture step this is - - - - - If true in this step we wait for all animations to finish - - - - - If true gesture player should wait for the specified amount of time - - - - - Time in seconds to wait if WaitForAnimation is false - - - - - Describes the final step of a gesture - - - - - Returns what kind of gesture step this is - - - - - Represents a sequence of animations, sounds, and chat actions - - - - - Returns asset type - - - - - Keyboard key that triggers the gestyre - - - - - Modifier to the trigger key - - - - - String that triggers playing of the gesture sequence - - - - - Text that replaces trigger in chat once gesture is triggered - - - - - Sequence of gesture steps - - - - - Constructs guesture asset - - - - - Constructs guesture asset - - A unique specific to this asset - A byte array containing the raw asset data - - - - Encodes gesture asset suitable for uplaod - - - - - Decodes gesture assset into play sequence - - true if the asset data was decoded successfully - - - - Represents a Landmark with RegionID and Position vector - - - - Override the base classes AssetType - - - UUID of the Landmark target region - - - Local position of the target - - - Construct an Asset of type Landmark - - - - Construct an Asset object of type Landmark - - A unique specific to this asset - A byte array containing the raw asset data - - - - Encode the raw contents of a string with the specific Landmark format - - - - - Decode the raw asset data, populating the RegionID and Position - - true if the AssetData was successfully decoded to a UUID and Vector - - - - Represents Mesh asset - - - - Override the base classes AssetType - - - - Decoded mesh data - - - - Initializes a new instance of an AssetMesh object - - - Initializes a new instance of an AssetMesh object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - - TODO: Encodes Collada file into LLMesh format - - - - - Decodes mesh asset. See - to furter decode it for rendering - true - - - - Represents an Animation - - - - Override the base classes AssetType - - - Default Constructor - - - - Construct an Asset object of type Animation - - Asset type - A unique specific to this asset - A byte array containing the raw asset data - - - - Represents a string of characters encoded with specific formatting properties - - - - Override the base classes AssetType - - - A text string containing main text of the notecard - - - List of s embedded on the notecard - - - Construct an Asset of type Notecard - - - - Construct an Asset object of type Notecard - - A unique specific to this asset - A byte array containing the raw asset data - - - - Encode the raw contents of a string with the specific Linden Text properties - - - - - Decode the raw asset data including the Linden Text properties - - true if the AssetData was successfully decoded - - - - A linkset asset, containing a parent primitive and zero or more children - - - - - Only used internally for XML serialization/deserialization - - - - Override the base classes AssetType - - - Initializes a new instance of an AssetPrim object - - - - Initializes a new instance of an AssetPrim object - - A unique specific to this asset - A byte array containing the raw asset data - - - - - - - - - - - - - - - The deserialized form of a single primitive in a linkset asset - - - - - Represents an AssetScriptBinary object containing the - LSO compiled bytecode of an LSL script - - - - Override the base classes AssetType - - - Initializes a new instance of an AssetScriptBinary object - - - Initializes a new instance of an AssetScriptBinary object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - - TODO: Encodes a scripts contents into a LSO Bytecode file - - - - - TODO: Decode LSO Bytecode into a string - - true - - - - Represents an LSL Text object containing a string of UTF encoded characters - - - - Override the base classes AssetType - - - A string of characters represting the script contents - - - Initializes a new AssetScriptText object - - - - Initializes a new AssetScriptText object with parameters - - A unique specific to this asset - A byte array containing the raw asset data - - - - Encode a string containing the scripts contents into byte encoded AssetData - - - - - Decode a byte array containing the scripts contents into a string - - true if decoding is successful - - - - Represents a Sound Asset - - - - Override the base classes AssetType - - - Initializes a new instance of an AssetSound object - - - Initializes a new instance of an AssetSound object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - - TODO: Encodes a sound file - - - - - TODO: Decode a sound file - - true - - - - Represents a texture - - - - Override the base classes AssetType - - - A object containing image data - - - - - - - - - Initializes a new instance of an AssetTexture object - - - - Initializes a new instance of an AssetTexture object - - A unique specific to this asset - A byte array containing the raw asset data - - - - Initializes a new instance of an AssetTexture object - - A object containing texture data - - - - Populates the byte array with a JPEG2000 - encoded image created from the data in - - - - - Decodes the JPEG2000 data in AssetData to the - object - - True if the decoding was successful, otherwise false - - - - Decodes the begin and end byte positions for each quality layer in - the image - - - - - - Represents a Wearable Asset, Clothing, Hair, Skin, Etc - - - - A string containing the name of the asset - - - A string containing a short description of the asset - - - The Assets WearableType - - - The For-Sale status of the object - - - An Integer representing the purchase price of the asset - - - The of the assets creator - - - The of the assets current owner - - - The of the assets prior owner - - - The of the Group this asset is set to - - - True if the asset is owned by a - - - The Permissions mask of the asset - - - A Dictionary containing Key/Value pairs of the objects parameters - - - A Dictionary containing Key/Value pairs where the Key is the textures Index and the Value is the Textures - - - Initializes a new instance of an AssetWearable object - - - Initializes a new instance of an AssetWearable object with parameters - A unique specific to this asset - A byte array containing the raw asset data - - - - Decode an assets byte encoded data to a string - - true if the asset data was decoded successfully - - - - Encode the assets string represantion into a format consumable by the asset server - - - - = - - - Number of times we've received an unknown CAPS exception in series. - - - For exponential backoff on error. - - - - A set of textures that are layered on texture of each other and "baked" - in to a single texture, for avatar appearances - - - - Final baked texture - - - Component layers - - - Width of the final baked image and scratchpad - - - Height of the final baked image and scratchpad - - - Bake type - - - Is this one of the 3 skin bakes - - - Final baked texture - - - Component layers - - - Width of the final baked image and scratchpad - - - Height of the final baked image and scratchpad - - - Bake type - - - - Default constructor - - Bake type - - - - Adds layer for baking - - TexturaData struct that contains texture and its params - - - - Converts avatar texture index (face) to Bake type - - Face number (AvatarTextureIndex) - BakeType, layer to which this texture belongs to - - - - Make sure images exist, resize source if needed to match the destination - - Destination image - Source image - Sanitization was succefull - - - - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color - - Color of the base of this layer - - - - Fills a baked layer as a solid *appearing* color. The colors are - subtly dithered on a 16x16 grid to prevent the JPEG2000 stage from - compressing it too far since it seems to cause upload failures if - the image is a pure solid color - - Red value - Green value - Blue value - - - - Image width - - - - - Image height - - - - - Image channel flags - - - - - Red channel data - - - - - Green channel data - - - - - Blue channel data - - - - - Alpha channel data - - - - - Bump channel data - - - - - Create a new blank image - - width - height - channel flags - - - - - - - - - - Convert the channels in the image. Channels are created or destroyed as required. - - new channel flags - - - - Resize or stretch the image using nearest neighbor (ugly) resampling - - new width - new height - - - - Create a byte array containing 32-bit RGBA data with a bottom-left - origin, suitable for feeding directly into OpenGL - - A byte array containing raw texture data - - - - Create a byte array containing 32-bit RGBA data with a bottom-left - origin, suitable for feeding directly into OpenGL - - A byte array containing raw texture data - - - - A Wrapper around openjpeg to encode and decode images to and from byte arrays - - - - TGA Header size - - - - Defines the beginning and ending file positions of a layer in an - LRCP-progression JPEG2000 file - - - - - This structure is used to marshal both encoded and decoded images. - MUST MATCH THE STRUCT IN dotnet.h! - - - - - Information about a single packet in a JPEG2000 stream - - - - Packet start position - - - Packet header end position - - - Packet end position - - - OpenJPEG is not threadsafe, so this object is used to lock - during calls into unmanaged code - - - - Encode a object into a byte array - - The object to encode - true to enable lossless conversion, only useful for small images ie: sculptmaps - A byte array containing the encoded Image object - - - - Encode a object into a byte array - - The object to encode - a byte array of the encoded image - - - - Decode JPEG2000 data to an and - - - JPEG2000 encoded data - ManagedImage object to decode to - Image object to decode to - True if the decode succeeds, otherwise false - - - - - - - - - - - - - - - - - - - - - Encode a object into a byte array - - The source object to encode - true to enable lossless decoding - A byte array containing the source Bitmap object - - - - Capability to load TGAs to Bitmap - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Parsing Collada model files into data structures - - - - - Parses Collada document - - Load .dae model from this file - Load and decode images for uploading with model - A list of mesh prims that were parsed from the collada file - - - - Implements mesh upload communications with the simulator - - - - - Inlcude stub convex hull physics, required for uploading to Second Life - - - - - Use the same mesh used for geometry as the physical mesh upload - - - - - Callback for mesh upload operations - - null on failure, result from server on success - - - - Creates instance of the mesh uploader - - GridClient instance to communicate with the simulator - List of ModelPrimitive objects to upload as a linkset - Inventory name for newly uploaded object - Inventory description for newly upload object - - - - Performs model upload in one go, without first checking for the price - - - - - Performs model upload in one go, without first checking for the price - - Callback that will be invoke upon completion of the upload. Null is sent on request failure - - - - Ask server for details of cost and impact of the mesh upload - - Callback that will be invoke upon completion of the upload. Null is sent on request failure - - - - Performas actual mesh and image upload - - Uri recieved in the upload prepare stage - Callback that will be invoke upon completion of the upload. Null is sent on request failure - - - - Interface requirements for Messaging system - - - - - Abstract base for rendering plugins - - - - - Generates a basic mesh structure from a primitive - - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh - - - - Generates a basic mesh structure from a sculpted primitive and - texture - - Sculpted primitive to generate the mesh from - Sculpt texture - Level of detail to generate the mesh at - The generated mesh - - - - Generates a series of faces, each face containing a mesh and - metadata - - Primitive to generate the mesh from - Level of detail to generate the mesh at - The generated mesh - - - - Generates a series of faces for a sculpted prim, each face - containing a mesh and metadata - - Sculpted primitive to generate the mesh from - Sculpt texture - Level of detail to generate the mesh at - The generated mesh - - - - Apply texture coordinate modifications from a - to a list of vertices - - Vertex list to modify texture coordinates for - Center-point of the face - Face texture parameters - Scale of the prim - - - - Binary reader, which is endian aware - - - - What is the format of the source file - - - - Construct a reader from a stream - - The stream to read from - - - - Construct a reader from a stream - - The stream to read from - What is the format of the file, assumes PC and similar architecture - - - - Read a 32 bit integer - - A 32 bit integer in the system's endianness - - - - Read a 16 bit integer - - A 16 bit integer in the system's endianness - - - - Read a 64 bit integer - - A 64 bit integer in the system's endianness - - - - Read an unsigned 32 bit integer - - A 32 bit unsigned integer in the system's endianness - - - - Read a single precision floating point value - - A single precision floating point value in the system's endianness - - - - Read a double precision floating point value - - A double precision floating point value in the system's endianness - - - - Read a UTF-8 string - - A standard system string - - - - Read a UTF-8 string - - length of string to read - A standard system string - - - - Load and handle Linden Lab binary meshes. - - - The exact definition of this file is a bit sketchy, especially concerning skin weights. - A good starting point is on the - second life wiki - - - - - Defines a polygon - - - - - Structure of a vertex, No surprises there, except for the Detail tex coord - - - The skinweights are a tad unconventional. The best explanation found is: - >Each weight actually contains two pieces of information. The number to the - >left of the decimal point is the index of the joint and also implicitly - >indexes to the following joint. The actual weight is to the right of the - >decimal point and interpolates between these two joints. The index is into - >an "expanded" list of joints, not just a linear array of the joints as - >defined in the skeleton file. In particular, any joint that has more than - >one child will be repeated in the list for each of its children. - - Maybe I'm dense, but that description seems to be a bit hard to build an - algorithm on. - - Esentially the weights are compressed into one floating point value. - 1. The whole number part is an index into an array of joints - 2. The fractional part is the weight that joint has - 3. If the fractional part is 0 (x.0000) then the vertex is 100% influenced by the specified joint - - - - - Provide a nice format for debugging - - Vertex definition as a string - - - - Describes deltas to apply to a vertex in order to morph a vertex - - - - - Provide a nice format for debugging - - MorphVertex definition as a string - - - - Describes a named mesh morph, essentially a named list of MorphVertices - - - - - Provide a nice format for debugging - - The name of the morph - - - - Don't really know what this does - - - - - Provide a nice format for debugging - - Human friendly format - - - - A reference mesh is one way to implement level of detail - - - Reference meshes are supplemental meshes to full meshes. For all practical - purposes almost all lod meshes are implemented as reference meshes, except for - 'avatar_eye_1.llm' which for some reason is implemented as a full mesh. - - - - - Load a mesh from a stream - - Filename and path of the file containing the reference mesh - - - - Level of Detail mesh - - - - - Construct a linden mesh with the given name - - the name of the mesh - - - - Construct a linden mesh with the given name - - the name of the mesh - The skeleton governing mesh deformation - - - - Load the mesh from a stream - - The filename and path of the file containing the mesh data - - - - Layout of one skinweight element - - - - List of skinweights, in the same order as the mesh vertices - - - - Decompress the skinweights - - the expanded joint list, used to index which bones should influece the vertex - - - - Load a reference mesh from a given stream - - The lod level of this reference mesh - the name and path of the file containing the mesh data - the loaded reference mesh - - - - Trim a string at the first occurence of NUL - - - The llm file uses null terminated strings (C/C++ style), this is where - the conversion is made. - - The string to trim - A standard .Net string - - - - load the 'avatar_skeleton.xml' - - - Partial class which extends the auto-generated 'LindenSkeleton.Xsd.cs'.eton.xsd - - - - - - Load a skeleton from a given file. - - - We use xml scema validation on top of the xml de-serializer, since the schema has - some stricter checks than the de-serializer provides. E.g. the vector attributes - are guaranteed to hold only 3 float values. This reduces the need for error checking - while working with the loaded skeleton. - - A valid recursive skeleton - - - - Load a skeleton from a given file. - - - We use xml scema validation on top of the xml de-serializer, since the schema has - some stricter checks than the de-serializer provides. E.g. the vector attributes - are guaranteed to hold only 3 float values. This reduces the need for error checking - while working with the loaded skeleton. - - The path to the skeleton definition file - A valid recursive skeleton - - - - Build and "expanded" list of joints - - - The algorithm is based on this description: - - >An "expanded" list of joints, not just a - >linear array of the joints as defined in the skeleton file. - >In particular, any joint that has more than one child will - >be repeated in the list for each of its children. - - The list should only take these joint names in consideration - An "expanded" joints list as a flat list of bone names - - - - Expand one joint - - The parent of the joint we are operating on - The joint we are supposed to expand - Joint list that we will extend upon - The expanded list should only contain these joints - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Contains all mesh faces that belong to a prim - - - - List of primitive faces - - - - Decodes mesh asset into FacetedMesh - - Mesh primitive - Asset retrieved from the asset server - Level of detail - Resulting decoded FacetedMesh - True if mesh asset decoding was successful - - - - Sent to the client to indicate a teleport request has completed - - - - The of the agent - - - - - - The simulators handle the agent teleported to - - - A Uri which contains a list of Capabilities the simulator supports - - - Indicates the level of access required - to access the simulator, or the content rating, or the simulators - map status - - - The IP Address of the simulator - - - The UDP Port the simulator will listen for UDP traffic on - - - Status flags indicating the state of the Agent upon arrival, Flying, etc. - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Sent to the viewer when a neighboring simulator is requesting the agent make a connection to it. - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent to the client which indicates a teleport request has failed - and contains some information on why it failed - - - - - - - A string key of the reason the teleport failed e.g. CouldntTPCloser - Which could be used to look up a value in a dictionary or enum - - - The of the Agent - - - A string human readable message containing the reason - An example: Could not teleport closer to destination - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Contains a list of prim owner information for a specific parcel in a simulator - - - A Simulator will always return at least 1 entry - If agent does not have proper permission the OwnerID will be UUID.Zero - If agent does not have proper permission OR there are no primitives on parcel - the DataBlocksExtended map will not be sent from the simulator - - - - - Prim ownership information for a specified owner on a single parcel - - - - The of the prim owner, - UUID.Zero if agent has no permission to view prim owner information - - - The total number of prims - - - True if the OwnerID is a - - - True if the owner is online - This is no longer used by the LL Simulators - - - The date the most recent prim was rezzed - - - An Array of objects - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - The details of a single parcel in a region, also contains some regionwide globals - - - - Simulator-local ID of this parcel - - - Maximum corner of the axis-aligned bounding box for this - parcel - - - Minimum corner of the axis-aligned bounding box for this - parcel - - - Total parcel land area - - - - - - Key of authorized buyer - - - Bitmap describing land layout in 4x4m squares across the - entire region - - - - - - Date land was claimed - - - Appears to always be zero - - - Parcel Description - - - - - - - - - Total number of primitives owned by the parcel group on - this parcel - - - Whether the land is deeded to a group or not - - - - - - Maximum number of primitives this parcel supports - - - The Asset UUID of the Texture which when applied to a - primitive will display the media - - - A URL which points to any Quicktime supported media type - - - A byte, if 0x1 viewer should auto scale media to fit object - - - URL For Music Stream - - - Parcel Name - - - Autoreturn value in minutes for others' objects - - - - - - Total number of other primitives on this parcel - - - UUID of the owner of this parcel - - - Total number of primitives owned by the parcel owner on - this parcel - - - - - - How long is pass valid for - - - Price for a temporary pass - - - - - - Disallows people outside the parcel from being able to see in - - - - - - - - - - - - True if the region denies access to age unverified users - - - - - - This field is no longer used - - - The result of a request for parcel properties - - - Sale price of the parcel, only useful if ForSale is set - The SalePrice will remain the same after an ownership - transfer (sale), so it can be used to see the purchase price after - a sale if the new owner has not changed it - - - - Number of primitives your avatar is currently - selecting and sitting on in this parcel - - - - - - - - A number which increments by 1, starting at 0 for each ParcelProperties request. - Can be overriden by specifying the sequenceID with the ParcelPropertiesRequest being sent. - a Negative number indicates the action in has occurred. - - - - Maximum primitives across the entire simulator - - - Total primitives across the entire simulator - - - - - - Key of parcel snapshot - - - Parcel ownership status - - - Total number of primitives on this parcel - - - - - - - - - A description of the media - - - An Integer which represents the height of the media - - - An integer which represents the width of the media - - - A boolean, if true the viewer should loop the media - - - A string which contains the mime type of the media - - - true to obscure (hide) media url - - - true to obscure (hide) music url - - - true if avatars in this parcel should be invisible to people outside - - - true if avatars outside can hear any sounds avatars inside play - - - true if group members outside can hear any sounds avatars inside play - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - A message sent from the viewer to the simulator to updated a specific parcels settings - - - The of the agent authorized to purchase this - parcel of land or a NULL if the sale is authorized to anyone - - - true to enable auto scaling of the parcel media - - - The category of this parcel used when search is enabled to restrict - search results - - - A string containing the description to set - - - The of the which allows for additional - powers and restrictions. - - - The which specifies how avatars which teleport - to this parcel are handled - - - The LocalID of the parcel to update settings on - - - A string containing the description of the media which can be played - to visitors - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - true if avatars in this parcel should be invisible to people outside - - - true if avatars outside can hear any sounds avatars inside play - - - true if group members outside can hear any sounds avatars inside play - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - Base class used for the RemoteParcelRequest message - - - - A message sent from the viewer to the simulator to request information - on a remote parcel - - - - Local sim position of the parcel we are looking up - - - Region handle of the parcel we are looking up - - - Region of the parcel we are looking up - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the simulator to the viewer in response to a - which will contain parcel information - - - - The grid-wide unique parcel ID - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message containing a request for a remote parcel from a viewer, or a response - from the simulator to that request - - - - The request or response details block - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the simulator to an agent which contains - the groups the agent is in - - - - The Agent receiving the message - - - Group Details specific to the agent - - - true of the agent accepts group notices - - - The agents tier contribution to the group - - - The Groups - - - The of the groups insignia - - - The name of the group - - - The aggregate permissions the agent has in the group for all roles the agent - is assigned - - - An optional block containing additional agent specific information - - - true of the agent allows this group to be - listed in their profile - - - An array containing information - for each the agent is a member of - - - An array containing information - for each the agent is a member of - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the viewer to the simulator which - specifies the language and permissions for others to detect - the language specified - - - - A string containng the default language - to use for the agent - - - true of others are allowed to - know the language setting - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - An EventQueue message sent from the simulator to an agent when the agent - leaves a group - - - - An object containing the Agents UUID, and the Groups UUID - - - The ID of the Agent leaving the group - - - The GroupID the Agent is leaving - - - - An Array containing the AgentID and GroupID - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - Base class for Asset uploads/results via Capabilities - - - - The request state - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the viewer to the simulator to request a temporary upload capability - which allows an asset to be uploaded - - - - The Capability URL sent by the simulator to upload the baked texture to - - - - A message sent from the simulator that will inform the agent the upload is complete, - and the UUID of the uploaded asset - - - - The uploaded texture asset ID - - - - A message sent from the viewer to the simulator to request a temporary - capability URI which is used to upload an agents baked appearance textures - - - - Object containing request or response - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the simulator which indicates the minimum version required for - using voice chat - - - - Major Version Required - - - Minor version required - - - The name of the region sending the version requrements - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the simulator to the viewer containing the - voice server URI - - - - The Parcel ID which the voice server URI applies - - - The name of the region - - - A uri containing the server/channel information - which the viewer can utilize to participate in voice conversations - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - - - - - - - - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent by the viewer to the simulator to request a temporary - capability for a script contained with in a Tasks inventory to be updated - - - - Object containing request or response - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the simulator to the viewer to indicate - a Tasks scripts status. - - - - The Asset ID of the script - - - True of the script is compiled/ran using the mono interpreter, false indicates it - uses the older less efficient lsl2 interprter - - - The Task containing the scripts - - - true of the script is in a running state - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message containing the request/response used for updating a gesture - contained with an agents inventory - - - - Object containing request or response - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message request/response which is used to update a notecard contained within - a tasks inventory - - - - The of the Task containing the notecard asset to update - - - The notecard assets contained in the tasks inventory - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A reusable class containing a message sent from the viewer to the simulator to request a temporary uploader capability - which is used to update an asset in an agents inventory - - - - - The Notecard AssetID to replace - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message containing the request/response used for updating a notecard - contained with an agents inventory - - - - Object containing request or response - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the simulator to the viewer which indicates - an error occurred while attempting to update a script in an agents or tasks - inventory - - - - true of the script was successfully compiled by the simulator - - - A string containing the error which occured while trying - to update the script - - - A new AssetID assigned to the script - - - - A message sent from the viewer to the simulator - requesting the update of an existing script contained - within a tasks inventory - - - - if true, set the script mode to running - - - The scripts InventoryItem ItemID to update - - - A lowercase string containing either "mono" or "lsl2" which - specifies the script is compiled and ran on the mono runtime, or the older - lsl runtime - - - The tasks which contains the script to update - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message containing either the request or response used in updating a script inside - a tasks inventory - - - - Object containing request or response - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Response from the simulator to notify the viewer the upload is completed, and - the UUID of the script asset and its compiled status - - - - The uploaded texture asset ID - - - true of the script was compiled successfully - - - - A message sent from a viewer to the simulator requesting a temporary uploader capability - used to update a script contained in an agents inventory - - - - The existing asset if of the script in the agents inventory to replace - - - The language of the script - Defaults to lsl version 2, "mono" might be another possible option - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message containing either the request or response used in updating a script inside - an agents inventory - - - - Object containing request or response - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - Base class for Map Layers via Capabilities - - - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Sent by an agent to the capabilities server to request map layers - - - - - A message sent from the simulator to the viewer which contains an array of map images and their grid coordinates - - - - - An object containing map location details - - - - The Asset ID of the regions tile overlay - - - The grid location of the southern border of the map tile - - - The grid location of the western border of the map tile - - - The grid location of the eastern border of the map tile - - - The grid location of the northern border of the map tile - - - An array containing LayerData items - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - Object containing request or response - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - New as of 1.23 RC1, no details yet. - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - A string containing the method used - - - - A request sent from an agent to the Simulator to begin a new conference. - Contains a list of Agents which will be included in the conference - - - - An array containing the of the agents invited to this conference - - - The conferences Session ID - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A moderation request sent from a conference moderator - Contains an agent and an optional action to take - - - - The Session ID - - - - - - A list containing Key/Value pairs, known valid values: - key: text value: true/false - allow/disallow specified agents ability to use text in session - key: voice value: true/false - allow/disallow specified agents ability to use voice in session - - "text" or "voice" - - - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - A message sent from the agent to the simulator which tells the - simulator we've accepted a conference invitation - - - - The conference SessionID - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - Key of sender - - - Name of sender - - - Key of destination avatar - - - ID of originating estate - - - Key of originating region - - - Coordinates in originating region - - - Instant message type - - - Group IM session toggle - - - Key of IM session, for Group Messages, the groups UUID - - - Timestamp of the instant message - - - Instant message text - - - Whether this message is held for offline avatars - - - Context specific packed data - - - Is this invitation for voice group/conference chat - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Sent from the simulator to the viewer. - - When an agent initially joins a session the AgentUpdatesBlock object will contain a list of session members including - a boolean indicating they can use voice chat in this session, a boolean indicating they are allowed to moderate - this session, and lastly a string which indicates another agent is entering the session with the Transition set to "ENTER" - - During the session lifetime updates on individuals are sent. During the update the booleans sent during the initial join are - excluded with the exception of the Transition field. This indicates a new user entering or exiting the session with - the string "ENTER" or "LEAVE" respectively. - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - An EventQueue message sent when the agent is forcibly removed from a chatterbox session - - - - - A string containing the reason the agent was removed - - - - - The ChatterBoxSession's SessionID - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - - Event Queue message describing physics engine attributes of a list of objects - Sim sends these when object is selected - - - - Array with the list of physics properties - - - - Serializes the message - - Serialized OSD - - - - Deserializes the message - - Incoming data to deserialize - - - - Deserializes the message - - Incoming data to deserialize - - - - Serializes the message - - Serialized OSD - - - - - Deserializes the message - - Incoming data to deserialize - - - - Serializes the message - - Serialized OSD - - - - Deserializes the message - - Incoming data to deserialize - - - - Serializes the message - - Serialized OSD - - - - Detects which class handles deserialization of this message - - An containing the data - Object capable of decoding this message - - - - A message sent from the viewer to the simulator which - specifies that the user has changed current URL - of the specific media on a prim face - - - - - New URL - - - - - Prim UUID where navigation occured - - - - - Face index - - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - Base class used for the ObjectMedia message - - - - Message used to retrive prim media data - - - - - Prim UUID - - - - - Requested operation, either GET or UPDATE - - - - - Serialize object - - Serialized object as OSDMap - - - - Deserialize the message - - An containing the data - - - - Message used to update prim media data - - - - - Prim UUID - - - - - Array of media entries indexed by face number - - - - - Media version string - - - - - Serialize object - - Serialized object as OSDMap - - - - Deserialize the message - - An containing the data - - - - Message used to update prim media data - - - - - Prim UUID - - - - - Array of media entries indexed by face number - - - - - Requested operation, either GET or UPDATE - - - - - Serialize object - - Serialized object as OSDMap - - - - Deserialize the message - - An containing the data - - - - Message for setting or getting per face MediaEntry - - - - The request or response details block - - - - Serialize the object - - An containing the objects data - - - - Deserialize the message - - An containing the data - - - Details about object resource usage - - - Object UUID - - - Object name - - - Indicates if object is group owned - - - Locatio of the object - - - Object owner - - - Resource usage, keys are resource names, values are resource usage for that specific resource - - - - Deserializes object from OSD - - An containing the data - - - - Makes an instance based on deserialized data - - serialized data - Instance containg deserialized data - - - Details about parcel resource usage - - - Parcel UUID - - - Parcel local ID - - - Parcel name - - - Indicates if parcel is group owned - - - Parcel owner - - - Array of containing per object resource usage - - - - Deserializes object from OSD - - An containing the data - - - - Makes an instance based on deserialized data - - serialized data - Instance containg deserialized data - - - Resource usage base class, both agent and parcel resource - usage contains summary information - - - Summary of available resources, keys are resource names, - values are resource usage for that specific resource - - - Summary resource usage, keys are resource names, - values are resource usage for that specific resource - - - - Serializes object - - serialized data - - - - Deserializes object from OSD - - An containing the data - - - Agent resource usage - - - Per attachment point object resource usage - - - - Deserializes object from OSD - - An containing the data - - - - Makes an instance based on deserialized data - - serialized data - Instance containg deserialized data - - - - Detects which class handles deserialization of this message - - An containing the data - Object capable of decoding this message - - - Request message for parcel resource usage - - - UUID of the parel to request resource usage info - - - - Serializes object - - serialized data - - - - Deserializes object from OSD - - An containing the data - - - Response message for parcel resource usage - - - URL where parcel resource usage details can be retrieved - - - URL where parcel resource usage summary can be retrieved - - - - Serializes object - - serialized data - - - - Deserializes object from OSD - - An containing the data - - - - Detects which class handles deserialization of this message - - An containing the data - Object capable of decoding this message - - - Parcel resource usage - - - Array of containing per percal resource usage - - - - Deserializes object from OSD - - An containing the data - - - - Reply to request for bunch if display names - - - - Current display name - - - Following UUIDs failed to return a valid display name - - - - Serializes the message - - OSD containting the messaage - - - - Message sent when requesting change of the display name - - - - Current display name - - - Desired new display name - - - - Serializes the message - - OSD containting the messaage - - - - Message recieved in response to request to change display name - - - - New display name - - - String message indicating the result of the operation - - - Numerical code of the result, 200 indicates success - - - - Serializes the message - - OSD containting the messaage - - - - Message recieved when someone nearby changes their display name - - - - Previous display name, empty string if default - - - New display name - - - - Serializes the message - - OSD containting the messaage - - - - Return a decoded capabilities message as a strongly typed object - - A string containing the name of the capabilities message key - An to decode - A strongly typed object containing the decoded information from the capabilities message, or null - if no existing Message object exists for the specified event - - - - Permissions for control of object media - - - - - Style of cotrols that shold be displayed to the user - - - - - Class representing media data for a single face - - - - Is display of the alternative image enabled - - - Should media auto loop - - - Shoule media be auto played - - - Auto scale media to prim face - - - Should viewer automatically zoom in on the face when clicked - - - Should viewer interpret first click as interaction with the media - or when false should the first click be treated as zoom in commadn - - - Style of controls viewer should display when - viewer media on this face - - - Starting URL for the media - - - Currently navigated URL - - - Media height in pixes - - - Media width in pixels - - - Who can controls the media - - - Who can interact with the media - - - Is URL whitelist enabled - - - Array of URLs that are whitelisted - - - - Serialize to OSD - - OSDMap with the serialized data - - - - Deserialize from OSD data - - Serialized OSD data - Deserialized object - - - - Particle system specific enumerators, flags and methods. - - - - - Current version of the media data for the prim - - - - - Array of media entries indexed by face number - - - - - Complete structure for the particle system - - - - - Particle source pattern - - - - None - - - Drop particles from source position with no force - - - "Explode" particles in all directions - - - Particles shoot across a 2D area - - - Particles shoot across a 3D Cone - - - Inverse of AngleCone (shoot particles everywhere except the 3D cone defined - - - - Particle Data Flags - - - - None - - - Interpolate color and alpha from start to end - - - Interpolate scale from start to end - - - Bounce particles off particle sources Z height - - - velocity of particles is dampened toward the simulators wind - - - Particles follow the source - - - Particles point towards the direction of source's velocity - - - Target of the particles - - - Particles are sent in a straight line - - - Particles emit a glow - - - used for point/grab/touch - - - continuous ribbon particle - - - particle data contains glow - - - particle data contains blend functions - - - - Particle Flags Enum - - - - None - - - Acceleration and velocity for particles are - relative to the object rotation - - - Particles use new 'correct' angle parameters - - - Particle Flags - There appears to be more data packed in to this area - for many particle systems. It doesn't appear to be flag values - and serialization breaks unless there is a flag for every - possible bit so it is left as an unsigned integer - - - pattern of particles - - - A representing the maximimum age (in seconds) particle will be displayed - Maximum value is 30 seconds - - - A representing the number of seconds, - from when the particle source comes into view, - or the particle system's creation, that the object will emits particles; - after this time period no more particles are emitted - - - A in radians that specifies where particles will not be created - - - A in radians that specifies where particles will be created - - - A representing the number of seconds between burts. - - - A representing the number of meters - around the center of the source where particles will be created. - - - A representing in seconds, the minimum speed between bursts of new particles - being emitted - - - A representing in seconds the maximum speed of new particles being emitted. - - - A representing the maximum number of particles emitted per burst - - - A which represents the velocity (speed) from the source which particles are emitted - - - A which represents the Acceleration from the source which particles are emitted - - - The Key of the texture displayed on the particle - - - The Key of the specified target object or avatar particles will follow - - - Flags of particle from - - - Max Age particle system will emit particles for - - - The the particle has at the beginning of its lifecycle - - - The the particle has at the ending of its lifecycle - - - A that represents the starting X size of the particle - Minimum value is 0, maximum value is 4 - - - A that represents the starting Y size of the particle - Minimum value is 0, maximum value is 4 - - - A that represents the ending X size of the particle - Minimum value is 0, maximum value is 4 - - - A that represents the ending Y size of the particle - Minimum value is 0, maximum value is 4 - - - A that represents the start glow value - Minimum value is 0, maximum value is 1 - - - A that represents the end glow value - Minimum value is 0, maximum value is 1 - - - OpenGL blend function to use at particle source - - - OpenGL blend function to use at particle destination - - - - Can this particle system be packed in a legacy compatible way - - True if the particle system doesn't use new particle system features - - - - Decodes a byte[] array into a ParticleSystem Object - - ParticleSystem object - Start position for BitPacker - - - - Generate byte[] array from particle data - - Byte array - - - - - - - Parameters used to construct a visual representation of a primitive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Attachment point to an avatar - - - - - - - - - - - - - - - - Calculdates hash code for prim construction data - - The has - - - - Information on the flexible properties of a primitive - - - - - - - - - - - - - - - - - - - - - - - Default constructor - - - - - - - - - - - - - - - - - - - - - - - - Information on the light properties of a primitive - - - - - - - - - - - - - - - - - - - - Default constructor - - - - - - - - - - - - - - - - - - - - - - - - Information on the light properties of a primitive as texture map - - - - - - - - - - - Default constructor - - - - - - - - - - - - - - - - - - - - - - - - Information on the sculpt properties of a sculpted primitive - - - - - Render inside out (inverts the normals). - - - - - Render an X axis mirror of the sculpty. - - - - - Default constructor - - - - - - - - - - - - Extended properties to describe an object - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Default constructor - - - - - Set the properties that are set in an ObjectPropertiesFamily packet - - that has - been partially filled by an ObjectPropertiesFamily packet - - - - Describes physics attributes of the prim - - - - Primitive's local ID - - - Density (1000 for normal density) - - - Friction - - - Gravity multiplier (1 for normal gravity) - - - Type of physics representation of this primitive in the simulator - - - Restitution - - - - Creates PhysicsProperties from OSD - - OSDMap with incoming data - Deserialized PhysicsProperties object - - - - Serializes PhysicsProperties to OSD - - OSDMap with serialized PhysicsProperties data - - - - - - - - - - - - - - - - - - - - - Foliage type for this primitive. Only applicable if this - primitive is foliage - - - Unknown - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Identifies the owner if audio or a particle system is - active - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Objects physics engine propertis - - - Extra data about primitive - - - Indicates if prim is attached to an avatar - - - Number of clients referencing this prim - - - Uses basic heuristics to estimate the primitive shape - - - - Default constructor - - - - - Packs PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters in to signed eight bit values - - Floating point parameter to pack - Signed eight bit value containing the packed parameter - - - - Unpacks PathTwist, PathTwistBegin, PathRadiusOffset, and PathSkew - parameters from signed eight bit integers to floating point values - - Signed eight bit value to unpack - Unpacked floating point value - - - - Texture animation mode - - - - Disable texture animation - - - Enable texture animation - - - Loop when animating textures - - - Animate in reverse direction - - - Animate forward then reverse - - - Slide texture smoothly instead of frame-stepping - - - Rotate texture instead of using frames - - - Scale texture instead of using frames - - - - A single textured face. Don't instantiate this class yourself, use the - methods in TextureEntry - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - In the future this will specify whether a webpage is - attached to this face - - - - - - - - - - Contains the definition for individual faces - - - - - - - - - - - - Represents all of the texturable faces for an object - - Grid objects have infinite faces, with each face - using the properties of the default face unless set otherwise. So if - you have a TextureEntry with a default texture uuid of X, and face 18 - has a texture UUID of Y, every face would be textured with X except for - face 18 that uses Y. In practice however, primitives utilize a maximum - of nine faces - - - - - - - - - - Constructor that takes a default texture UUID - - Texture UUID to use as the default texture - - - - Constructor that takes a TextureEntryFace for the - default face - - Face to use as the default face - - - - Constructor that creates the TextureEntry class from a byte array - - Byte array containing the TextureEntry field - Starting position of the TextureEntry field in - the byte array - Length of the TextureEntry field, in bytes - - - - This will either create a new face if a custom face for the given - index is not defined, or return the custom face for that index if - it already exists - - The index number of the face to create or - retrieve - A TextureEntryFace containing all the properties for that - face - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Controls the texture animation of a particular prim - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The type of bump-mapping applied to a face - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - The level of shininess applied to a face - - - - - - - - - - - - - - - - - The texture mapping style used for a face - - - - - - - - - - - - - - - - - Flags in the TextureEntry block that describe which properties are - set - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - This is used to login a specific user account(s). It may only be called after - Connector initialization has completed successfully - - Handle returned from successful Connector ‘create’ request - User's account name - User's account password - Values may be “AutoAnswer” or “VerifyAnswer” - "" - This is an integer that specifies how often - the daemon will send participant property events while in a channel. If this is not set - the default will be “on state change”, which means that the events will be sent when - the participant starts talking, stops talking, is muted, is unmuted. - The valid values are: - 0 – Never - 5 – 10 times per second - 10 – 5 times per second - 50 – 1 time per second - 100 – on participant state change (this is the default) - false - - - - - This is used to logout a user session. It should only be called with a valid AccountHandle. - - Handle returned from successful Connector ‘login’ request - - - - - This is used to get a list of audio devices that can be used for capture (input) of voice. - - - - - - This is used to get a list of audio devices that can be used for render (playback) of voice. - - - - - This command is used to select the render device. - - The name of the device as returned by the Aux.GetRenderDevices command. - - - - This command is used to select the capture device. - - The name of the device as returned by the Aux.GetCaptureDevices command. - - - - This command is used to start the audio capture process which will cause - AuxAudioProperty Events to be raised. These events can be used to display a - microphone VU meter for the currently selected capture device. This command - should not be issued if the user is on a call. - - (unused but required) - - - - - This command is used to stop the audio capture process. - - - - - - This command is used to set the mic volume while in the audio tuning process. - Once an acceptable mic level is attained, the application must issue a - connector set mic volume command to have that level be used while on voice - calls. - - the microphone volume (-100 to 100 inclusive) - - - - - This command is used to set the speaker volume while in the audio tuning - process. Once an acceptable speaker level is attained, the application must - issue a connector set speaker volume command to have that level be used while - on voice calls. - - the speaker volume (-100 to 100 inclusive) - - - - - This is used to initialize and stop the Connector as a whole. The Connector - Create call must be completed successfully before any other requests are made - (typically during application initialization). The shutdown should be called - when the application is shutting down to gracefully release resources - - A string value indicting the Application name - URL for the management server - LoggingSettings - - - - - - Shutdown Connector -- Should be called when the application is shutting down - to gracefully release resources - - Handle returned from successful Connector ‘create’ request - - - - Mute or unmute the microphone - - Handle returned from successful Connector ‘create’ request - true (mute) or false (unmute) - - - - Mute or unmute the speaker - - Handle returned from successful Connector ‘create’ request - true (mute) or false (unmute) - - - - Set microphone volume - - Handle returned from successful Connector ‘create’ request - The level of the audio, a number between -100 and 100 where - 0 represents ‘normal’ speaking volume - - - - Set local speaker volume - - Handle returned from successful Connector ‘create’ request - The level of the audio, a number between -100 and 100 where - 0 represents ‘normal’ speaking volume - - - - List of audio input devices - - - - - List of audio output devices - - - - - Start up the Voice service. - - - - - Handle miscellaneous request status - - - - ///If something goes wrong, we log it. - - - - Cleanup oject resources - - - - - Request voice cap when changing regions - - - - - Handle a change in session state - - - - - Close a voice session - - - - - - Locate a Session context from its handle - - Creates the session context if it does not exist. - - - - Handle completion of main voice cap request. - - - - - - - - Daemon has started so connect to it. - - - - - The daemon TCP connection is open. - - - - - Handle creation of the Connector. - - - - - Handle response to audio output device query - - - - - Handle response to audio input device query - - - - - Set audio test mode - - - - - Set voice channel for new parcel - - - - - - Request info from a parcel capability Uri. - - - - - - Receive parcel voice cap - - - - - - - - Tell Vivox where we are standing - - This has to be called when we move or turn. - - - - Start and stop updating out position. - - - - - Enable logging - - - The folder where any logs will be created - - - This will be prepended to beginning of each log file - - - The suffix or extension to be appended to each log file - - - - 0: NONE - No logging - 1: ERROR - Log errors only - 2: WARNING - Log errors and warnings - 3: INFO - Log errors, warnings and info - 4: DEBUG - Log errors, warnings, info and debug - - - - - Constructor for default logging settings - - - - Audio Properties Events are sent after audio capture is started. These events are used to display a microphone VU meter - - - - Event for most mundane request reposnses. - - - - Response to Connector.Create request - - - Response to Aux.GetCaptureDevices request - - - Response to Aux.GetRenderDevices request - - - Audio Properties Events are sent after audio capture is started. - These events are used to display a microphone VU meter - - - Response to Account.Login request - - - This event message is sent whenever the login state of the - particular Account has transitioned from one value to another - - - - Starts a thread that keeps the daemon running - - - - - - - Stops the daemon and the thread keeping it running - - - - - - - - - - - - - Create a Session - Sessions typically represent a connection to a media session with one or more - participants. This is used to generate an ‘outbound’ call to another user or - channel. The specifics depend on the media types involved. A session handle is - required to control the local user functions within the session (or remote - users if the current account has rights to do so). Currently creating a - session automatically connects to the audio media, there is no need to call - Session.Connect at this time, this is reserved for future use. - - Handle returned from successful Connector ‘create’ request - This is the URI of the terminating point of the session (ie who/what is being called) - This is the display name of the entity being called (user or channel) - Only needs to be supplied when the target URI is password protected - This indicates the format of the password as passed in. This can either be - “ClearText” or “SHA1UserName”. If this element does not exist, it is assumed to be “ClearText”. If it is - “SHA1UserName”, the password as passed in is the SHA1 hash of the password and username concatenated together, - then base64 encoded, with the final “=” character stripped off. - - - - - - - Used to accept a call - - SessionHandle such as received from SessionNewEvent - "default" - - - - - This command is used to start the audio render process, which will then play - the passed in file through the selected audio render device. This command - should not be issued if the user is on a call. - - The fully qualified path to the sound file. - True if the file is to be played continuously and false if it is should be played once. - - - - - This command is used to stop the audio render process. - - The fully qualified path to the sound file issued in the start render command. - - - - - This is used to ‘end’ an established session (i.e. hang-up or disconnect). - - Handle returned from successful Session ‘create’ request or a SessionNewEvent - - - - - Set the combined speaking and listening position in 3D space. - - Handle returned from successful Session ‘create’ request or a SessionNewEvent - Speaking position - Listening position - - - - - Set User Volume for a particular user. Does not affect how other users hear that user. - - Handle returned from successful Session ‘create’ request or a SessionNewEvent - - The level of the audio, a number between -100 and 100 where 0 represents ‘normal’ speaking volume - - - - Positional vector of the users position - - - Velocity vector of the position - - - At Orientation (X axis) of the position - - - Up Orientation (Y axis) of the position - - - Left Orientation (Z axis) of the position - - - - Extract the avatar UUID encoded in a SIP URI - - - - - - - Represents a single Voice Session to the Vivox service. - - - - - Close this session. - - - - - Look up an existing Participants in this session - - - - - - - - - - - - Delegate to wrap another delegate and its arguments - - - - - - - An instance of DelegateWrapper which calls InvokeWrappedDelegate, - which in turn calls the DynamicInvoke method of the wrapped - delegate - - - - - Callback used to call EndInvoke on the asynchronously - invoked DelegateWrapper - - - - - Executes the specified delegate with the specified arguments - asynchronously on a thread pool thread - - - - - - - Invokes the wrapped delegate synchronously - - - - - - - Calls EndInvoke on the wrapper and Close on the resulting WaitHandle - to prevent resource leaks - - - - - diff --git a/bin/OpenMetaverse.dll b/bin/OpenMetaverse.dll index 5c576a7a6f..83d3946d1e 100755 Binary files a/bin/OpenMetaverse.dll and b/bin/OpenMetaverse.dll differ diff --git a/bin/OpenMetaverseTypes.XML b/bin/OpenMetaverseTypes.XML deleted file mode 100644 index 3da5955b02..0000000000 --- a/bin/OpenMetaverseTypes.XML +++ /dev/null @@ -1,2667 +0,0 @@ - - - - OpenMetaverseTypes - - - - - Same as Queue except Dequeue function blocks until there is an object to return. - Note: This class does not need to be synchronized - - - - - Create new BlockingQueue. - - The System.Collections.ICollection to copy elements from - - - - Create new BlockingQueue. - - The initial number of elements that the queue can contain - - - - Create new BlockingQueue. - - - - - BlockingQueue Destructor (Close queue, resume any waiting thread). - - - - - Remove all objects from the Queue. - - - - - Remove all objects from the Queue, resume all dequeue threads. - - - - - Removes and returns the object at the beginning of the Queue. - - Object in queue. - - - - Removes and returns the object at the beginning of the Queue. - - time to wait before returning - Object in queue. - - - - Removes and returns the object at the beginning of the Queue. - - time to wait before returning (in milliseconds) - Object in queue. - - - - Adds an object to the end of the Queue - - Object to put in queue - - - - Open Queue. - - - - - Gets flag indicating if queue has been closed. - - - - - Copy constructor - - Circular queue to copy - - - - An 8-bit color structure including an alpha channel - - - - Red - - - Green - - - Blue - - - Alpha - - - - - - - - - - - - - Builds a color from a byte array - - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - - - - Returns the raw bytes for this vector - - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted - A 16 byte array containing R, G, B, and A - - - - Copy constructor - - Color to copy - - - - IComparable.CompareTo implementation - - Sorting ends up like this: |--Grayscale--||--Color--|. - Alpha is only used when the colors are otherwise equivalent - - - - Builds a color from a byte array - - Byte array containing a 16 byte color - Beginning position in the byte array - True if the byte array stores inverted values, - otherwise false. For example the color black (fully opaque) inverted - would be 0xFF 0xFF 0xFF 0x00 - True if the alpha value is inverted in - addition to whatever the inverted parameter is. Setting inverted true - and alphaInverted true will flip the alpha value back to non-inverted, - but keep the other color bytes inverted - - - - Writes the raw bytes for this color to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - - - - Serializes this color into four bytes in a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 4 bytes before the end of the array - True to invert the output (1.0 becomes 0 - instead of 255) - - - - Writes the raw bytes for this color to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - - - - Ensures that values are in range 0-1 - - - - - Create an RGB color from a hue, saturation, value combination - - Hue - Saturation - Value - An fully opaque RGB color (alpha is 1.0) - - - - Performs linear interpolation between two colors - - Color to start at - Color to end at - Amount to interpolate - The interpolated color - - - A Color4 with zero RGB values and fully opaque (alpha 1.0) - - - A Color4 with full RGB values (1.0) and fully opaque (alpha 1.0) - - - - Attribute class that allows extra attributes to be attached to ENUMs - - - - Text used when presenting ENUM to user - - - Default initializer - - - Text used when presenting ENUM to user - - - - The different types of grid assets - - - - Unknown asset type - - - Texture asset, stores in JPEG2000 J2C stream format - - - Sound asset - - - Calling card for another avatar - - - Link to a location in world - - - Collection of textures and parameters that can be worn by an avatar - - - Primitive that can contain textures, sounds, - scripts and more - - - Notecard asset - - - Holds a collection of inventory items. "Category" in the Linden viewer - - - Linden scripting language script - - - LSO bytecode for a script - - - Uncompressed TGA texture - - - Collection of textures and shape parameters that can be worn - - - Uncompressed sound - - - Uncompressed TGA non-square image, not to be used as a - texture - - - Compressed JPEG non-square image, not to be used as a - texture - - - Animation - - - Sequence of animations, sounds, chat, and pauses - - - Simstate file - - - Asset is a link to another inventory item - - - Asset is a link to another inventory folder - - - Marketplace Folder. Same as an Category but different display methods. - - - Linden mesh format - - - - The different types of folder. - - - - None folder type - - - Texture folder type - - - Sound folder type - - - Calling card folder type - - - Landmark folder type - - - Clothing folder type - - - Object folder type - - - Notecard folder type - - - The root folder type - - - LSLText folder - - - Bodyparts folder - - - Trash folder - - - Snapshot folder - - - Lost And Found folder - - - Animation folder - - - Gesture folder - - - Favorites folder - - - Ensemble beginning range - - - Ensemble ending range - - - Current outfit folder - - - Outfit folder - - - My outfits folder - - - Mesh folder - - - Marketplace direct delivery inbox ("Received Items") - - - Marketplace direct delivery outbox - - - Basic root folder - - - Marketplace listings folder - - - Marketplace stock folder - - - Hypergrid Suitcase folder - - - - Inventory Item Types, eg Script, Notecard, Folder, etc - - - - Unknown - - - Texture - - - Sound - - - Calling Card - - - Landmark - - - Notecard - - - - - - Folder - - - - - - an LSL Script - - - - - - - - - - - - - - - - - - - - - - Item Sale Status - - - - Not for sale - - - The original is for sale - - - Copies are for sale - - - The contents of the object are for sale - - - - Types of wearable assets - - - - Body shape - - - Skin textures and attributes - - - Hair - - - Eyes - - - Shirt - - - Pants - - - Shoes - - - Socks - - - Jacket - - - Gloves - - - Undershirt - - - Underpants - - - Skirt - - - Alpha mask to hide parts of the avatar - - - Tattoo - - - Physics - - - Invalid wearable asset - - - - Identifier code for primitive types - - - - None - - - A Primitive - - - A Avatar - - - Linden grass - - - Linden tree - - - A primitive that acts as the source for a particle stream - - - A Linden tree - - - - Primary parameters for primitives such as Physics Enabled or Phantom - - - - Deprecated - - - Whether physics are enabled for this object - - - - - - - - - - - - - - - - - - - - - Whether this object contains an active touch script - - - - - - Whether this object can receive payments - - - Whether this object is phantom (no collisions) - - - - - - - - - - - - - - - Deprecated - - - - - - - - - - - - Deprecated - - - - - - - - - - - - - - - Server flag, will not be sent to clients. Specifies that - the object is destroyed when it touches a simulator edge - - - Server flag, will not be sent to clients. Specifies that - the object will be returned to the owner's inventory when it - touches a simulator edge - - - Server flag, will not be sent to clients. - - - Server flag, will not be sent to client. Specifies that - the object is hovering/flying - - - - - - - - - - - - - - - - Sound flags for sounds attached to primitives - - - - - - - - - - - - - - - - - - - - - - - - - - Material type for a primitive - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Used in a helper function to roughly determine prim shape - - - - - Extra parameters for primitives, these flags are for features that have - been added after the original ObjectFlags that has all eight bits - reserved already - - - - Whether this object has flexible parameters - - - Whether this object has light parameters - - - Whether this object is a sculpted prim - - - Whether this object is a light image map - - - Whether this object is a mesh - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - Attachment points for objects on avatar bodies - - - Both InventoryObject and InventoryAttachment types can be attached - - - - Right hand if object was not previously attached - - - Chest - - - Skull - - - Left shoulder - - - Right shoulder - - - Left hand - - - Right hand - - - Left foot - - - Right foot - - - Spine - - - Pelvis - - - Mouth - - - Chin - - - Left ear - - - Right ear - - - Left eyeball - - - Right eyeball - - - Nose - - - Right upper arm - - - Right forearm - - - Left upper arm - - - Left forearm - - - Right hip - - - Right upper leg - - - Right lower leg - - - Left hip - - - Left upper leg - - - Left lower leg - - - Stomach - - - Left pectoral - - - Right pectoral - - - HUD Center position 2 - - - HUD Top-right - - - HUD Top - - - HUD Top-left - - - HUD Center - - - HUD Bottom-left - - - HUD Bottom - - - HUD Bottom-right - - - Neck - - - Avatar Center - - - - Tree foliage types - - - - Pine1 tree - - - Oak tree - - - Tropical Bush1 - - - Palm1 tree - - - Dogwood tree - - - Tropical Bush2 - - - Palm2 tree - - - Cypress1 tree - - - Cypress2 tree - - - Pine2 tree - - - Plumeria - - - Winter pinetree1 - - - Winter Aspen tree - - - Winter pinetree2 - - - Eucalyptus tree - - - Fern - - - Eelgrass - - - Sea Sword - - - Kelp1 plant - - - Beach grass - - - Kelp2 plant - - - - Grass foliage types - - - - - - - - - - - - - - - - - - - - - - - Action associated with clicking on an object - - - - Touch object - - - Sit on object - - - Purchase object or contents - - - Pay the object - - - Open task inventory - - - Play parcel media - - - Open parcel media - - - - Type of physics representation used for this prim in the simulator - - - - Use prim physics form this object - - - No physics, prim doesn't collide - - - Use convex hull represantion of this prim - - - For thread safety - - - For thread safety - - - - Purges expired objects from the cache. Called automatically by the purge timer. - - - - - A thread-safe lockless queue that supports multiple readers and - multiple writers - - - - - Provides a node container for data in a singly linked list - - - - Pointer to the next node in list - - - The data contained by the node - - - - Constructor - - - - - Constructor - - - - Queue head - - - Queue tail - - - Queue item count - - - Gets the current number of items in the queue. Since this - is a lockless collection this value should be treated as a close - estimate - - - - Constructor - - - - - Enqueue an item - - Item to enqeue - - - - Try to dequeue an item - - Dequeued item if the dequeue was successful - True if an item was successfully deqeued, otherwise false - - - - Convert this matrix to euler rotations - - X euler angle - Y euler angle - Z euler angle - - - - Convert this matrix to a quaternion rotation - - A quaternion representation of this rotation matrix - - - - Construct a matrix from euler rotation values in radians - - X euler angle in radians - Y euler angle in radians - Z euler angle in radians - - - - Get a formatted string representation of the vector - - A string representation of the vector - - - A 4x4 matrix containing all zeroes - - - A 4x4 identity matrix - - - X value - - - Y value - - - Z value - - - W value - - - - Build a quaternion from normalized float values - - X value from -1.0 to 1.0 - Y value from -1.0 to 1.0 - Z value from -1.0 to 1.0 - - - - Constructor, builds a quaternion object from a byte array - - Byte array containing four four-byte floats - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. - - - - Normalizes the quaternion - - - - - Builds a quaternion object from a byte array - - The source byte array - Offset in the byte array to start reading at - Whether the source data is normalized or - not. If this is true 12 bytes will be read, otherwise 16 bytes will - be read. - - - - Normalize this quaternion and serialize it to a byte array - - A 12 byte array containing normalized X, Y, and Z floating - point values in order using little endian byte ordering - - - - Writes the raw bytes for this quaternion to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 12 bytes before the end of the array - - - - Convert this quaternion to euler angles - - X euler angle - Y euler angle - Z euler angle - - - - Convert this quaternion to an angle around an axis - - Unit vector describing the axis - Angle around the axis, in radians - - - - Returns the conjugate (spatial inverse) of a quaternion - - - - - Build a quaternion from an axis and an angle of rotation around - that axis - - - - - Build a quaternion from an axis and an angle of rotation around - that axis - - Axis of rotation - Angle of rotation - - - - Creates a quaternion from a vector containing roll, pitch, and yaw - in radians - - Vector representation of the euler angles in - radians - Quaternion representation of the euler angles - - - - Creates a quaternion from roll, pitch, and yaw euler angles in - radians - - X angle in radians - Y angle in radians - Z angle in radians - Quaternion representation of the euler angles - - - - Conjugates and renormalizes a vector - - - - - Spherical linear interpolation between two quaternions - - - - - Get a string representation of the quaternion elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the quaternion - - - A quaternion with a value of 0,0,0,1 - - - - Determines the appropriate events to set, leaves the locks, and sets the events. - - - - - A routine for lazily creating a event outside the lock (so if errors - happen they are outside the lock and that we don't do much work - while holding a spin lock). If all goes well, reenter the lock and - set 'waitEvent' - - - - - Waits on 'waitEvent' with a timeout of 'millisceondsTimeout. - Before the wait 'numWaiters' is incremented and is restored before leaving this routine. - - - - - A hierarchical token bucket for bandwidth throttling. See - http://en.wikipedia.org/wiki/Token_bucket for more information - - - - Parent bucket to this bucket, or null if this is a root - bucket - - - Size of the bucket in bytes. If zero, the bucket has - infinite capacity - - - Rate that the bucket fills, in bytes per millisecond. If - zero, the bucket always remains full - - - Number of tokens currently in the bucket - - - Time of the last drip, in system ticks - - - - The parent bucket of this bucket, or null if this bucket has no - parent. The parent bucket will limit the aggregate bandwidth of all - of its children buckets - - - - - Maximum burst rate in bytes per second. This is the maximum number - of tokens that can accumulate in the bucket at any one time - - - - - The speed limit of this bucket in bytes per second. This is the - number of tokens that are added to the bucket per second - - Tokens are added to the bucket any time - is called, at the granularity of - the system tick interval (typically around 15-22ms) - - - - The number of bytes that can be sent at this moment. This is the - current number of tokens in the bucket - If this bucket has a parent bucket that does not have - enough tokens for a request, will - return false regardless of the content of this bucket - - - - - Default constructor - - Parent bucket if this is a child bucket, or - null if this is a root bucket - Maximum size of the bucket in bytes, or - zero if this bucket has no maximum capacity - Rate that the bucket fills, in bytes per - second. If zero, the bucket always remains full - - - - Remove a given number of tokens from the bucket - - Number of tokens to remove from the bucket - True if the requested number of tokens were removed from - the bucket, otherwise false - - - - Remove a given number of tokens from the bucket - - Number of tokens to remove from the bucket - True if tokens were added to the bucket - during this call, otherwise false - True if the requested number of tokens were removed from - the bucket, otherwise false - - - - Add tokens to the bucket over time. The number of tokens added each - call depends on the length of time that has passed since the last - call to Drip - - True if tokens were added to the bucket, otherwise false - - - - Operating system - - - - Unknown - - - Microsoft Windows - - - Microsoft Windows CE - - - Linux - - - Apple OSX - - - - Runtime platform - - - - .NET runtime - - - Mono runtime: http://www.mono-project.com/ - - - Used for converting degrees to radians - - - Used for converting radians to degrees - - - Provide a single instance of the CultureInfo class to - help parsing in situations where the grid assumes an en-us - culture - - - UNIX epoch in DateTime format - - - Provide a single instance of the MD5 class to avoid making - duplicate copies and handle thread safety - - - Provide a single instance of the SHA-1 class to avoid - making duplicate copies and handle thread safety - - - Provide a single instance of a random number generator - to avoid making duplicate copies and handle thread safety - - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper - - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper - - - - Clamp a given value between a range - - Value to clamp - Minimum allowable value - Maximum allowable value - A value inclusively between lower and upper - - - - Round a floating-point value to the nearest integer - - Floating point number to round - Integer - - - - Test if a single precision float is a finite number - - - - - Test if a double precision float is a finite number - - - - - Get the distance between two floating-point values - - First value - Second value - The distance between the two values - - - - Compute the MD5 hash for a byte array - - Byte array to compute the hash for - MD5 hash of the input data - - - - Compute the SHA1 hash for a byte array - - Byte array to compute the hash for - SHA1 hash of the input data - - - - Calculate the SHA1 hash of a given string - - The string to hash - The SHA1 hash as a string - - - - Compute the SHA256 hash for a byte array - - Byte array to compute the hash for - SHA256 hash of the input data - - - - Calculate the SHA256 hash of a given string - - The string to hash - The SHA256 hash as a string - - - - Calculate the MD5 hash of a given string - - The password to hash - An MD5 hash in string format, with $1$ prepended - - - - Calculate the MD5 hash of a given string - - The string to hash - The MD5 hash as a string - - - - Generate a random double precision floating point value - - Random value of type double - - - - Get the current running platform - - Enumeration of the current platform we are running on - - - - Get the current running runtime - - Enumeration of the current runtime we are running on - - - - Convert the first two bytes starting in the byte array in - little endian ordering to a signed short integer - - An array two bytes or longer - A signed short integer, will be zero if a short can't be - read at the given position - - - - Convert the first two bytes starting at the given position in - little endian ordering to a signed short integer - - An array two bytes or longer - Position in the array to start reading - A signed short integer, will be zero if a short can't be - read at the given position - - - - Convert the first four bytes starting at the given position in - little endian ordering to a signed integer - - An array four bytes or longer - Position to start reading the int from - A signed integer, will be zero if an int can't be read - at the given position - - - - Convert the first four bytes of the given array in little endian - ordering to a signed integer - - An array four bytes or longer - A signed integer, will be zero if the array contains - less than four bytes - - - - Convert the first eight bytes of the given array in little endian - ordering to a signed long integer - - An array eight bytes or longer - A signed long integer, will be zero if the array contains - less than eight bytes - - - - Convert the first eight bytes starting at the given position in - little endian ordering to a signed long integer - - An array eight bytes or longer - Position to start reading the long from - A signed long integer, will be zero if a long can't be read - at the given position - - - - Convert the first two bytes starting at the given position in - little endian ordering to an unsigned short - - Byte array containing the ushort - Position to start reading the ushort from - An unsigned short, will be zero if a ushort can't be read - at the given position - - - - Convert two bytes in little endian ordering to an unsigned short - - Byte array containing the ushort - An unsigned short, will be zero if a ushort can't be - read - - - - Convert the first four bytes starting at the given position in - little endian ordering to an unsigned integer - - Byte array containing the uint - Position to start reading the uint from - An unsigned integer, will be zero if a uint can't be read - at the given position - - - - Convert the first four bytes of the given array in little endian - ordering to an unsigned integer - - An array four bytes or longer - An unsigned integer, will be zero if the array contains - less than four bytes - - - - Convert the first eight bytes of the given array in little endian - ordering to an unsigned 64-bit integer - - An array eight bytes or longer - An unsigned 64-bit integer, will be zero if the array - contains less than eight bytes - - - - Convert four bytes in little endian ordering to a floating point - value - - Byte array containing a little ending floating - point value - Starting position of the floating point value in - the byte array - Single precision value - - - - Convert an integer to a byte array in little endian format - - The integer to convert - A four byte little endian array - - - - Convert an integer to a byte array in big endian format - - The integer to convert - A four byte big endian array - - - - Convert a 64-bit integer to a byte array in little endian format - - The value to convert - An 8 byte little endian array - - - - Convert a 64-bit unsigned integer to a byte array in little endian - format - - The value to convert - An 8 byte little endian array - - - - Convert a floating point value to four bytes in little endian - ordering - - A floating point value - A four byte array containing the value in little endian - ordering - - - - Converts an unsigned integer to a hexadecimal string - - An unsigned integer to convert to a string - A hexadecimal string 10 characters long - 0x7fffffff - - - - Convert a variable length UTF8 byte array to a string - - The UTF8 encoded byte array to convert - The decoded string - - - - Converts a byte array to a string containing hexadecimal characters - - The byte array to convert to a string - The name of the field to prepend to each - line of the string - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name - - - - Converts a byte array to a string containing hexadecimal characters - - The byte array to convert to a string - Number of bytes in the array to parse - A string to prepend to each line of the hex - dump - A string containing hexadecimal characters on multiple - lines. Each line is prepended with the field name - - - - Convert a string to a UTF8 encoded byte array - - The string to convert - A null-terminated UTF8 byte array - - - - Converts a string containing hexadecimal characters to a byte array - - String containing hexadecimal characters - If true, gracefully handles null, empty and - uneven strings as well as stripping unconvertable characters - The converted byte array - - - - Returns true is c is a hexadecimal digit (A-F, a-f, 0-9) - - Character to test - true if hex digit, false if not - - - - Converts 1 or 2 character string into equivalant byte value - - 1 or 2 character string - byte - - - - Convert a float value to a byte given a minimum and maximum range - - Value to convert to a byte - Minimum value range - Maximum value range - A single byte representing the original float value - - - - Convert a byte to a float value given a minimum and maximum range - - Byte array to get the byte from - Position in the byte array the desired byte is at - Minimum value range - Maximum value range - A float value inclusively between lower and upper - - - - Convert a byte to a float value given a minimum and maximum range - - Byte to convert to a float value - Minimum value range - Maximum value range - A float value inclusively between lower and upper - - - - Attempts to parse a floating point value from a string, using an - EN-US number format - - String to parse - Resulting floating point number - True if the parse was successful, otherwise false - - - - Attempts to parse a floating point value from a string, using an - EN-US number format - - String to parse - Resulting floating point number - True if the parse was successful, otherwise false - - - - Tries to parse an unsigned 32-bit integer from a hexadecimal string - - String to parse - Resulting integer - True if the parse was successful, otherwise false - - - - Returns text specified in EnumInfo attribute of the enumerator - To add the text use [EnumInfo(Text = "Some nice text here")] before declaration - of enum values - - Enum value - Text representation of the enum - - - - Takes an AssetType and returns the string representation - - The source - The string version of the AssetType - - - - Translate a string name of an AssetType into the proper Type - - A string containing the AssetType name - The AssetType which matches the string name, or AssetType.Unknown if no match was found - - - - Takes a FolderType and returns the string representation - - The source - The string version of the FolderType - - - - Translate a string name of an FolderType into the proper Type - - A string containing the FolderType name - The FolderType which matches the string name, or FolderType. None if no match was found - - - - Convert an InventoryType to a string - - The to convert - A string representation of the source - - - - Convert a string into a valid InventoryType - - A string representation of the InventoryType to convert - A InventoryType object which matched the type - - - - Convert a SaleType to a string - - The to convert - A string representation of the source - - - - Convert a string into a valid SaleType - - A string representation of the SaleType to convert - A SaleType object which matched the type - - - - Converts a string used in LLSD to AttachmentPoint type - - String representation of AttachmentPoint to convert - AttachmentPoint enum - - - - Copy a byte array - - Byte array to copy - A copy of the given byte array - - - - Packs to 32-bit unsigned integers in to a 64-bit unsigned integer - - The left-hand (or X) value - The right-hand (or Y) value - A 64-bit integer containing the two 32-bit input values - - - - Unpacks two 32-bit unsigned integers from a 64-bit unsigned integer - - The 64-bit input integer - The left-hand (or X) output value - The right-hand (or Y) output value - - - - Convert an IP address object to an unsigned 32-bit integer - - IP address to convert - 32-bit unsigned integer holding the IP address bits - - - - Gets a unix timestamp for the current time - - An unsigned integer representing a unix timestamp for now - - - - Convert a UNIX timestamp to a native DateTime object - - An unsigned integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp - - - - Convert a UNIX timestamp to a native DateTime object - - A signed integer representing a UNIX - timestamp - A DateTime object containing the same time specified in - the given timestamp - - - - Convert a native DateTime object to a UNIX timestamp - - A DateTime object you want to convert to a - timestamp - An unsigned integer representing a UNIX timestamp - - - - Swap two values - - Type of the values to swap - First value - Second value - - - - Try to parse an enumeration value from a string - - Enumeration type - String value to parse - Enumeration value on success - True if the parsing succeeded, otherwise false - - - - Swaps the high and low words in a byte. Converts aaaabbbb to bbbbaaaa - - Byte to swap the words in - Byte value with the words swapped - - - - Attempts to convert a string representation of a hostname or IP - address to a - - Hostname to convert to an IPAddress - Converted IP address object, or null if the conversion - failed - - - - A 128-bit Universally Unique Identifier, used throughout the Second - Life networking protocol - - - - The System.Guid object this struct wraps around - - - - Constructor that takes a string UUID representation - - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - UUID("11f8aa9c-b071-4242-836b-13b7abe0d489") - - - - Constructor that takes a System.Guid object - - A Guid object that contains the unique identifier - to be represented by this UUID - - - - Constructor that takes a byte array containing a UUID - - Byte array containing a 16 byte UUID - Beginning offset in the array - - - - Constructor that takes an unsigned 64-bit unsigned integer to - convert to a UUID - - 64-bit unsigned integer to convert to a UUID - - - - Copy constructor - - UUID to copy - - - - IComparable.CompareTo implementation - - - - - Assigns this UUID from 16 bytes out of a byte array - - Byte array containing the UUID to assign this UUID to - Starting position of the UUID in the byte array - - - - Returns a copy of the raw bytes for this UUID - - A 16 byte array containing this UUID - - - - Writes the raw bytes for this UUID to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - - - - Calculate an LLCRC (cyclic redundancy check) for this UUID - - The CRC checksum for this UUID - - - - Create a 64-bit integer representation from the second half of this UUID - - An integer created from the last eight bytes of this UUID - - - - Generate a UUID from a string - - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - UUID.Parse("11f8aa9c-b071-4242-836b-13b7abe0d489") - - - - Generate a UUID from a string - - A string representation of a UUID, case - insensitive and can either be hyphenated or non-hyphenated - Will contain the parsed UUID if successful, - otherwise null - True if the string was successfully parse, otherwise false - UUID.TryParse("11f8aa9c-b071-4242-836b-13b7abe0d489", result) - - - - Combine two UUIDs together by taking the MD5 hash of a byte array - containing both UUIDs - - First UUID to combine - Second UUID to combine - The UUID product of the combination - - - - - - - - - - Return a hash code for this UUID, used by .NET for hash tables - - An integer composed of all the UUID bytes XORed together - - - - Comparison function - - An object to compare to this UUID - True if the object is a UUID and both UUIDs are equal - - - - Comparison function - - UUID to compare to - True if the UUIDs are equal, otherwise false - - - - Get a hyphenated string representation of this UUID - - A string representation of this UUID, lowercase and - with hyphens - 11f8aa9c-b071-4242-836b-13b7abe0d489 - - - - Equals operator - - First UUID for comparison - Second UUID for comparison - True if the UUIDs are byte for byte equal, otherwise false - - - - Not equals operator - - First UUID for comparison - Second UUID for comparison - True if the UUIDs are not equal, otherwise true - - - - XOR operator - - First UUID - Second UUID - A UUID that is a XOR combination of the two input UUIDs - - - - String typecasting operator - - A UUID in string form. Case insensitive, - hyphenated or non-hyphenated - A UUID built from the string representation - - - An UUID with a value of all zeroes - - - A cache of UUID.Zero as a string to optimize a common path - - - - A two-dimensional vector with floating-point values - - - - X value - - - Y value - - - - Test if this vector is equal to another vector, within a given - tolerance range - - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false - - - - Test if this vector is composed of all finite numbers - - - - - IComparable.CompareTo implementation - - - - - Builds a vector from a byte array - - Byte array containing two four-byte floats - Beginning position in the byte array - - - - Returns the raw bytes for this vector - - An eight-byte array containing X and Y - - - - Writes the raw bytes for this vector to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 8 bytes before the end of the array - - - - Parse a vector from a string - - A string representation of a 2D vector, enclosed - in arrow brackets and separated by commas - - - - Interpolates between two vectors using a cubic equation - - - - - Get a formatted string representation of the vector - - A string representation of the vector - - - - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the vector - - - A vector with a value of 0,0 - - - A vector with a value of 1,1 - - - A vector with a value of 1,0 - - - A vector with a value of 0,1 - - - - A three-dimensional vector with floating-point values - - - - X value - - - Y value - - - Z value - - - - Constructor, builds a vector from a byte array - - Byte array containing three four-byte floats - Beginning position in the byte array - - - - Test if this vector is equal to another vector, within a given - tolerance range - - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false - - - - IComparable.CompareTo implementation - - - - - Test if this vector is composed of all finite numbers - - - - - Builds a vector from a byte array - - Byte array containing a 12 byte vector - Beginning position in the byte array - - - - Returns the raw bytes for this vector - - A 12 byte array containing X, Y, and Z - - - - Writes the raw bytes for this vector to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 12 bytes before the end of the array - - - - Parse a vector from a string - - A string representation of a 3D vector, enclosed - in arrow brackets and separated by commas - - - - Calculate the rotation between two vectors - - Normalized directional vector (such as 1,0,0 for forward facing) - Normalized target vector - - - - Interpolates between two vectors using a cubic equation - - - - - Get a formatted string representation of the vector - - A string representation of the vector - - - - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the vector - - - - Cross product between two vectors - - - - - Explicit casting for Vector3d > Vector3 - - - - - - A vector with a value of 0,0,0 - - - A vector with a value of 1,1,1 - - - A unit vector facing forward (X axis), value 1,0,0 - - - A unit vector facing left (Y axis), value 0,1,0 - - - A unit vector facing up (Z axis), value 0,0,1 - - - - A three-dimensional vector with doubleing-point values - - - - X value - - - Y value - - - Z value - - - - Constructor, builds a vector from a byte array - - Byte array containing three eight-byte doubles - Beginning position in the byte array - - - - Test if this vector is equal to another vector, within a given - tolerance range - - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false - - - - IComparable.CompareTo implementation - - - - - Test if this vector is composed of all finite numbers - - - - - Builds a vector from a byte array - - Byte array containing a 24 byte vector - Beginning position in the byte array - - - - Returns the raw bytes for this vector - - A 24 byte array containing X, Y, and Z - - - - Writes the raw bytes for this vector to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 24 bytes before the end of the array - - - - Parse a vector from a string - - A string representation of a 3D vector, enclosed - in arrow brackets and separated by commas - - - - Interpolates between two vectors using a cubic equation - - - - - Get a formatted string representation of the vector - - A string representation of the vector - - - - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the vector - - - - Cross product between two vectors - - - - - Implicit casting for Vector3 > Vector3d - - - - - - A vector with a value of 0,0,0 - - - A vector with a value of 1,1,1 - - - A unit vector facing forward (X axis), value of 1,0,0 - - - A unit vector facing left (Y axis), value of 0,1,0 - - - A unit vector facing up (Z axis), value of 0,0,1 - - - X value - - - Y value - - - Z value - - - W value - - - - Constructor, builds a vector from a byte array - - Byte array containing four four-byte floats - Beginning position in the byte array - - - - Test if this vector is equal to another vector, within a given - tolerance range - - Vector to test against - The acceptable magnitude of difference - between the two vectors - True if the magnitude of difference between the two vectors - is less than the given tolerance, otherwise false - - - - IComparable.CompareTo implementation - - - - - Test if this vector is composed of all finite numbers - - - - - Builds a vector from a byte array - - Byte array containing a 16 byte vector - Beginning position in the byte array - - - - Returns the raw bytes for this vector - - A 16 byte array containing X, Y, Z, and W - - - - Writes the raw bytes for this vector to a byte array - - Destination byte array - Position in the destination array to start - writing. Must be at least 16 bytes before the end of the array - - - - Get a string representation of the vector elements with up to three - decimal digits and separated by spaces only - - Raw string representation of the vector - - - A vector with a value of 0,0,0,0 - - - A vector with a value of 1,1,1,1 - - - A vector with a value of 1,0,0,0 - - - A vector with a value of 0,1,0,0 - - - A vector with a value of 0,0,1,0 - - - A vector with a value of 0,0,0,1 - - - diff --git a/bin/OpenMetaverseTypes.dll b/bin/OpenMetaverseTypes.dll index a07cc1daa0..3bb48cf984 100755 Binary files a/bin/OpenMetaverseTypes.dll and b/bin/OpenMetaverseTypes.dll differ diff --git a/bin/OpenSim.exe.config b/bin/OpenSim.exe.config index b01191e140..5be6989918 100755 --- a/bin/OpenSim.exe.config +++ b/bin/OpenSim.exe.config @@ -5,11 +5,10 @@ - - + @@ -39,7 +38,8 @@ - + + diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 5f1e779337..05a43f4b90 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -52,13 +52,19 @@ ; name and use default public port 9000. The private port is not used ; in the configuration for a standalone. - ;# {BaseURL} {} {BaseURL} {"http://example.com" "http://127.0.0.1"} "http://127.0.0.1" - BaseURL = http://127.0.0.1 + ;# {BaseHostname} {} {BaseHostname} {"example.com" "127.0.0.1"} "127.0.0.1" + BaseHostname = "127.0.0.1" + + ;# {BaseURL} {} {BaseURL} {"http://${Const|BaseHostname}} "http://${Const|BaseHostname}" + BaseURL = http://${Const|BaseHostname} ;# {PublicPort} {} {PublicPort} {8002 9000} "8002" PublicPort = "8002" ;# {PrivatePort} {} {PrivatePort} {8003} "8003" + ; port to access private grid services. + ; grids that run all their regions should deny access to this port + ; from outside their networks, using firewalls PrivatePort = "8003" @@ -135,7 +141,7 @@ ;; The XML here has the same format as it does on the filesystem ;; (including the tag), except that everything is also enclosed ;; in a tag. - ; regionload_webserver_url = "http://example.com/regions.xml"; + ; regionload_webserver_url = "http://example.com/regions.xml" ;# {allow_regionless} {} {Allow simulator to start up with no regions configured.} {true false} false ;; Allow the simulator to start up if there are no region configuration available @@ -253,6 +259,10 @@ ;; alternative OpenDynamicsEngine engine. ubODEMeshmerizer meshing above MUST be selected also ; physics = ubODE + ; ubODE and OpenDynamicsEngine does allocate a lot of memory on stack. On linux you may need to increase its limit + ; script opensim-ode-sh starts opensim setting that limit. You may need to increase it even more on large regions + ; edit the line ulimit -s 262144, and change this last value + ;# {DefaultScriptEngine} {} {Default script engine} {XEngine} XEngine ;; Default script engine to use. Currently, we only have XEngine ; DefaultScriptEngine = "XEngine" @@ -279,8 +289,8 @@ ;; SpawnPointRouting adjusts the landing for incoming avatars. ;; "closest" will place the avatar at the SpawnPoint located in the closest ;; available spot to the destination (typically map click/landmark). - ;; "random" will place the avatar on a randomly selected spawnpoint; - ;; "sequence" will place the avatar on the next sequential SpawnPoint + ;; "random" will place the avatar on a randomly selected spawnpoint. + ;; "sequence" will place the avatar on the next sequential SpawnPoint. ; SpawnPointRouting = closest ;# {TelehubAllowLandmark} {} {Allow users with landmarks to override telehub routing} {true false} false @@ -357,8 +367,8 @@ ; TexturePrimSize = 48 ;# {RenderMeshes} {} {Render meshes and sculpties on map tiles?} {true false} false - ;; Attempt to render meshes and sculpties on the map - ; RenderMeshes = false; + ;; Attempt to render meshes and sculpties on the map. + ; RenderMeshes = false [Permissions] @@ -522,10 +532,9 @@ ;# {ExternalHostNameForLSL} {} {Hostname to use for HTTP-IN URLs. This should be reachable from the internet.} {} ;; Hostname to use in llRequestURL/llRequestSecureURL - ;; if not defined - default machine name is being used - ;; (on Windows this mean NETBIOS name - useably only inside local network) - ; ExternalHostNameForLSL = "127.0.0.1" - + ;; if not defined - llRequestURL/llRequestSecureURL are disabled + ExternalHostNameForLSL = ${Const|BaseHostname} + ;# {shard} {} {Name to use for X-Secondlife-Shard header? (press enter if unsure)} {} OpenSim ;; What is reported as the "X-Secondlife-Shard" ;; Defaults to the user server url if not set @@ -541,7 +550,7 @@ ;; web server ; user_agent = "OpenSim LSL (Mozilla Compatible)" - ;; The follow 3 variables are for HTTP Basic Authentication for the Robust services. + ;; The following 3 variables are for HTTP Basic Authentication for the Robust services. ;; Use this if your central services in port 8003 need to be accessible on the Internet ;; but you want to protect them from unauthorized access. The username and password ;; here need to match the ones in the Robust service configuration. @@ -606,7 +615,6 @@ [SimulatorFeatures] - ;# {SearchServerURI} {} {URL of the search server} {} ;; Optional. If given this serves the same purpose as the grid wide ;; [LoginServices] SearchURL setting and will override that where @@ -663,7 +671,7 @@ ;; For standalones, this is the storage dll. ; StorageProvider = OpenSim.Data.MySQL.dll - ;# {MuteListModule} {OfflineMessageModule:OfflineMessageModule} {} {} MuteListModule + ;# {MuteListModule} {OfflineMessageModule:OfflineMessageModule} {} {} None ;; Mute list handler (not yet implemented). MUST BE SET to allow offline ;; messages to work ; MuteListModule = MuteListModule @@ -922,17 +930,6 @@ ;; it is more usefull if there are no previously compiled scripts DLLs (as with DeleteScriptsOnStartup = true) ;CompactMemOnLoad = false - ;# {DefaultCompileLanguage} {Enabled:true} {Default script language?} {lsl vb cs} lsl - ;; Default language for scripts - ; DefaultCompileLanguage = "lsl" - - ;# {AllowedCompilers} {Enabled:true} {Languages to allow (comma separated)?} {} lsl - ;; List of allowed languages (lsl,vb,cs) - ;; AllowedCompilers=lsl,cs,vb - ;; *warning*, non lsl languages have access to static methods such as - ;; System.IO.File. Enable at your own risk. - ; AllowedCompilers = "lsl" - ;; Compile debug info (line numbers) into the script assemblies ; CompileWithDebugInformation = true @@ -1119,7 +1116,7 @@ [MediaOnAPrim] ;# {Enabled} {} {Enable Media-on-a-Prim (MOAP)} {true false} true ;; Enable media on a prim facilities - ; Enabled = true; + ; Enabled = true [NPC] diff --git a/bin/OpenSim32.exe b/bin/OpenSim32.exe new file mode 100644 index 0000000000..74477c0b68 Binary files /dev/null and b/bin/OpenSim32.exe differ diff --git a/bin/OpenSim32.exe.config b/bin/OpenSim32.exe.config new file mode 100644 index 0000000000..92242406f1 --- /dev/null +++ b/bin/OpenSim32.exe.config @@ -0,0 +1,75 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/OpenSim.32BitLaunch.pdb b/bin/OpenSim32.pdb similarity index 71% rename from bin/OpenSim.32BitLaunch.pdb rename to bin/OpenSim32.pdb index 5083dd5df5..86d3058531 100644 Binary files a/bin/OpenSim.32BitLaunch.pdb and b/bin/OpenSim32.pdb differ diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index f70f7dbe57..3747fcf6af 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -600,8 +600,7 @@ ; HttpBodyMaxLenMAX=16384 ; Hostname to use in llRequestURL/llRequestSecureURL - ; if not defined - default machine name is being used - ; (on Windows this mean NETBIOS name - useably only inside local network) + ; if not defined - llRequestURL/llRequestSecureURL are disabled ; ExternalHostNameForLSL=127.0.0.1 ; Disallow the following address ranges for user scripting calls (e.g. llHttpRequest()) @@ -650,14 +649,6 @@ [ClientStack.LindenUDP] - ; Set this to true to process incoming packets asynchronously. Networking is - ; already separated from packet handling with a queue, so this will only - ; affect whether networking internals such as packet decoding and - ; acknowledgement accounting are done synchronously or asynchronously - ; Default is true. - ; - ;async_packet_handling = true - ; The client socket receive buffer size determines how many ; incoming requests we can process; the default on .NET is 8192 ; which is about 2 4k-sized UDP datagrams. On mono this is @@ -944,18 +935,35 @@ [Mesh] - ; enable / disable Collada mesh support + ; enable / disable mesh asset uploads + ; mesh asset must conform to standard mesh format, with OpenSim extensions ; default is true AllowMeshUpload = true - ; if you use Meshmerizer and want collisions for meshies, setting this to true - ; will cause OpenSim to attempt to decode meshies assets, extract the physics - ; mesh, and use it for collisions. - UseMeshiesPhysicsMesh = true - ; Minimum user level required to upload meshes ;LevelUpload = 0 + ; support meshes on physics + ;UseMeshiesPhysicsMesh = true + + ;support convex shape type on normal prims + ; (ubOde only) + ;ConvexPrims = true + + ;support convex shape type on sculpts + ; (ubOde only) + ;ConvexSculpts = true + + ; mesh cache settings: + ; (ubOde only) + ; do cache (keep true) + ;MeshFileCache = true + ; cache folder name relative to bin/ or absolute path + ;MeshFileCachePath = MeshCache + ;MeshFileCacheDoExpire = true; + ;MeshFileCacheExpireHours = 48 + + [Textures] ; If true, textures generated dynamically (i.e. through osSetDynamicTextureData() and similar OSSL functions) are reused where possible @@ -977,7 +985,7 @@ [ODEPhysicsSettings] ; ## - ; ## Physics stats settings + ; ## Physics stats settings ( most ignored by ubOde ) ; ; If collect_stats is enabled, then extra stat information is collected which is accessible via the MonitorModule @@ -1150,12 +1158,14 @@ ; ## additional meshing options ; ## - ; Physical collision mesh proxies are normally created for complex prim shapes, - ; and collisions for simple boxes and spheres are computed algorithmically. - ; If you would rather have mesh proxies for simple prims, you can set this to - ; true. Note that this will increase memory usage and region startup time. - ; Default is false. - ;force_simple_prim_meshing = false + ; Physics needs to create internal meshs (or convert the object meshs or scultps) + ; for all prims except simple boxes and spheres. + + ; collisions of small objects againts larger ones can have a increased CPU load cost + ; so this are represented by a simple BOX + ; if all their scale dimensions are lower or equal to this option. Default is 0.1m + ; (ubOde only) + ; MinSizeToMeshmerize = 0.1 [BulletSim] @@ -1459,13 +1469,21 @@ [Trees] - ; Enable this to allow the tree module to manage your sim trees, including growing, reproducing and dying - ; default is false + ; enable the trees module. default true + enabled = true + + ; active_trees allows module to change its trees in time. + ; some will be deleted, others created and rest may grow + ; default is false. You can change it with console command tree active true | false later active_trees = false + ; the trees change execution time rate (in ms) + update_rate = 1000 - ; Density of tree population - tree_density = 1000.0 - + ; allow the trees to grow. + ; DANGER + ; this option causes high network use on the order of + ; NumberOfTrees * NumberAvatars * 1000 / update_rate udp packets per second + allowGrow = false [VectorRender] ; the font to use for rendering text (default: Arial) @@ -1787,14 +1805,6 @@ ; Save the source of all compiled scripts WriteScriptSourceToDebugFile = false - ; Default language for scripts - DefaultCompileLanguage = lsl - - ; List of allowed languages (lsl,vb,cs) - ; AllowedCompilers=lsl,cs,vb - ; *warning*, non lsl languages have access to static methods such as System.IO.File. Enable at your own risk. - AllowedCompilers=lsl - ; Compile debug info (line numbers) into the script assemblies CompileWithDebugInformation = true @@ -1899,7 +1909,8 @@ ; regex specifying for which regions concierge service is desired; if ; empty, then for all - regions = "^MeetingSpace-" + ;regions = "^MeetingSpace-" + regions = "" ; for each region that matches the regions regexp you can provide ; (optionally) a welcome template using format substitution: @@ -1907,14 +1918,14 @@ ; {1} is replaced with the name of the region ; {2} is replaced with the name of the concierge (whoami variable above) - welcomes = /path/to/welcome/template/directory + ;welcomes = /path/to/welcome/template/directory ; Concierge can send attendee lists to an event broker whenever an ; avatar enters or leaves a concierged region. the URL is subject ; to format substitution: ; {0} is replaced with the region's name ; {1} is replaced with the region's UUID - broker = "http://broker.place.com/{1}" + ;broker = "http://broker.place.com/{1}" [MRM] @@ -2055,7 +2066,7 @@ ;XmlRpcServiceWriteKey = 1234 ; Disables HTTP Keep-Alive for XmlRpcGroupsServicesConnector HTTP Requests, - ; only set to false it if you absolute sure regions and groups server suport it. + ; only set to false it if you absolute sure regions and groups server support it. ; XmlRpcDisableKeepAlive = true ; Minimum user level required to create groups @@ -2108,6 +2119,8 @@ ; If true, this will print out an error if more than a minute has passed since the last simulator frame ; Also is another source of region statistics provided via the regionstats URL Enabled = true + ; next option may still use framework performance monitors designed for debug only, so avoid it + ;ServerStatsEnabled = false [WebStats] diff --git a/bin/RestSharp.dll b/bin/RestSharp.dll new file mode 100644 index 0000000000..ea01262bdb Binary files /dev/null and b/bin/RestSharp.dll differ diff --git a/bin/RestSharp.xml b/bin/RestSharp.xml new file mode 100644 index 0000000000..27a71c7e4e --- /dev/null +++ b/bin/RestSharp.xml @@ -0,0 +1,3024 @@ + + + + RestSharp + + + + + Tries to Authenticate with the credentials of the currently logged in user, or impersonate a user + + + + + Authenticate with the credentials of the currently logged in user + + + + + Authenticate by impersonation + + + + + + + Authenticate by impersonation, using an existing ICredentials instance + + + + + + + + + Base class for OAuth 2 Authenticators. + + + Since there are many ways to authenticate in OAuth2, + this is used as a base class to differentiate between + other authenticators. + + Any other OAuth2 authenticators must derive from this + abstract class. + + + + + Access token to be used when authenticating. + + + + + Initializes a new instance of the class. + + + The access token. + + + + + Gets the access token. + + + + + The OAuth 2 authenticator using URI query parameter. + + + Based on http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-5.1.2 + + + + + Initializes a new instance of the class. + + + The access token. + + + + + The OAuth 2 authenticator using the authorization request header field. + + + Based on http://tools.ietf.org/html/draft-ietf-oauth-v2-10#section-5.1.1 + + + + + Stores the Authorization header value as "[tokenType] accessToken". used for performance. + + + + + Initializes a new instance of the class. + + + The access token. + + + + + Initializes a new instance of the class. + + + The access token. + + + The token type. + + + + + All text parameters are UTF-8 encoded (per section 5.1). + + + + + + Generates a random 16-byte lowercase alphanumeric string. + + + + + + + Generates a timestamp based on the current elapsed seconds since '01/01/1970 0000 GMT" + + + + + + + Generates a timestamp based on the elapsed seconds of a given time since '01/01/1970 0000 GMT" + + + A specified point in time. + + + + + The set of characters that are unreserved in RFC 2396 but are NOT unreserved in RFC 3986. + + + + + + URL encodes a string based on section 5.1 of the OAuth spec. + Namely, percent encoding with [RFC3986], avoiding unreserved characters, + upper-casing hexadecimal characters, and UTF-8 encoding for text value pairs. + + The value to escape. + The escaped value. + + The method is supposed to take on + RFC 3986 behavior if certain elements are present in a .config file. Even if this + actually worked (which in my experiments it doesn't), we can't rely on every + host actually having this configuration element present. + + + + + + + URL encodes a string based on section 5.1 of the OAuth spec. + Namely, percent encoding with [RFC3986], avoiding unreserved characters, + upper-casing hexadecimal characters, and UTF-8 encoding for text value pairs. + + + + + + + Sorts a collection of key-value pairs by name, and then value if equal, + concatenating them into a single string. This string should be encoded + prior to, or after normalization is run. + + + + + + + + Sorts a by name, and then value if equal. + + A collection of parameters to sort + A sorted parameter collection + + + + Creates a request URL suitable for making OAuth requests. + Resulting URLs must exclude port 80 or port 443 when accompanied by HTTP and HTTPS, respectively. + Resulting URLs must be lower case. + + + The original request URL + + + + + Creates a request elements concatentation value to send with a request. + This is also known as the signature base. + + + + The request's HTTP method type + The request URL + The request's parameters + A signature base string + + + + Creates a signature value given a signature base and the consumer secret. + This method is used when the token secret is currently unknown. + + + The hashing method + The signature base + The consumer key + + + + + Creates a signature value given a signature base and the consumer secret. + This method is used when the token secret is currently unknown. + + + The hashing method + The treatment to use on a signature value + The signature base + The consumer key + + + + + Creates a signature value given a signature base and the consumer secret and a known token secret. + + + The hashing method + The signature base + The consumer secret + The token secret + + + + + Creates a signature value given a signature base and the consumer secret and a known token secret. + + + The hashing method + The treatment to use on a signature value + The signature base + The consumer secret + The token secret + + + + + A class to encapsulate OAuth authentication flow. + + + + + + Generates a instance to pass to an + for the purpose of requesting an + unauthorized request token. + + The HTTP method for the intended request + + + + + + Generates a instance to pass to an + for the purpose of requesting an + unauthorized request token. + + The HTTP method for the intended request + Any existing, non-OAuth query parameters desired in the request + + + + + + Generates a instance to pass to an + for the purpose of exchanging a request token + for an access token authorized by the user at the Service Provider site. + + The HTTP method for the intended request + + + + + Generates a instance to pass to an + for the purpose of exchanging a request token + for an access token authorized by the user at the Service Provider site. + + The HTTP method for the intended request + + Any existing, non-OAuth query parameters desired in the request + + + + Generates a instance to pass to an + for the purpose of exchanging user credentials + for an access token authorized by the user at the Service Provider site. + + The HTTP method for the intended request + + Any existing, non-OAuth query parameters desired in the request + + + + + + + + + + + + + Allows control how class and property names and values are deserialized by XmlAttributeDeserializer + + + + + The name to use for the serialized element + + + + + Sets if the property to Deserialize is an Attribute or Element (Default: false) + + + + + Wrapper for System.Xml.Serialization.XmlSerializer. + + + + + Types of parameters that can be added to requests + + + + + Data formats + + + + + HTTP method to use when making requests + + + + + Format strings for commonly-used date formats + + + + + .NET format string for ISO 8601 date format + + + + + .NET format string for roundtrip date format + + + + + Status for responses (surprised?) + + + + + Extension method overload! + + + + + Save a byte array to a file + + Bytes to save + Full path to save file to + + + + Read a stream into a byte array + + Stream to read + byte[] + + + + Copies bytes from one stream to another + + The input stream. + The output stream. + + + + Converts a byte array to a string, using its byte order mark to convert it to the right encoding. + http://www.shrinkrays.net/code-snippets/csharp/an-extension-method-for-converting-a-byte-array-to-a-string.aspx + + An array of bytes to convert + The byte as a string. + + + + Decodes an HTML-encoded string and returns the decoded string. + + The HTML string to decode. + The decoded text. + + + + Decodes an HTML-encoded string and sends the resulting output to a TextWriter output stream. + + The HTML string to decode + The TextWriter output stream containing the decoded string. + + + + HTML-encodes a string and sends the resulting output to a TextWriter output stream. + + The string to encode. + The TextWriter output stream containing the encoded string. + + + + Reflection extensions + + + + + Retrieve an attribute from a member (property) + + Type of attribute to retrieve + Member to retrieve attribute from + + + + + Retrieve an attribute from a type + + Type of attribute to retrieve + Type to retrieve attribute from + + + + + Checks a type to see if it derives from a raw generic (e.g. List[[]]) + + + + + + + + Find a value from a System.Enum by trying several possible variants + of the string value of the enum. + + Type of enum + Value for which to search + The culture used to calculate the name variants + + + + + Convert a to a instance. + + The response status. + + responseStatus + + + + Uses Uri.EscapeDataString() based on recommendations on MSDN + http://blogs.msdn.com/b/yangxind/archive/2006/11/09/don-t-use-net-system-uri-unescapedatastring-in-url-decoding.aspx + + + + + Check that a string is not null or empty + + String to check + bool + + + + Remove underscores from a string + + String to process + string + + + + Parses most common JSON date formats + + JSON value to parse + + DateTime + + + + Remove leading and trailing " from a string + + String to parse + String + + + + Checks a string to see if it matches a regex + + String to check + Pattern to match + bool + + + + Converts a string to pascal case + + String to convert + + string + + + + Converts a string to pascal case with the option to remove underscores + + String to convert + Option to remove underscores + + + + + + Converts a string to camel case + + String to convert + + String + + + + Convert the first letter of a string to lower case + + String to convert + string + + + + Checks to see if a string is all uppper case + + String to check + bool + + + + Add underscores to a pascal-cased string + + String to convert + string + + + + Add dashes to a pascal-cased string + + String to convert + string + + + + Add an undescore prefix to a pascasl-cased string + + + + + + + Add spaces to a pascal-cased string + + String to convert + string + + + + Return possible variants of a name for name matching. + + String to convert + The culture to use for conversion + IEnumerable<string> + + + + XML Extension Methods + + + + + Returns the name of an element with the namespace if specified + + Element name + XML Namespace + + + + + Container for files to be uploaded with requests + + + + + Creates a file parameter from an array of bytes. + + The parameter name to use in the request. + The data to use as the file's contents. + The filename to use in the request. + The content type to use in the request. + The + + + + Creates a file parameter from an array of bytes. + + The parameter name to use in the request. + The data to use as the file's contents. + The filename to use in the request. + The using the default content type. + + + + The length of data to be sent + + + + + Provides raw data for file + + + + + Name of the file to use when uploading + + + + + MIME content type of file + + + + + Name of the parameter + + + + + HttpWebRequest wrapper (async methods) + + + HttpWebRequest wrapper + + + HttpWebRequest wrapper (sync methods) + + + + + Always send a multipart/form-data request - even when no Files are present. + + + + + An alternative to RequestBody, for when the caller already has the byte array. + + + + + Execute an async POST-style request with the specified HTTP Method. + + + The HTTP method to execute. + + + + + Execute an async GET-style request with the specified HTTP Method. + + + The HTTP method to execute. + + + + + Creates an IHttp + + + + + + Default constructor + + + + + Execute a POST request + + + + + Execute a PUT request + + + + + Execute a GET request + + + + + Execute a HEAD request + + + + + Execute an OPTIONS request + + + + + Execute a DELETE request + + + + + Execute a PATCH request + + + + + Execute a MERGE request + + + + + Execute a GET-style request with the specified HTTP Method. + + The HTTP method to execute. + + + + + Execute a POST-style request with the specified HTTP Method. + + The HTTP method to execute. + + + + + True if this HTTP request has any HTTP parameters + + + + + True if this HTTP request has any HTTP cookies + + + + + True if a request body has been specified + + + + + True if files have been set to be uploaded + + + + + Always send a multipart/form-data request - even when no Files are present. + + + + + UserAgent to be sent with request + + + + + Timeout in milliseconds to be used for the request + + + + + The number of milliseconds before the writing or reading times out. + + + + + System.Net.ICredentials to be sent with request + + + + + The System.Net.CookieContainer to be used for the request + + + + + The method to use to write the response instead of reading into RawBytes + + + + + Collection of files to be sent with request + + + + + Whether or not HTTP 3xx response redirects should be automatically followed + + + + + X509CertificateCollection to be sent with request + + + + + Maximum number of automatic redirects to follow if FollowRedirects is true + + + + + Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) + will be sent along to the server. + + + + + HTTP headers to be sent with request + + + + + HTTP parameters (QueryString or Form values) to be sent with request + + + + + HTTP cookies to be sent with request + + + + + Request body to be sent with request + + + + + Content type of the request body. + + + + + An alternative to RequestBody, for when the caller already has the byte array. + + + + + URL to call for this request + + + + + Flag to send authorisation header with the HttpWebRequest + + + + + Proxy info to be sent with request + + + + + Representation of an HTTP cookie + + + + + Comment of the cookie + + + + + Comment of the cookie + + + + + Indicates whether the cookie should be discarded at the end of the session + + + + + Domain of the cookie + + + + + Indicates whether the cookie is expired + + + + + Date and time that the cookie expires + + + + + Indicates that this cookie should only be accessed by the server + + + + + Name of the cookie + + + + + Path of the cookie + + + + + Port of the cookie + + + + + Indicates that the cookie should only be sent over secure channels + + + + + Date and time the cookie was created + + + + + Value of the cookie + + + + + Version of the cookie + + + + + Container for HTTP file + + + + + The length of data to be sent + + + + + Provides raw data for file + + + + + Name of the file to use when uploading + + + + + MIME content type of file + + + + + Name of the parameter + + + + + Representation of an HTTP header + + + + + Name of the header + + + + + Value of the header + + + + + Representation of an HTTP parameter (QueryString or Form value) + + + + + Name of the parameter + + + + + Value of the parameter + + + + + HTTP response data + + + + + HTTP response data + + + + + MIME content type of response + + + + + Length in bytes of the response content + + + + + Encoding of the response content + + + + + String representation of response content + + + + + HTTP response status code + + + + + Description of HTTP status returned + + + + + Response content + + + + + The URL that actually responded to the content (different from request if redirected) + + + + + HttpWebResponse.Server + + + + + Headers returned by server with the response + + + + + Cookies returned by server with the response + + + + + Status of the request. Will return Error for transport errors. + HTTP errors will still return ResponseStatus.Completed, check StatusCode instead + + + + + Transport or other non-HTTP error generated while attempting request + + + + + Exception thrown when error is encountered. + + + + + Default constructor + + + + + MIME content type of response + + + + + Length in bytes of the response content + + + + + Encoding of the response content + + + + + Lazy-loaded string representation of response content + + + + + HTTP response status code + + + + + Description of HTTP status returned + + + + + Response content + + + + + The URL that actually responded to the content (different from request if redirected) + + + + + HttpWebResponse.Server + + + + + Headers returned by server with the response + + + + + Cookies returned by server with the response + + + + + Status of the request. Will return Error for transport errors. + HTTP errors will still return ResponseStatus.Completed, check StatusCode instead + + + + + Transport or other non-HTTP error generated while attempting request + + + + + Exception thrown when error is encountered. + + + + + + + + + + + + + + + + + + + + + + + + Executes a GET-style request and callback asynchronously, authenticating if needed + + Request to be executed + Callback function to be executed upon completion providing access to the async handle. + The HTTP method to execute + + + + Executes a POST-style request and callback asynchronously, authenticating if needed + + Request to be executed + Callback function to be executed upon completion providing access to the async handle. + The HTTP method to execute + + + + Executes a GET-style request and callback asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + Callback function to be executed upon completion + The HTTP method to execute + + + + Executes a GET-style request and callback asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + Callback function to be executed upon completion + The HTTP method to execute + + + + Executes the request and callback asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + The cancellation token + + + + Executes the request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + + + + Executes a GET-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + + + + Executes a GET-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + The cancellation token + + + + Executes a POST-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + + + + Executes a POST-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + The cancellation token + + + + Executes the request and callback asynchronously, authenticating if needed + + Request to be executed + The cancellation token + + + + Executes the request asynchronously, authenticating if needed + + Request to be executed + + + + Executes a GET-style asynchronously, authenticating if needed + + Request to be executed + + + + Executes a GET-style asynchronously, authenticating if needed + + Request to be executed + The cancellation token + + + + Executes a POST-style asynchronously, authenticating if needed + + Request to be executed + + + + Executes a POST-style asynchronously, authenticating if needed + + Request to be executed + The cancellation token + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + X509CertificateCollection to be sent with request + + + + + Adds a file to the Files collection to be included with a POST or PUT request + (other methods do not support file uploads). + + The parameter name to use in the request + Full path to file to upload + This request + + + + Adds the bytes to the Files collection with the specified file name + + The parameter name to use in the request + The file data + The file name to use for the uploaded file + This request + + + + Adds the bytes to the Files collection with the specified file name and content type + + The parameter name to use in the request + The file data + The file name to use for the uploaded file + The MIME type of the file to upload + This request + + + + Serializes obj to format specified by RequestFormat, but passes xmlNamespace if using the default XmlSerializer + The default format is XML. Change RequestFormat if you wish to use a different serialization format. + + The object to serialize + The XML namespace to use when serializing + This request + + + + Serializes obj to data format specified by RequestFormat and adds it to the request body. + The default format is XML. Change RequestFormat if you wish to use a different serialization format. + + The object to serialize + This request + + + + Serializes obj to JSON format and adds it to the request body. + + The object to serialize + This request + + + + Serializes obj to XML format and adds it to the request body. + + The object to serialize + This request + + + + Serializes obj to format specified by RequestFormat, but passes xmlNamespace if using the default XmlSerializer + Serializes obj to XML format and passes xmlNamespace then adds it to the request body. + + The object to serialize + The XML namespace to use when serializing + This request + + + + Calls AddParameter() for all public, readable properties specified in the includedProperties list + + + request.AddObject(product, "ProductId", "Price", ...); + + The object with properties to add as parameters + The names of the properties to include + This request + + + + Calls AddParameter() for all public, readable properties of obj + + The object with properties to add as parameters + This request + + + + Add the parameter to the request + + Parameter to add + + + + + Adds a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT) + + Name of the parameter + Value of the parameter + This request + + + + Adds a parameter to the request. There are five types of parameters: + - GetOrPost: Either a QueryString value or encoded form value based on method + - HttpHeader: Adds the name/value pair to the HTTP request's Headers collection + - UrlSegment: Inserted into URL if there is a matching url token e.g. {AccountId} + - Cookie: Adds the name/value pair to the HTTP request's Cookies collection + - RequestBody: Used by AddBody() (not recommended to use directly) + + Name of the parameter + Value of the parameter + The type of parameter to add + This request + + + + Shortcut to AddParameter(name, value, HttpHeader) overload + + Name of the header to add + Value of the header to add + + + + + Shortcut to AddParameter(name, value, Cookie) overload + + Name of the cookie to add + Value of the cookie to add + + + + + Shortcut to AddParameter(name, value, UrlSegment) overload + + Name of the segment to add + Value of the segment to add + + + + + Shortcut to AddParameter(name, value, QueryString) overload + + Name of the parameter to add + Value of the parameter to add + + + + + Always send a multipart/form-data request - even when no Files are present. + + + + + Serializer to use when writing JSON request bodies. Used if RequestFormat is Json. + By default the included JsonSerializer is used (currently using JSON.NET default serialization). + + + + + Serializer to use when writing XML request bodies. Used if RequestFormat is Xml. + By default the included XmlSerializer is used. + + + + + Set this to write response to Stream rather than reading into memory. + + + + + Container of all HTTP parameters to be passed with the request. + See AddParameter() for explanation of the types of parameters that can be passed + + + + + Container of all the files to be uploaded with the request. + + + + + Determines what HTTP method to use for this request. Supported methods: GET, POST, PUT, DELETE, HEAD, OPTIONS + Default is GET + + + + + The Resource URL to make the request against. + Tokens are substituted with UrlSegment parameters and match by name. + Should not include the scheme or domain. Do not include leading slash. + Combined with RestClient.BaseUrl to assemble final URL: + {BaseUrl}/{Resource} (BaseUrl is scheme + domain, e.g. http://example.com) + + + // example for url token replacement + request.Resource = "Products/{ProductId}"; + request.AddParameter("ProductId", 123, ParameterType.UrlSegment); + + + + + Serializer to use when writing XML request bodies. Used if RequestFormat is Xml. + By default XmlSerializer is used. + + + + + Used by the default deserializers to determine where to start deserializing from. + Can be used to skip container or root elements that do not have corresponding deserialzation targets. + + + + + Used by the default deserializers to explicitly set which date format string to use when parsing dates. + + + + + Used by XmlDeserializer. If not specified, XmlDeserializer will flatten response by removing namespaces from element names. + + + + + In general you would not need to set this directly. Used by the NtlmAuthenticator. + + + + + Timeout in milliseconds to be used for the request. This timeout value overrides a timeout set on the RestClient. + + + + + The number of milliseconds before the writing or reading times out. This timeout value overrides a timeout set on the RestClient. + + + + + How many attempts were made to send this Request? + + + This Number is incremented each time the RestClient sends the request. + Useful when using Asynchronous Execution with Callbacks + + + + + Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) + will be sent along to the server. The default is false. + + + + + Container for data sent back from API + + + + + The RestRequest that was made to get this RestResponse + + + Mainly for debugging if ResponseStatus is not OK + + + + + MIME content type of response + + + + + Length in bytes of the response content + + + + + Encoding of the response content + + + + + String representation of response content + + + + + HTTP response status code + + + + + Description of HTTP status returned + + + + + Response content + + + + + The URL that actually responded to the content (different from request if redirected) + + + + + HttpWebResponse.Server + + + + + Cookies returned by server with the response + + + + + Headers returned by server with the response + + + + + Status of the request. Will return Error for transport errors. + HTTP errors will still return ResponseStatus.Completed, check StatusCode instead + + + + + Transport or other non-HTTP error generated while attempting request + + + + + Exceptions thrown during the request, if any. + + Will contain only network transport or framework exceptions thrown during the request. + HTTP protocol errors are handled by RestSharp and will not appear here. + + + + Container for data sent back from API including deserialized data + + Type of data to deserialize to + + + + Deserialized entity data + + + + + Parameter container for REST requests + + + + + Return a human-readable representation of this parameter + + String + + + + Name of the parameter + + + + + Value of the parameter + + + + + Type of the parameter + + + + + Client to translate RestRequests into Http requests and process response result + + + + + Executes the request and callback asynchronously, authenticating if needed + + Request to be executed + Callback function to be executed upon completion providing access to the async handle. + + + + Executes a GET-style request and callback asynchronously, authenticating if needed + + Request to be executed + Callback function to be executed upon completion providing access to the async handle. + The HTTP method to execute + + + + Executes a POST-style request and callback asynchronously, authenticating if needed + + Request to be executed + Callback function to be executed upon completion providing access to the async handle. + The HTTP method to execute + + + + Executes the request and callback asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + Callback function to be executed upon completion + + + + Executes a GET-style request and callback asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + Callback function to be executed upon completion + The HTTP method to execute + + + + Executes a POST-style request and callback asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + Callback function to be executed upon completion + The HTTP method to execute + + + + Executes a GET-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + + + + Executes a GET-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + The cancellation token + + + + Executes a POST-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + + + + Executes a POST-style request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + The cancellation token + + + + Executes the request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + + + + Executes the request asynchronously, authenticating if needed + + Target deserialization type + Request to be executed + The cancellation token + + + + Executes the request asynchronously, authenticating if needed + + Request to be executed + + + + Executes a GET-style asynchronously, authenticating if needed + + Request to be executed + + + + Executes a GET-style asynchronously, authenticating if needed + + Request to be executed + The cancellation token + + + + Executes a POST-style asynchronously, authenticating if needed + + Request to be executed + + + + Executes a POST-style asynchronously, authenticating if needed + + Request to be executed + The cancellation token + + + + Executes the request asynchronously, authenticating if needed + + Request to be executed + The cancellation token + + + + Default constructor that registers default content handlers + + + + + Sets the BaseUrl property for requests made by this client instance + + + + + + Sets the BaseUrl property for requests made by this client instance + + + + + + Registers a content handler to process response content + + MIME content type of the response content + Deserializer to use to process content + + + + Remove a content handler for the specified MIME content type + + MIME content type to remove + + + + Remove all content handlers + + + + + Retrieve the handler for the specified MIME content type + + MIME content type to retrieve + IDeserializer instance + + + + Assembles URL to call based on parameters, method and resource + + RestRequest to execute + Assembled System.Uri + + + + Executes the specified request and downloads the response data + + Request to execute + Response data + + + + Executes the request and returns a response, authenticating if needed + + Request to be executed + RestResponse + + + + Executes the specified request and deserializes the response content using the appropriate content handler + + Target deserialization type + Request to execute + RestResponse[[T]] with deserialized data in Data property + + + + Parameters included with every request made with this instance of RestClient + If specified in both client and request, the request wins + + + + + Maximum number of redirects to follow if FollowRedirects is true + + + + + X509CertificateCollection to be sent with request + + + + + Proxy to use for requests made by this client instance. + Passed on to underlying WebRequest if set. + + + + + Default is true. Determine whether or not requests that result in + HTTP status codes of 3xx should follow returned redirect + + + + + The CookieContainer used for requests made by this client instance + + + + + UserAgent to use for requests made by this client instance + + + + + Timeout in milliseconds to use for requests made by this client instance + + + + + The number of milliseconds before the writing or reading times out. + + + + + Whether to invoke async callbacks using the SynchronizationContext.Current captured when invoked + + + + + Authenticator to use for requests made by this client instance + + + + + Combined with Request.Resource to construct URL for request + Should include scheme and domain without trailing slash. + + + client.BaseUrl = new Uri("http://example.com"); + + + + + Executes the request and callback asynchronously, authenticating if needed + + The IRestClient this method extends + Request to be executed + Callback function to be executed upon completion + + + + Executes the request and callback asynchronously, authenticating if needed + + The IRestClient this method extends + Target deserialization type + Request to be executed + Callback function to be executed upon completion providing access to the async handle + + + + Add a parameter to use on every request made with this client instance + + The IRestClient instance + Parameter to add + + + + + Removes a parameter from the default parameters that are used on every request made with this client instance + + The IRestClient instance + The name of the parameter that needs to be removed + + + + + Adds a HTTP parameter (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT) + Used on every request made by this client instance + + The IRestClient instance + Name of the parameter + Value of the parameter + This request + + + + Adds a parameter to the request. There are four types of parameters: + - GetOrPost: Either a QueryString value or encoded form value based on method + - HttpHeader: Adds the name/value pair to the HTTP request's Headers collection + - UrlSegment: Inserted into URL if there is a matching url token e.g. {AccountId} + - RequestBody: Used by AddBody() (not recommended to use directly) + + The IRestClient instance + Name of the parameter + Value of the parameter + The type of parameter to add + This request + + + + Shortcut to AddDefaultParameter(name, value, HttpHeader) overload + + The IRestClient instance + Name of the header to add + Value of the header to add + + + + + Shortcut to AddDefaultParameter(name, value, UrlSegment) overload + + The IRestClient instance + Name of the segment to add + Value of the segment to add + + + + + Container for data used to make requests + + + + + Default constructor + + + + + Sets Method property to value of method + + Method to use for this request + + + + Sets Resource property + + Resource to use for this request + + + + Sets Resource and Method properties + + Resource to use for this request + Method to use for this request + + + + Sets Resource property + + Resource to use for this request + + + + Sets Resource and Method properties + + Resource to use for this request + Method to use for this request + + + + Adds a file to the Files collection to be included with a POST or PUT request + (other methods do not support file uploads). + + The parameter name to use in the request + Full path to file to upload + This request + + + + Adds the bytes to the Files collection with the specified file name + + The parameter name to use in the request + The file data + The file name to use for the uploaded file + This request + + + + Adds the bytes to the Files collection with the specified file name and content type + + The parameter name to use in the request + The file data + The file name to use for the uploaded file + The MIME type of the file to upload + This request + + + + Adds the bytes to the Files collection with the specified file name and content type + + The parameter name to use in the request + A function that writes directly to the stream. Should NOT close the stream. + The file name to use for the uploaded file + This request + + + + Adds the bytes to the Files collection with the specified file name and content type + + The parameter name to use in the request + A function that writes directly to the stream. Should NOT close the stream. + The file name to use for the uploaded file + The MIME type of the file to upload + This request + + + + Serializes obj to format specified by RequestFormat, but passes xmlNamespace if using the default XmlSerializer + The default format is XML. Change RequestFormat if you wish to use a different serialization format. + + The object to serialize + The XML namespace to use when serializing + This request + + + + Serializes obj to data format specified by RequestFormat and adds it to the request body. + The default format is XML. Change RequestFormat if you wish to use a different serialization format. + + The object to serialize + This request + + + + Serializes obj to JSON format and adds it to the request body. + + The object to serialize + This request + + + + Serializes obj to XML format and adds it to the request body. + + The object to serialize + This request + + + + Serializes obj to format specified by RequestFormat, but passes xmlNamespace if using the default XmlSerializer + Serializes obj to XML format and passes xmlNamespace then adds it to the request body. + + The object to serialize + The XML namespace to use when serializing + This request + + + + Calls AddParameter() for all public, readable properties specified in the includedProperties list + + + request.AddObject(product, "ProductId", "Price", ...); + + The object with properties to add as parameters + The names of the properties to include + This request + + + + Calls AddParameter() for all public, readable properties of obj + + The object with properties to add as parameters + This request + + + + Add the parameter to the request + + Parameter to add + + + + + Adds a HTTP parameter to the request (QueryString for GET, DELETE, OPTIONS and HEAD; Encoded form for POST and PUT) + + Name of the parameter + Value of the parameter + This request + + + + Adds a parameter to the request. There are four types of parameters: + - GetOrPost: Either a QueryString value or encoded form value based on method + - HttpHeader: Adds the name/value pair to the HTTP request's Headers collection + - UrlSegment: Inserted into URL if there is a matching url token e.g. {AccountId} + - RequestBody: Used by AddBody() (not recommended to use directly) + + Name of the parameter + Value of the parameter + The type of parameter to add + This request + + + + Shortcut to AddParameter(name, value, HttpHeader) overload + + Name of the header to add + Value of the header to add + + + + + Shortcut to AddParameter(name, value, Cookie) overload + + Name of the cookie to add + Value of the cookie to add + + + + + Shortcut to AddParameter(name, value, UrlSegment) overload + + Name of the segment to add + Value of the segment to add + + + + + Shortcut to AddParameter(name, value, QueryString) overload + + Name of the parameter to add + Value of the parameter to add + + + + + Internal Method so that RestClient can increase the number of attempts + + + + + Always send a multipart/form-data request - even when no Files are present. + + + + + Serializer to use when writing JSON request bodies. Used if RequestFormat is Json. + By default the included JsonSerializer is used (currently using JSON.NET default serialization). + + + + + Serializer to use when writing XML request bodies. Used if RequestFormat is Xml. + By default the included XmlSerializer is used. + + + + + Set this to write response to Stream rather than reading into memory. + + + + + Determine whether or not the "default credentials" (e.g. the user account under which the current process is running) + will be sent along to the server. The default is false. + + + + + Container of all HTTP parameters to be passed with the request. + See AddParameter() for explanation of the types of parameters that can be passed + + + + + Container of all the files to be uploaded with the request. + + + + + Determines what HTTP method to use for this request. Supported methods: GET, POST, PUT, DELETE, HEAD, OPTIONS + Default is GET + + + + + The Resource URL to make the request against. + Tokens are substituted with UrlSegment parameters and match by name. + Should not include the scheme or domain. Do not include leading slash. + Combined with RestClient.BaseUrl to assemble final URL: + {BaseUrl}/{Resource} (BaseUrl is scheme + domain, e.g. http://example.com) + + + // example for url token replacement + request.Resource = "Products/{ProductId}"; + request.AddParameter("ProductId", 123, ParameterType.UrlSegment); + + + + + Serializer to use when writing XML request bodies. Used if RequestFormat is Xml. + By default XmlSerializer is used. + + + + + Used by the default deserializers to determine where to start deserializing from. + Can be used to skip container or root elements that do not have corresponding deserialzation targets. + + + + + A function to run prior to deserializing starting (e.g. change settings if error encountered) + + + + + Used by the default deserializers to explicitly set which date format string to use when parsing dates. + + + + + Used by XmlDeserializer. If not specified, XmlDeserializer will flatten response by removing namespaces from element names. + + + + + In general you would not need to set this directly. Used by the NtlmAuthenticator. + + + + + Gets or sets a user-defined state object that contains information about a request and which can be later + retrieved when the request completes. + + + + + Timeout in milliseconds to be used for the request. This timeout value overrides a timeout set on the RestClient. + + + + + The number of milliseconds before the writing or reading times out. This timeout value overrides a timeout set on the RestClient. + + + + + How many attempts were made to send this Request? + + + This Number is incremented each time the RestClient sends the request. + Useful when using Asynchronous Execution with Callbacks + + + + + Base class for common properties shared by RestResponse and RestResponse[[T]] + + + + + Default constructor + + + + + The RestRequest that was made to get this RestResponse + + + Mainly for debugging if ResponseStatus is not OK + + + + + MIME content type of response + + + + + Length in bytes of the response content + + + + + Encoding of the response content + + + + + String representation of response content + + + + + HTTP response status code + + + + + Description of HTTP status returned + + + + + Response content + + + + + The URL that actually responded to the content (different from request if redirected) + + + + + HttpWebResponse.Server + + + + + Cookies returned by server with the response + + + + + Headers returned by server with the response + + + + + Status of the request. Will return Error for transport errors. + HTTP errors will still return ResponseStatus.Completed, check StatusCode instead + + + + + Transport or other non-HTTP error generated while attempting request + + + + + The exception thrown during the request, if any + + + + + Container for data sent back from API including deserialized data + + Type of data to deserialize to + + + + Deserialized entity data + + + + + Container for data sent back from API + + + + + Comment of the cookie + + + + + Comment of the cookie + + + + + Indicates whether the cookie should be discarded at the end of the session + + + + + Domain of the cookie + + + + + Indicates whether the cookie is expired + + + + + Date and time that the cookie expires + + + + + Indicates that this cookie should only be accessed by the server + + + + + Name of the cookie + + + + + Path of the cookie + + + + + Port of the cookie + + + + + Indicates that the cookie should only be sent over secure channels + + + + + Date and time the cookie was created + + + + + Value of the cookie + + + + + Version of the cookie + + + + + Wrapper for System.Xml.Serialization.XmlSerializer. + + + + + Default constructor, does not specify namespace + + + + + Specify the namespaced to be used when serializing + + XML namespace + + + + Serialize the object as XML + + Object to serialize + XML as string + + + + Name of the root element to use when serializing + + + + + XML namespace to use when serializing + + + + + Format string to use when serializing dates + + + + + Content type for serialized content + + + + + Encoding for serialized content + + + + + Need to subclass StringWriter in order to override Encoding + + + + + Default JSON serializer for request bodies + Doesn't currently use the SerializeAs attribute, defers to Newtonsoft's attributes + + + + + Default serializer + + + + + Serialize the object as JSON + + Object to serialize + JSON as String + + + + Unused for JSON Serialization + + + + + Unused for JSON Serialization + + + + + Unused for JSON Serialization + + + + + Content type for serialized content + + + + + Allows control how class and property names and values are serialized by XmlSerializer + Currently not supported with the JsonSerializer + When specified at the property level the class-level specification is overridden + + + + + Called by the attribute when NameStyle is speficied + + The string to transform + String + + + + The name to use for the serialized element + + + + + Sets the value to be serialized as an Attribute instead of an Element + + + + + The culture to use when serializing + + + + + Transforms the casing of the name based on the selected value. + + + + + The order to serialize the element. Default is int.MaxValue. + + + + + Options for transforming casing of element names + + + + + Default XML Serializer + + + + + Default constructor, does not specify namespace + + + + + Specify the namespaced to be used when serializing + + XML namespace + + + + Serialize the object as XML + + Object to serialize + XML as string + + + + Determines if a given object is numeric in any way + (can be integer, double, null, etc). + + + + + Name of the root element to use when serializing + + + + + XML namespace to use when serializing + + + + + Format string to use when serializing dates + + + + + Content type for serialized content + + + + + Helper methods for validating required values + + + + + Require a parameter to not be null + + Name of the parameter + Value of the parameter + + + + Represents the json array. + + + + + Initializes a new instance of the class. + + + + + Initializes a new instance of the class. + + The capacity of the json array. + + + + The json representation of the array. + + The json representation of the array. + + + + Represents the json object. + + + + + The internal member dictionary. + + + + + Initializes a new instance of . + + + + + Initializes a new instance of . + + The implementation to use when comparing keys, or null to use the default for the type of the key. + + + + Adds the specified key. + + The key. + The value. + + + + Determines whether the specified key contains key. + + The key. + + true if the specified key contains key; otherwise, false. + + + + + Removes the specified key. + + The key. + + + + + Tries the get value. + + The key. + The value. + + + + + Adds the specified item. + + The item. + + + + Clears this instance. + + + + + Determines whether [contains] [the specified item]. + + The item. + + true if [contains] [the specified item]; otherwise, false. + + + + + Copies to. + + The array. + Index of the array. + + + + Removes the specified item. + + The item. + + + + + Gets the enumerator. + + + + + + Returns an enumerator that iterates through a collection. + + + An object that can be used to iterate through the collection. + + + + + Returns a json that represents the current . + + + A json that represents the current . + + + + + Gets the at the specified index. + + + + + + Gets the keys. + + The keys. + + + + Gets the values. + + The values. + + + + Gets or sets the with the specified key. + + + + + + Gets the count. + + The count. + + + + Gets a value indicating whether this instance is read only. + + + true if this instance is read only; otherwise, false. + + + + + This class encodes and decodes JSON strings. + Spec. details, see http://www.json.org/ + + JSON uses Arrays and Objects. These correspond here to the datatypes JsonArray(IList<object>) and JsonObject(IDictionary<string,object>). + All numbers are parsed to doubles. + + + + + Parses the string json into a value + + A JSON string. + An IList<object>, a IDictionary<string,object>, a double, a string, null, true, or false + + + + Try parsing the json string into a value. + + + A JSON string. + + + The object. + + + Returns true if successfull otherwise false. + + + + + Converts a IDictionary<string,object> / IList<object> object into a JSON string + + A IDictionary<string,object> / IList<object> + Serializer strategy to use + A JSON encoded string, or null if object 'json' is not serializable + + + + Determines if a given object is numeric in any way + (can be integer, double, null, etc). + + + + + Helper methods for validating values + + + + + Validate an integer value is between the specified values (exclusive of min/max) + + Value to validate + Exclusive minimum value + Exclusive maximum value + + + + Validate a string length + + String to be validated + Maximum length of the string + + + diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 7d13d4382f..2cd189750b 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -287,8 +287,8 @@ [GridService] LocalServiceModule = "OpenSim.Services.GridService.dll:GridService" - ; Realm = "regions" - ; AllowDuplicateNames = "True" + ; Realm = "regions" + ; AllowDuplicateNames = "" ;; Perform distance check for the creation of a linked region ; Check4096 = "True" @@ -444,10 +444,6 @@ ; for the server connector LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" - ; Set this to true to allow the use of advanced web services and multiple - ; bots using one account - AllowDuplicatePresences = false; - [AvatarService] ; for the server connector LocalServiceModule = "OpenSim.Services.AvatarService.dll:AvatarService" diff --git a/bin/Robust.exe.config b/bin/Robust.exe.config index 7db6458d26..3ad5f31732 100644 --- a/bin/Robust.exe.config +++ b/bin/Robust.exe.config @@ -5,11 +5,10 @@ - - + diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index d33178c461..2ebcef744b 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -390,10 +390,6 @@ [PresenceService] ; for the server connector LocalServiceModule = "OpenSim.Services.PresenceService.dll:PresenceService" - ; Set this to true to allow the use of advanced web services and multiple - ; bots using one account - AllowDuplicatePresences = false; - [AvatarService] ; for the server connector diff --git a/bin/Robust32.exe b/bin/Robust32.exe new file mode 100644 index 0000000000..e5e4674337 Binary files /dev/null and b/bin/Robust32.exe differ diff --git a/bin/OpenSim.32BitLaunch.exe.config b/bin/Robust32.exe.config similarity index 53% rename from bin/OpenSim.32BitLaunch.exe.config rename to bin/Robust32.exe.config index 5b7807a8e3..ca3ee0e0cf 100644 --- a/bin/OpenSim.32BitLaunch.exe.config +++ b/bin/Robust32.exe.config @@ -1,75 +1,72 @@ - +
+ + + - - + - - + + - - - - - - + - - + + - - + - - - - - - - - - - - - - + - + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/Robust32.pdb b/bin/Robust32.pdb new file mode 100644 index 0000000000..15a0d7544e Binary files /dev/null and b/bin/Robust32.pdb differ diff --git a/bin/Robust32.vshost.exe b/bin/Robust32.vshost.exe new file mode 100644 index 0000000000..681ab771eb Binary files /dev/null and b/bin/Robust32.vshost.exe differ diff --git a/bin/Robust.32BitLaunch.exe.config b/bin/Robust32.vshost.exe.config similarity index 53% rename from bin/Robust.32BitLaunch.exe.config rename to bin/Robust32.vshost.exe.config index 0399a1bd34..ca3ee0e0cf 100644 --- a/bin/Robust.32BitLaunch.exe.config +++ b/bin/Robust32.vshost.exe.config @@ -1,63 +1,72 @@ - +
+ + + - - + - - + + - - - - + - - + + - - + - - - + - + + + + + + + + + + + + + \ No newline at end of file diff --git a/bin/config-include/Grid.ini b/bin/config-include/Grid.ini index fc988792b4..988e681a00 100644 --- a/bin/config-include/Grid.ini +++ b/bin/config-include/Grid.ini @@ -12,7 +12,7 @@ InventoryServices = "RemoteXInventoryServicesConnector" GridServices = "RemoteGridServicesConnector" AvatarServices = "RemoteAvatarServicesConnector" - NeighbourServices = "RemoteNeighbourServicesConnector" + NeighbourServices = "NeighbourServicesOutConnector" AuthenticationServices = "RemoteAuthenticationServicesConnector" AuthorizationServices = "LocalAuthorizationServicesConnector" PresenceServices = "RemotePresenceServicesConnector" diff --git a/bin/config-include/GridHypergrid.ini b/bin/config-include/GridHypergrid.ini index f5f4c8755f..709c462e34 100644 --- a/bin/config-include/GridHypergrid.ini +++ b/bin/config-include/GridHypergrid.ini @@ -15,7 +15,7 @@ InventoryServices = "HGInventoryBroker" GridServices = "RemoteGridServicesConnector" AvatarServices = "RemoteAvatarServicesConnector" - NeighbourServices = "RemoteNeighbourServicesConnector" + NeighbourServices = "NeighbourServicesOutConnector" AuthenticationServices = "RemoteAuthenticationServicesConnector" AuthorizationServices = "LocalAuthorizationServicesConnector" PresenceServices = "RemotePresenceServicesConnector" @@ -36,9 +36,6 @@ SimulationServiceInConnector = true LibraryModule = true -[Profile] - Module = "BasicProfileModule" - [SimulationDataStore] LocalServiceModule = "OpenSim.Services.SimulationService.dll:SimulationDataService" diff --git a/bin/config-include/HyperSimianGrid.ini b/bin/config-include/HyperSimianGrid.ini index efad5772a3..018c65e92c 100644 --- a/bin/config-include/HyperSimianGrid.ini +++ b/bin/config-include/HyperSimianGrid.ini @@ -29,7 +29,7 @@ InventoryServices = "HGInventoryBroker" AvatarServices = "SimianAvatarServiceConnector" - NeighbourServices = "RemoteNeighbourServicesConnector" + NeighbourServices = "NeighbourServicesOutConnector" SimulationServices = "RemoteSimulationConnectorModule" EntityTransferModule = "HGEntityTransferModule" InventoryAccessModule = "HGInventoryAccessModule" diff --git a/bin/config-include/SimianGrid.ini b/bin/config-include/SimianGrid.ini index 5749656231..b3db08a598 100644 --- a/bin/config-include/SimianGrid.ini +++ b/bin/config-include/SimianGrid.ini @@ -29,7 +29,7 @@ InventoryServices = "SimianInventoryServiceConnector" AvatarServices = "SimianAvatarServiceConnector" - NeighbourServices = "RemoteNeighbourServicesConnector" + NeighbourServices = "NeighbourServicesOutConnector" SimulationServices = "RemoteSimulationConnectorModule" EntityTransferModule = "BasicEntityTransferModule" InventoryAccessModule = "BasicInventoryAccessModule" diff --git a/bin/config-include/Standalone.ini b/bin/config-include/Standalone.ini index 78ada2b7c3..db7cb365cd 100644 --- a/bin/config-include/Standalone.ini +++ b/bin/config-include/Standalone.ini @@ -7,7 +7,7 @@ [Modules] AssetServices = "LocalAssetServicesConnector" InventoryServices = "LocalInventoryServicesConnector" - NeighbourServices = "LocalNeighbourServicesConnector" + NeighbourServices = "NeighbourServicesOutConnector" AuthenticationServices = "LocalAuthenticationServicesConnector" AuthorizationServices = "LocalAuthorizationServicesConnector" GridServices = "LocalGridServicesConnector" diff --git a/bin/config-include/StandaloneHypergrid.ini b/bin/config-include/StandaloneHypergrid.ini index eaacfff36a..84867a9a3c 100644 --- a/bin/config-include/StandaloneHypergrid.ini +++ b/bin/config-include/StandaloneHypergrid.ini @@ -10,7 +10,7 @@ [Modules] AssetServices = "HGAssetBroker" InventoryServices = "HGInventoryBroker" - NeighbourServices = "LocalNeighbourServicesConnector" + NeighbourServices = "NeighbourServicesOutConnector" AuthenticationServices = "LocalAuthenticationServicesConnector" AuthorizationServices = "LocalAuthorizationServicesConnector" GridServices = "LocalGridServicesConnector" diff --git a/bin/config-include/osslEnable.ini b/bin/config-include/osslEnable.ini index 45eddf748e..5987952bdc 100644 --- a/bin/config-include/osslEnable.ini +++ b/bin/config-include/osslEnable.ini @@ -31,7 +31,7 @@ ; higher threat level OSSL functions, as detailed later on. OSFunctionThreatLevel = VeryLow - ; Each of the OSSL functions can be enabled or disabled individually. + ; Some of the OSSL functions can be enabled or disabled individually. ; To disable, set the value to 'false'. ; To enable for everyone, set the value to 'true'. ; To enable for individuals or groups, set it to a comma separated list. This checks @@ -45,12 +45,10 @@ ; "PARCEL_OWNER" -- enable for parcel owner ; "PARCEL_GROUP_MEMBER" -- enable for any member of the parcel group ; uuid -- enable for specified ID (may be avatar or group ID) - - ; The OSSL function name is prepended with "Allow_" and it checks against - ; the owners of the containing prim. There can also be entries beginning with - ; 'Creators_". The 'Creators_" parameters can only be a list of UUIDs and it is - ; checked against the creator of the script itself. - + ; from this we can also create macros that can be include in the list as + ; ${XEngine|macroname} see examples below + + ; parcel macros ; Allowing ossl functions for anyone owning a parcel can be dangerous especially if ; a region is selling or otherwise giving away parcel ownership. By default, parcel ; ownership or group membership does not enable OSSL functions. Uncomment the @@ -62,49 +60,31 @@ ; osslParcelO = "PARCEL_OWNER," ; osslParcelOG = "PARCEL_GROUP_MEMBER,PARCEL_OWNER," - ; There are a block of functions for creating and controlling NPCs. + ; NPC macros ; These can be mis-used so limit use to those you can trust. - osslNPC = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER - - ; ThreatLevel None - Allow_osDrawEllipse = true - Allow_osDrawFilledPolygon = true - Allow_osDrawFilledRectangle = true - Allow_osDrawImage = true - Allow_osDrawLine = true - Allow_osDrawPolygon = true - Allow_osDrawRectangle = true - Allow_osDrawText = true + osslNPC = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER + + ; The OSSL function name is prepended with "Allow_" and it checks against + ; the owners of the containing prim. There can also be entries beginning with + ; 'Creators_". The 'Creators_" parameters can only be a list of UUIDs and it is + ; checked against the creator of the script itself. + +; ************************************************* + + ; ThreatLevel None Allow_osGetAgents = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetAvatarList = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER - Allow_osGetCurrentSunHour = true Allow_osGetGender = true Allow_osGetHealth = true Allow_osGetHealRate = true - Allow_osGetInventoryDesc = true - Allow_osGetMapTexture = true - Allow_osGetRegionSize = true + Allow_osGetNPCList = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetRezzingObject = true - Allow_osGetSunParam = true - Allow_osGetTerrainHeight = true - Allow_osIsNpc = true - Allow_osIsUUID = true - Allow_osList2Double = true - Allow_osMax = true - Allow_osMin = true - Allow_osMovePen = true Allow_osNpcGetOwner = ${XEngine|osslNPC} Allow_osParseJSON = true Allow_osParseJSONNew = true - Allow_osSetFontName = true - Allow_osSetFontSize = true - Allow_osSetPenCap = true - Allow_osSetPenColor = true - Allow_osSetPenSize = true Allow_osSetSunParam = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osTeleportOwner = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osWindActiveModelPluginName = true - Allow_osCheckODE = true ; Here for completeness. This function cannot be turned off ; ThreatLevel Nuisance Allow_osSetEstateSunSettings = ESTATE_MANAGER,ESTATE_OWNER @@ -114,11 +94,11 @@ Allow_osEjectFromGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceBreakAllLinks = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceBreakLink = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER - Allow_osGetDrawStringSize = true Allow_osGetWindParam = true Allow_osInviteToGroup = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osReplaceString = true Allow_osSetDynamicTextureData = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER + Allow_osSetDynamicTextureDataFace = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetDynamicTextureDataBlend = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetDynamicTextureDataBlendFace = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER Allow_osSetDynamicTextureURL = ${XEngine|osslParcelOG}ESTATE_MANAGER,ESTATE_OWNER @@ -171,7 +151,6 @@ Allow_osForceCreateLink = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceDropAttachment = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osForceDropAttachmentAt = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER - Allow_osGetAgentIP = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetLinkPrimitiveParams = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osGetPhysicsEngineType = true Allow_osGetPrimitiveParams = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER @@ -236,4 +215,51 @@ Allow_osKickAvatar = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER Allow_osRevokeScriptPermissions = false Allow_osTeleportAgent = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER + Allow_osTeleportObject = ${XEngine|osslParcelO}ESTATE_MANAGER,ESTATE_OWNER +; funtions ThreatLevel Severe with additional internal restrictions + Allow_osGetAgentIP = true ; always restricted to Administrators (true or false to disable) + +; available funtions out of Threat level control (for reference only) +; Allow_osClearInertia = true +; Allow_osCheckODE = true +; Allow_osCollisionSound = true +; Allow_osDrawEllipse = true +; Allow_osDrawFilledEllipse = true +; Allow_osDrawFilledPolygon = true +; Allow_osDrawFilledRectangle = true +; Allow_osDrawResetTransform = true +; Allow_osDrawRotationTransform = true +; Allow_osDrawScaleTransform = true +; Allow_osDrawTranslationTransform = true +; Allow_osDrawImage = true +; Allow_osDrawLine = true +; Allow_osDrawPolygon = true +; Allow_osDrawRectangle = true +; Allow_osDrawText = true +; Allow_osGetCurrentSunHour = true +; Allow_osGetPhysicsEngineName = true +; Allow_osGetInertiaData = true +; Allow_osGetInventoryDesc = true +; Allow_osGetLinkNumber = true +; Allow_osGetMapTexture = true +; Allow_osGetRegionSize = true +; Allow_osGetSunParam = true +; Allow_osGetTerrainHeight = true +; Allow_osGetDrawStringSize = true +; Allow_osIsNpc = true +; Allow_osIsUUID = true +; Allow_osList2Double = true +; Allow_osMax = true +; Allow_osMin = true +; Allow_osMovePen = true +; Allow_osSetInertia = true +; Allow_osSetInertiaAsBox = true +; Allow_osSetInertiaAsSphere = true +; Allow_osSetInertiaAsCylinder = true +; Allow_osSetFontName = true +; Allow_osSetFontSize = true +; Allow_osSetPenCap = true +; Allow_osSetPenColor = true +; Allow_osSetPenSize = true +; Allow_osVolumeDetect = true diff --git a/bin/lib/NET/Mono.Security.dll b/bin/lib/NET/Mono.Security.dll index 6accde7911..1371f5cb63 100644 Binary files a/bin/lib/NET/Mono.Security.dll and b/bin/lib/NET/Mono.Security.dll differ diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index 6d006bf593..5c3ccd0062 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index ec29f58f61..97dd73cb97 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib32/libode.dylib b/bin/lib32/libode.dylib old mode 100644 new mode 100755 index ce0d5d0be6..49e205e261 Binary files a/bin/lib32/libode.dylib and b/bin/lib32/libode.dylib differ diff --git a/bin/lib32/libode.so b/bin/lib32/libode.so index daf6a4d1b0..35cb027f51 100755 Binary files a/bin/lib32/libode.so and b/bin/lib32/libode.so differ diff --git a/bin/lib32/ode.dll b/bin/lib32/ode.dll index 62aa4df9c4..cb4d1a060a 100755 Binary files a/bin/lib32/ode.dll and b/bin/lib32/ode.dll differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index 82774a22f0..eea102020f 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index 8b092751d7..3987835b7c 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ diff --git a/bin/lib64/libode-x86_64.so b/bin/lib64/libode-x86_64.so index d8f3c20ec4..663ff5d664 100755 Binary files a/bin/lib64/libode-x86_64.so and b/bin/lib64/libode-x86_64.so differ diff --git a/bin/lib64/libode.dylib b/bin/lib64/libode.dylib old mode 100644 new mode 100755 index ce0d5d0be6..49e205e261 Binary files a/bin/lib64/libode.dylib and b/bin/lib64/libode.dylib differ diff --git a/bin/lib64/ode.dll b/bin/lib64/ode.dll index 543b900026..050ee4659e 100755 Binary files a/bin/lib64/ode.dll and b/bin/lib64/ode.dll differ diff --git a/bin/netcd.dll b/bin/netcd.dll new file mode 100644 index 0000000000..d1f7330d9e Binary files /dev/null and b/bin/netcd.dll differ diff --git a/bin/opensim-ode.sh b/bin/opensim-ode.sh deleted file mode 100755 index b901425fc1..0000000000 --- a/bin/opensim-ode.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/bin/sh -echo "Starting OpenSimulator with ODE. If you get an error saying limit: Operation not permitted. Then you will need to chmod 0600 /etc/limits" -ulimit -s 262144 -mono OpenSim.exe -physics=OpenDynamicsEngine diff --git a/bin/opensim.sh b/bin/opensim.sh new file mode 100755 index 0000000000..508d925665 --- /dev/null +++ b/bin/opensim.sh @@ -0,0 +1,5 @@ +#!/bin/sh +ulimit -s 1048576 +# next option may improve SGen gc (for opensim only) you may also need to increase nursery size on large regions +#export MONO_GC_PARAMS="minor=split,promotion-age=14" +mono --desktop OpenSim.exe diff --git a/prebuild.xml b/prebuild.xml index cb39e18e16..f31f749fd4 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1464,6 +1464,7 @@ + @@ -1790,7 +1791,6 @@ - @@ -3298,7 +3298,46 @@ - + + + + ../../../bin/ + + + + + ../../../bin/ + + + + ../../../bin/ + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/share/32BitLaunch/OpenSim.32BitLaunch.exe b/share/32BitLaunch/OpenSim.32BitLaunch.exe deleted file mode 100755 index 62c14af416..0000000000 Binary files a/share/32BitLaunch/OpenSim.32BitLaunch.exe and /dev/null differ diff --git a/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.csproj b/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.csproj new file mode 100644 index 0000000000..c9a03e129b --- /dev/null +++ b/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.csproj @@ -0,0 +1,94 @@ + + + + Debug + x86 + {968B4C73-280D-4FF5-9F73-DD3D10160C2E} + Exe + false + OpenSim32 + v4.0 + + + 512 + false + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + true + + + true + full + false + bin\Debug\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + ..\..\..\bin\ + TRACE + prompt + 4 + x86 + true + false + + + OpenSim32 + + + + ..\..\..\bin\log4net.dll + + + + ..\..\..\bin\OpenSim.exe + + + + + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 4.5 + true + + + + + + + \ No newline at end of file diff --git a/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.csproj.user b/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.csproj.user new file mode 100644 index 0000000000..2f100f7ba6 --- /dev/null +++ b/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.csproj.user @@ -0,0 +1,16 @@ + + + + publish\ + + + + + + en-US + false + + + C:\Avination\testsim\bin\ + + \ No newline at end of file diff --git a/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.sln b/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.sln new file mode 100644 index 0000000000..93522eabdc --- /dev/null +++ b/share/32BitLaunch/OpenSim.32BitLaunch/OpenSim32.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "OpenSim32", "OpenSim32.csproj", "{968B4C73-280D-4FF5-9F73-DD3D10160C2E}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {968B4C73-280D-4FF5-9F73-DD3D10160C2E}.Debug|x86.ActiveCfg = Release|x86 + {968B4C73-280D-4FF5-9F73-DD3D10160C2E}.Debug|x86.Build.0 = Release|x86 + {968B4C73-280D-4FF5-9F73-DD3D10160C2E}.Release|x86.ActiveCfg = Release|x86 + {968B4C73-280D-4FF5-9F73-DD3D10160C2E}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/share/32BitLaunch/OpenSim.32BitLaunch/Program.cs b/share/32BitLaunch/OpenSim.32BitLaunch/Program.cs index 52806b81bf..ca6c359d40 100644 --- a/share/32BitLaunch/OpenSim.32BitLaunch/Program.cs +++ b/share/32BitLaunch/OpenSim.32BitLaunch/Program.cs @@ -27,33 +27,13 @@ using System; -namespace OpenSim._32BitLaunch +namespace OpenSim32 { class Program { static void Main(string[] args) { - log4net.Config.XmlConfigurator.Configure(); - - System.Console.WriteLine("32-bit OpenSim executor"); - System.Console.WriteLine("-----------------------"); - System.Console.WriteLine(""); - System.Console.WriteLine("This application is compiled for 32-bit CPU and will run under WOW32 or similar."); - System.Console.WriteLine("All 64-bit incompatibilities should be gone."); - System.Console.WriteLine(""); - System.Threading.Thread.Sleep(300); - try - { - global::OpenSim.Application.Main(args); - } - catch (Exception ex) - { - System.Console.WriteLine("OpenSim threw an exception:"); - System.Console.WriteLine(ex.ToString()); - System.Console.WriteLine(""); - System.Console.WriteLine("Application will now terminate!"); - System.Console.WriteLine(""); - } + global::OpenSim.Application.Main(args); } } } diff --git a/share/32BitLaunch/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs b/share/32BitLaunch/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs index e81870f92f..bda1a79493 100644 --- a/share/32BitLaunch/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs +++ b/share/32BitLaunch/OpenSim.32BitLaunch/Properties/AssemblyInfo.cs @@ -32,11 +32,11 @@ using System.Runtime.InteropServices; // General information about an assembly is controlled through the following // set of attributes. Change these attribute values to modify the information // associated with an assembly. -[assembly: AssemblyTitle("OpenSim.32BitLaunch")] -[assembly: AssemblyDescription("")] +[assembly: AssemblyTitle("OpenSim32")] +[assembly: AssemblyDescription("OpenSim 32Bit Launcher")] [assembly: AssemblyConfiguration("")] [assembly: AssemblyCompany("http://opensimulator.org")] -[assembly: AssemblyProduct("OpenSim.32BitLaunch")] +[assembly: AssemblyProduct("OpenSim 32BitLauncher")] [assembly: AssemblyCopyright("Copyright (c) 2008")] [assembly: AssemblyTrademark("")] [assembly: AssemblyCulture("")] @@ -59,5 +59,5 @@ using System.Runtime.InteropServices; // You can specify all the values or you can default the Build and Revision Numbers // by using the '*' as shown below: // [assembly: AssemblyVersion("0.6.3.*")] -[assembly: AssemblyVersion("0.6.3.*")] +[assembly: AssemblyVersion("0.9.1.*")] [assembly: AssemblyFileVersion("1.0.0.0")] diff --git a/share/32BitLaunch/OpenSim.32BitLaunch/app.config b/share/32BitLaunch/OpenSim.32BitLaunch/app.config new file mode 100644 index 0000000000..92242406f1 --- /dev/null +++ b/share/32BitLaunch/OpenSim.32BitLaunch/app.config @@ -0,0 +1,75 @@ + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/share/32BitLaunch/README b/share/32BitLaunch/README deleted file mode 100644 index 443cde0ab9..0000000000 --- a/share/32BitLaunch/README +++ /dev/null @@ -1,5 +0,0 @@ -Many issues appear in the support channels because of a misunderstanding of the use of these utilities. And through discussion at OpenSimulator Office Hours it was determined that these tools probably serve no useful purpose anymore. - -Instead of removing them immediately, we move them here, for a time, in case there is a useful purpose that has escaped us during conversations. - -If a need to compile these arises, the OpenSim.32BitLaunch and Robust.32BitLaunch directories may be placed under the ./OpenSim/Tools sources subdirectory, run the prebuild script and compile. diff --git a/share/32BitLaunch/Robust.32BitLaunch.exe b/share/32BitLaunch/Robust.32BitLaunch.exe deleted file mode 100755 index affedb4bca..0000000000 Binary files a/share/32BitLaunch/Robust.32BitLaunch.exe and /dev/null differ diff --git a/share/32BitLaunch/Robust.32BitLaunch/Program.cs b/share/32BitLaunch/Robust.32BitLaunch/Program.cs index 490414c456..ec5943e4ca 100644 --- a/share/32BitLaunch/Robust.32BitLaunch/Program.cs +++ b/share/32BitLaunch/Robust.32BitLaunch/Program.cs @@ -26,35 +26,14 @@ */ using System; -using log4net; -namespace Robust._32BitLaunch +namespace Robust32 { class Program { static void Main(string[] args) { - log4net.Config.XmlConfigurator.Configure(); - - System.Console.WriteLine("32-bit OpenSim executor"); - System.Console.WriteLine("-----------------------"); - System.Console.WriteLine(""); - System.Console.WriteLine("This application is compiled for 32-bit CPU and will run under WOW32 or similar."); - System.Console.WriteLine("All 64-bit incompatibilities should be gone."); - System.Console.WriteLine(""); - System.Threading.Thread.Sleep(300); - try - { global::OpenSim.Server.OpenSimServer.Main(args); - } - catch (Exception ex) - { - System.Console.WriteLine("OpenSim threw an exception:"); - System.Console.WriteLine(ex.ToString()); - System.Console.WriteLine(""); - System.Console.WriteLine("Application will now terminate!"); - System.Console.WriteLine(""); - } } } } diff --git a/share/32BitLaunch/Robust.32BitLaunch/Robust32.csproj b/share/32BitLaunch/Robust.32BitLaunch/Robust32.csproj new file mode 100644 index 0000000000..a6dae90c3a --- /dev/null +++ b/share/32BitLaunch/Robust.32BitLaunch/Robust32.csproj @@ -0,0 +1,92 @@ + + + + Debug + x86 + {A159489E-6552-4734-8EFA-8E031F63C7F6} + Exe + false + Robust32 + v4.0 + + + 512 + publish\ + true + Disk + false + Foreground + 7 + Days + false + false + true + 0 + 1.0.0.%2a + false + false + true + + + true + full + false + ..\..\..\bin\ + DEBUG;TRACE + prompt + 4 + x86 + + + pdbonly + true + ..\..\..\bin\ + TRACE + prompt + 4 + x86 + true + Off + + + Robust32 + + + Robust32.Program + + + + + False + ..\..\..\bin\Robust.exe + + + + + + + + + + + + False + Microsoft .NET Framework 4 %28x86 and x64%29 + true + + + False + .NET Framework 3.5 SP1 + false + + + False + Windows Installer 4.5 + true + + + + + + + \ No newline at end of file diff --git a/share/32BitLaunch/Robust.32BitLaunch/Robust32.csproj.user b/share/32BitLaunch/Robust.32BitLaunch/Robust32.csproj.user new file mode 100644 index 0000000000..8221333555 --- /dev/null +++ b/share/32BitLaunch/Robust.32BitLaunch/Robust32.csproj.user @@ -0,0 +1,13 @@ + + + + publish\ + + + + + + en-US + false + + \ No newline at end of file diff --git a/share/32BitLaunch/Robust.32BitLaunch/Robust32.sln b/share/32BitLaunch/Robust.32BitLaunch/Robust32.sln new file mode 100644 index 0000000000..368b3ca50b --- /dev/null +++ b/share/32BitLaunch/Robust.32BitLaunch/Robust32.sln @@ -0,0 +1,22 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio 14 +VisualStudioVersion = 14.0.25420.1 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Robust32", "Robust32.csproj", "{A159489E-6552-4734-8EFA-8E031F63C7F6}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|x86 = Debug|x86 + Release|x86 = Release|x86 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {A159489E-6552-4734-8EFA-8E031F63C7F6}.Debug|x86.ActiveCfg = Debug|x86 + {A159489E-6552-4734-8EFA-8E031F63C7F6}.Debug|x86.Build.0 = Debug|x86 + {A159489E-6552-4734-8EFA-8E031F63C7F6}.Release|x86.ActiveCfg = Release|x86 + {A159489E-6552-4734-8EFA-8E031F63C7F6}.Release|x86.Build.0 = Release|x86 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/share/32BitLaunch/Robust.32BitLaunch/app.config b/share/32BitLaunch/Robust.32BitLaunch/app.config new file mode 100644 index 0000000000..ca3ee0e0cf --- /dev/null +++ b/share/32BitLaunch/Robust.32BitLaunch/app.config @@ -0,0 +1,72 @@ + + + +
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file