From 1842388bb4dcf5ecd57732ffa877b6ca1a3dec7b Mon Sep 17 00:00:00 2001 From: BlueWall Date: Fri, 6 Dec 2013 02:52:13 -0500 Subject: [PATCH 01/24] Add support for user preferences (im via email) --- OpenSim/Data/IProfilesData.cs | 2 + OpenSim/Data/MySQL/MySQLUserProfilesData.cs | 39 ++++----- .../MySQL/Resources/UserProfiles.migrations | 10 +++ OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs | 29 ++++--- .../PGSQL/Resources/UserProfiles.migrations | 9 ++ .../SQLite/Resources/UserProfiles.migrations | 12 +++ OpenSim/Data/SQLite/SQLiteUserProfilesData.cs | 83 +++++++++++++++++++ OpenSim/Framework/UserProfiles.cs | 8 ++ .../Avatar/UserProfiles/UserProfileModule.cs | 67 +++++++++++++++ .../LocalUserProfilesServiceConnector.cs | 2 + .../Profiles/UserProfilesConnector.cs | 2 + .../Handlers/Profiles/UserProfilesHandlers.cs | 53 ++++++++++++ .../Interfaces/IUserProfilesService.cs | 5 ++ .../UserProfilesService.cs | 12 +++ 14 files changed, 297 insertions(+), 36 deletions(-) diff --git a/OpenSim/Data/IProfilesData.cs b/OpenSim/Data/IProfilesData.cs index 0de7f68af9..7fb075d3d5 100644 --- a/OpenSim/Data/IProfilesData.cs +++ b/OpenSim/Data/IProfilesData.cs @@ -48,6 +48,8 @@ namespace OpenSim.Data bool UpdateAvatarProperties(ref UserProfileProperties props, ref string result); bool UpdateAvatarInterests(UserProfileProperties up, ref string result); bool GetClassifiedInfo(ref UserClassifiedAdd ad, ref string result); + bool UpdateUserPreferences(ref UserPreferences pref, ref string result); + bool GetUserPreferences(ref UserPreferences pref, ref string result); bool GetUserAppData(ref UserAppData props, ref string result); bool SetUserAppData(UserAppData props, ref string result); OSDArray GetUserImageAssets(UUID avatarId); diff --git a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs index dc88f9460a..63492c2f10 100644 --- a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs +++ b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs @@ -895,7 +895,7 @@ namespace OpenSim.Data.MySQL } #region User Preferences - public OSDArray GetUserPreferences(UUID avatarId) + public bool GetUserPreferences(ref UserPreferences pref, ref string result) { string query = string.Empty; @@ -912,19 +912,16 @@ namespace OpenSim.Data.MySQL dbcon.Open(); using (MySqlCommand cmd = new MySqlCommand(query, dbcon)) { - cmd.Parameters.AddWithValue("?Id", avatarId.ToString()); + cmd.Parameters.AddWithValue("?Id", pref.UserId.ToString()); using (MySqlDataReader reader = cmd.ExecuteReader()) { if(reader.HasRows) { reader.Read(); - OSDMap record = new OSDMap(); - - record.Add("imviaemail",OSD.FromString((string)reader["imviaemail"])); - record.Add("visible",OSD.FromString((string)reader["visible"])); - record.Add("email",OSD.FromString((string)reader["email"])); - data.Add(record); + bool.TryParse((string)reader["imviaemail"], out pref.IMViaEmail); + bool.TryParse((string)reader["visible"], out pref.Visible); + pref.EMail = (string)reader["email"]; } else { @@ -947,17 +944,19 @@ namespace OpenSim.Data.MySQL { m_log.DebugFormat("[PROFILES_DATA]" + ": Get preferences exception {0}", e.Message); + result = e.Message; + return false; } - return data; + return true; } - public bool UpdateUserPreferences(bool emailIm, bool visible, UUID avatarId ) + public bool UpdateUserPreferences(ref UserPreferences pref, ref string result) { string query = string.Empty; - - query += "UPDATE userpsettings SET "; + + query += "UPDATE usersettings SET "; query += "imviaemail=?ImViaEmail, "; - query += "visible=?Visible,"; + query += "visible=?Visible "; query += "WHERE useruuid=?uuid"; try @@ -967,14 +966,11 @@ namespace OpenSim.Data.MySQL dbcon.Open(); using (MySqlCommand cmd = new MySqlCommand(query, dbcon)) { - cmd.Parameters.AddWithValue("?ImViaEmail", emailIm.ToString().ToLower ()); - cmd.Parameters.AddWithValue("?WantText", visible.ToString().ToLower ()); - cmd.Parameters.AddWithValue("?uuid", avatarId.ToString()); - - lock(Lock) - { - cmd.ExecuteNonQuery(); - } + cmd.Parameters.AddWithValue("?ImViaEmail", pref.IMViaEmail); + cmd.Parameters.AddWithValue("?Visible", pref.Visible); + cmd.Parameters.AddWithValue("?uuid", pref.UserId.ToString()); + + cmd.ExecuteNonQuery(); } } } @@ -982,6 +978,7 @@ namespace OpenSim.Data.MySQL { m_log.DebugFormat("[PROFILES_DATA]" + ": AgentInterestsUpdate exception {0}", e.Message); + result = e.Message; return false; } return true; diff --git a/OpenSim/Data/MySQL/Resources/UserProfiles.migrations b/OpenSim/Data/MySQL/Resources/UserProfiles.migrations index c29f1abf3e..bd325da1f0 100644 --- a/OpenSim/Data/MySQL/Resources/UserProfiles.migrations +++ b/OpenSim/Data/MySQL/Resources/UserProfiles.migrations @@ -81,3 +81,13 @@ CREATE TABLE IF NOT EXISTS `userdata` ( commit; +:VERSION 3 # ------------------------------- +begin; +CREATE TABLE IF NOT EXISTS `usersettings` ( + `useruuid` varchar(36) NOT NULL, + `imviaemail` enum('true','false') NOT NULL, + `visible` enum('true','false') NOT NULL, + `email` varchar(254) NOT NULL, + PRIMARY KEY (`useruuid`) +) ENGINE=MyISAM DEFAULT CHARSET=latin1; +commit; \ No newline at end of file diff --git a/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs b/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs index f4e41b47dd..46f57d8066 100644 --- a/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs +++ b/OpenSim/Data/PGSQL/PGSQLUserProfilesData.cs @@ -874,7 +874,7 @@ namespace OpenSim.Data.PGSQL } #region User Preferences - public OSDArray GetUserPreferences(UUID avatarId) + public bool GetUserPreferences(ref UserPreferences pref, ref string result) { string query = string.Empty; @@ -891,19 +891,16 @@ namespace OpenSim.Data.PGSQL dbcon.Open(); using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon)) { - cmd.Parameters.AddWithValue("Id", avatarId.ToString()); + cmd.Parameters.AddWithValue("Id", pref.UserId.ToString()); using (NpgsqlDataReader reader = cmd.ExecuteReader()) { if(reader.HasRows) { reader.Read(); - OSDMap record = new OSDMap(); - - record.Add("imviaemail",OSD.FromString((string)reader["imviaemail"])); - record.Add("visible",OSD.FromString((string)reader["visible"])); - record.Add("email",OSD.FromString((string)reader["email"])); - data.Add(record); + bool.TryParse((string)reader["imviaemail"], out pref.IMViaEmail); + bool.TryParse((string)reader["visible"], out pref.Visible); + pref.EMail = (string)reader["email"]; } else { @@ -926,15 +923,16 @@ namespace OpenSim.Data.PGSQL { m_log.DebugFormat("[PROFILES_DATA]" + ": Get preferences exception {0}", e.Message); + result = e.Message; } - return data; + return true; } - - public bool UpdateUserPreferences(bool emailIm, bool visible, UUID avatarId ) + + public bool UpdateUserPreferences(ref UserPreferences pref, ref string result) { string query = string.Empty; - query += "UPDATE userpsettings SET "; + query += "UPDATE usersettings SET "; query += "imviaemail=:ImViaEmail, "; query += "visible=:Visible,"; query += "WHERE useruuid=:uuid"; @@ -946,9 +944,9 @@ namespace OpenSim.Data.PGSQL dbcon.Open(); using (NpgsqlCommand cmd = new NpgsqlCommand(query, dbcon)) { - cmd.Parameters.AddWithValue("ImViaEmail", emailIm.ToString().ToLower ()); - cmd.Parameters.AddWithValue("WantText", visible.ToString().ToLower ()); - cmd.Parameters.AddWithValue("uuid", avatarId.ToString()); + cmd.Parameters.AddWithValue("ImViaEmail", pref.IMViaEmail.ToString().ToLower ()); + cmd.Parameters.AddWithValue("Visible", pref.Visible.ToString().ToLower ()); + cmd.Parameters.AddWithValue("uuid", pref.UserId.ToString()); lock(Lock) { @@ -961,6 +959,7 @@ namespace OpenSim.Data.PGSQL { m_log.DebugFormat("[PROFILES_DATA]" + ": AgentInterestsUpdate exception {0}", e.Message); + result = e.Message; return false; } return true; diff --git a/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations index f23c87087c..4fcaa8e0bf 100644 --- a/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations +++ b/OpenSim/Data/PGSQL/Resources/UserProfiles.migrations @@ -81,3 +81,12 @@ CREATE TABLE userdata ( commit; +:VERSION 3 # ------------------------------- +begin; +CREATE TABLE usersettings ( + "useruuid" char(36) NOT NULL, + "imviaemail" bytea NOT NULL, + "visible" bytea NOT NULL, + PRIMARY KEY ("useruuid") +); +commit; \ No newline at end of file diff --git a/OpenSim/Data/SQLite/Resources/UserProfiles.migrations b/OpenSim/Data/SQLite/Resources/UserProfiles.migrations index 16581f6e49..86434e8170 100644 --- a/OpenSim/Data/SQLite/Resources/UserProfiles.migrations +++ b/OpenSim/Data/SQLite/Resources/UserProfiles.migrations @@ -88,3 +88,15 @@ CREATE TABLE IF NOT EXISTS userdata ( commit; + +:VERSION 3 # ------------------------------- + +begin; +CREATE TABLE IF NOT EXISTS usersettings ( + useruuid char(36) NOT NULL, + imviaemail binary(1) NOT NULL, + visible binary(1) NOT NULL, + email varchar(254) NOT NULL, + PRIMARY KEY (useruuid) +) +commit; \ No newline at end of file diff --git a/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs index 8c1bcd48d1..916a226d6b 100644 --- a/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs @@ -747,6 +747,89 @@ namespace OpenSim.Data.SQLite } return true; } + + public bool UpdateUserPreferences(ref UserPreferences pref, ref string result) + { + string query = string.Empty; + + query += "UPDATE usersettings SET "; + query += "imviaemail=:ImViaEmail, "; + query += "visible=:Visible "; + query += "WHERE useruuid=:uuid"; + + try + { + using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand()) + { + cmd.CommandText = query; + cmd.Parameters.AddWithValue(":ImViaEmail", pref.IMViaEmail); + cmd.Parameters.AddWithValue(":Visible", pref.Visible); + cmd.Parameters.AddWithValue(":uuid", pref.UserId.ToString()); + + cmd.ExecuteNonQuery(); + } + } + catch (Exception e) + { + m_log.DebugFormat("[PROFILES_DATA]" + + ": AgentInterestsUpdate exception {0}", e.Message); + result = e.Message; + return false; + } + return true; + } + + public bool GetUserPreferences(ref UserPreferences pref, ref string result) + { + IDataReader reader = null; + string query = string.Empty; + + query += "SELECT imviaemail,visible,email FROM "; + query += "usersettings WHERE "; + query += "useruuid = :Id"; + + OSDArray data = new OSDArray(); + + try + { + using (SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand()) + { + cmd.CommandText = query; + cmd.Parameters.AddWithValue("?Id", pref.UserId.ToString()); + + using (reader = cmd.ExecuteReader(CommandBehavior.SingleRow)) + { + if(reader.Read()) + { + bool.TryParse((string)reader["imviaemail"], out pref.IMViaEmail); + bool.TryParse((string)reader["visible"], out pref.Visible); + pref.EMail = (string)reader["email"]; + } + else + { + query = "INSERT INTO usersettings VALUES "; + query += "(:Id,'false','false', '')"; + + using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand()) + { + put.Parameters.AddWithValue(":Id", pref.UserId.ToString()); + put.ExecuteNonQuery(); + + } + } + } + } + } + catch (Exception e) + { + m_log.DebugFormat("[PROFILES_DATA]" + + ": Get preferences exception {0}", e.Message); + result = e.Message; + return false; + } + return true; + } + public bool GetUserAppData(ref UserAppData props, ref string result) { IDataReader reader = null; diff --git a/OpenSim/Framework/UserProfiles.cs b/OpenSim/Framework/UserProfiles.cs index 61335917e1..492f6b9bd1 100644 --- a/OpenSim/Framework/UserProfiles.cs +++ b/OpenSim/Framework/UserProfiles.cs @@ -90,6 +90,14 @@ namespace OpenSim.Framework public UUID TargetId; public string Notes; } + + public class UserPreferences + { + public UUID UserId; + public bool IMViaEmail = false; + public bool Visible = false; + public string EMail = string.Empty; + } public class UserAccountProperties { diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs index 56ff2bddb1..b21082fd74 100644 --- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs @@ -270,6 +270,10 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles // Notes client.AddGenericPacketHandler("avatarnotesrequest", NotesRequest); client.OnAvatarNotesUpdate += NotesUpdate; + + // Preferences + client.OnUserInfoRequest += UserPreferencesRequest; + client.OnUpdateUserInfo += UpdateUserPreferences; } #endregion Region Event Handlers @@ -799,6 +803,69 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles } #endregion Notes + #region User Preferences + /// + /// Updates the user preferences. + /// + /// + /// Im via email. + /// + /// + /// Visible. + /// + /// + /// Remote client. + /// + public void UpdateUserPreferences(bool imViaEmail, bool visible, IClientAPI remoteClient) + { + UserPreferences pref = new UserPreferences(); + + pref.UserId = remoteClient.AgentId; + pref.IMViaEmail = imViaEmail; + pref.Visible = visible; + + string serverURI = string.Empty; + bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); + + object Pref = pref; + if(!JsonRpcRequest(ref Pref, "user_preferences_update", serverURI, UUID.Random().ToString())) + { + m_log.InfoFormat("[PROFILES]: UserPreferences update error"); + remoteClient.SendAgentAlertMessage("Error updating preferences", false); + return; + } + } + + /// + /// Users the preferences request. + /// + /// + /// Remote client. + /// + public void UserPreferencesRequest(IClientAPI remoteClient) + { + UserPreferences pref = new UserPreferences(); + + pref.UserId = remoteClient.AgentId; + + string serverURI = string.Empty; + bool foreign = GetUserProfileServerURI(remoteClient.AgentId, out serverURI); + + + object Pref = (object)pref; + if(!JsonRpcRequest(ref Pref, "user_preferences_request", serverURI, UUID.Random().ToString())) + { + m_log.InfoFormat("[PROFILES]: UserPreferences request error"); + remoteClient.SendAgentAlertMessage("Error requesting preferences", false); + return; + } + pref = (UserPreferences) Pref; + + remoteClient.SendUserInfoReply(pref.IMViaEmail, pref.Visible, pref.EMail); + + } + #endregion User Preferences + #region Avatar Properties /// /// Update the avatars interests . diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs index 323535ab07..4701ee653f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/UserProfiles/LocalUserProfilesServiceConnector.cs @@ -153,6 +153,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Profile Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest); Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate); Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate); + Server.AddJsonRPCHandler("user_preferences_update", handler.UserPreferenecesUpdate); + Server.AddJsonRPCHandler("user_preferences_request", handler.UserPreferencesRequest); Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest); Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData); Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData); diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs index 28dbbc2e13..640388200d 100644 --- a/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs +++ b/OpenSim/Server/Handlers/Profiles/UserProfilesConnector.cs @@ -104,6 +104,8 @@ namespace OpenSim.Server.Handlers.Profiles Server.AddJsonRPCHandler("avatar_properties_request", handler.AvatarPropertiesRequest); Server.AddJsonRPCHandler("avatar_properties_update", handler.AvatarPropertiesUpdate); Server.AddJsonRPCHandler("avatar_interests_update", handler.AvatarInterestsUpdate); + Server.AddJsonRPCHandler("user_preferences_update", handler.UserPreferenecesUpdate); + Server.AddJsonRPCHandler("user_preferences_request", handler.UserPreferencesRequest); Server.AddJsonRPCHandler("image_assets_request", handler.AvatarImageAssetsRequest); Server.AddJsonRPCHandler("user_data_request", handler.RequestUserAppData); Server.AddJsonRPCHandler("user_data_update", handler.UpdateUserAppData); diff --git a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs index f5f0794653..d30cc228b0 100644 --- a/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs +++ b/OpenSim/Server/Handlers/Profiles/UserProfilesHandlers.cs @@ -381,6 +381,59 @@ namespace OpenSim.Server.Handlers } #endregion Interests + #region User Preferences + public bool UserPreferencesRequest(OSDMap json, ref JsonRpcResponse response) + { + if(!json.ContainsKey("params")) + { + response.Error.Code = ErrorCode.ParseError; + m_log.DebugFormat ("User Preferences Request"); + return false; + } + + string result = string.Empty; + UserPreferences prefs = new UserPreferences(); + object Prefs = (object)prefs; + OSD.DeserializeMembers(ref Prefs, (OSDMap)json["params"]); + if(Service.UserPreferencesRequest(ref prefs, ref result)) + { + response.Result = OSD.SerializeMembers(prefs); + return true; + } + + response.Error.Code = ErrorCode.InternalError; + response.Error.Message = string.Format("{0}", result); + m_log.InfoFormat("[PROFILES]: User preferences request error - {0}", response.Error.Message); + return false; + } + + public bool UserPreferenecesUpdate(OSDMap json, ref JsonRpcResponse response) + { + if(!json.ContainsKey("params")) + { + response.Error.Code = ErrorCode.ParseError; + response.Error.Message = "no parameters supplied"; + m_log.DebugFormat ("User Preferences Update Request"); + return false; + } + + string result = string.Empty; + UserPreferences prefs = new UserPreferences(); + object Prefs = (object)prefs; + OSD.DeserializeMembers(ref Prefs, (OSDMap)json["params"]); + if(Service.UserPreferencesUpdate(ref prefs, ref result)) + { + response.Result = OSD.SerializeMembers(prefs); + return true; + } + + response.Error.Code = ErrorCode.InternalError; + response.Error.Message = string.Format("{0}", result); + m_log.InfoFormat("[PROFILES]: User preferences update error - {0}", response.Error.Message); + return false; + } + #endregion User Preferences + #region Utility public bool AvatarImageAssetsRequest(OSDMap json, ref JsonRpcResponse response) { diff --git a/OpenSim/Services/Interfaces/IUserProfilesService.cs b/OpenSim/Services/Interfaces/IUserProfilesService.cs index 319d3075dd..121baa8b1f 100644 --- a/OpenSim/Services/Interfaces/IUserProfilesService.cs +++ b/OpenSim/Services/Interfaces/IUserProfilesService.cs @@ -57,6 +57,11 @@ namespace OpenSim.Services.Interfaces bool AvatarPropertiesRequest(ref UserProfileProperties prop, ref string result); bool AvatarPropertiesUpdate(ref UserProfileProperties prop, ref string result); #endregion Profile Properties + + #region User Preferences + bool UserPreferencesRequest(ref UserPreferences pref, ref string result); + bool UserPreferencesUpdate(ref UserPreferences pref, ref string result); + #endregion User Preferences #region Interests bool AvatarInterestsUpdate(UserProfileProperties prop, ref string result); diff --git a/OpenSim/Services/UserProfilesService/UserProfilesService.cs b/OpenSim/Services/UserProfilesService/UserProfilesService.cs index d00f34d650..69c7b91957 100644 --- a/OpenSim/Services/UserProfilesService/UserProfilesService.cs +++ b/OpenSim/Services/UserProfilesService/UserProfilesService.cs @@ -163,6 +163,18 @@ namespace OpenSim.Services.ProfilesService } #endregion Interests + #region User Preferences + public bool UserPreferencesUpdate(ref UserPreferences pref, ref string result) + { + return ProfilesData.UpdateUserPreferences(ref pref, ref result); + } + + public bool UserPreferencesRequest(ref UserPreferences pref, ref string result) + { + return ProfilesData.GetUserPreferences(ref pref, ref result); + } + #endregion User Preferences + #region Utility public OSD AvatarImageAssetsRequest(UUID avatarId) { From 1496de7ce99079d3d7bf046db088c3d6e2a97bcb Mon Sep 17 00:00:00 2001 From: dahlia Date: Fri, 6 Dec 2013 15:58:19 -0800 Subject: [PATCH 02/24] use System.IO.Compression.DeflateStream for mesh decompression in an attempt to reduce mesh asset decoding failures --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 14 +++++--------- prebuild.xml | 1 - 2 files changed, 5 insertions(+), 10 deletions(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index 1f08b030c6..e313a302ae 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -40,7 +40,6 @@ using log4net; using Nini.Config; using System.Reflection; using System.IO; -using ComponentAce.Compression.Libs.zlib; namespace OpenSim.Region.Physics.Meshing { @@ -549,7 +548,6 @@ namespace OpenSim.Region.Physics.Meshing return true; } - /// /// decompresses a gzipped OSD object /// @@ -564,15 +562,13 @@ namespace OpenSim.Region.Physics.Meshing { using (MemoryStream outMs = new MemoryStream()) { - using (ZOutputStream zOut = new ZOutputStream(outMs)) + using (DeflateStream decompressionStream = new DeflateStream(inMs, CompressionMode.Decompress)) { byte[] readBuffer = new byte[2048]; - int readLen = 0; - while ((readLen = inMs.Read(readBuffer, 0, readBuffer.Length)) > 0) - { - zOut.Write(readBuffer, 0, readLen); - } - zOut.Flush(); + inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header + + decompressionStream.CopyTo(outMs); + outMs.Seek(0, SeekOrigin.Begin); byte[] decompressedBuf = outMs.GetBuffer(); diff --git a/prebuild.xml b/prebuild.xml index de3b89bb46..f6e0f4b4e0 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -585,7 +585,6 @@ - From 4058e5f709990cc502d5479fb4065bf232ee3a8d Mon Sep 17 00:00:00 2001 From: Diva Canto Date: Fri, 6 Dec 2013 16:01:29 -0800 Subject: [PATCH 03/24] Fixed misleading comment --- OpenSim/Services/Interfaces/IHypergridServices.cs | 3 --- 1 file changed, 3 deletions(-) diff --git a/OpenSim/Services/Interfaces/IHypergridServices.cs b/OpenSim/Services/Interfaces/IHypergridServices.cs index f9e7f083b4..05e175a243 100644 --- a/OpenSim/Services/Interfaces/IHypergridServices.cs +++ b/OpenSim/Services/Interfaces/IHypergridServices.cs @@ -43,9 +43,6 @@ namespace OpenSim.Services.Interfaces } - /// - /// HG1.5 only - /// public interface IUserAgentService { bool LoginAgentToGrid(AgentCircuitData agent, GridRegion gatekeeper, GridRegion finalDestination, bool fromLogin, out string reason); From c0380d1bfe596afe33659cc69ae99a09018f9908 Mon Sep 17 00:00:00 2001 From: dahlia Date: Fri, 6 Dec 2013 16:24:44 -0800 Subject: [PATCH 04/24] apparently mono DeflateStream has no CopyTo method =( --- OpenSim/Region/Physics/Meshing/Meshmerizer.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs index e313a302ae..d96de4ac8e 100644 --- a/OpenSim/Region/Physics/Meshing/Meshmerizer.cs +++ b/OpenSim/Region/Physics/Meshing/Meshmerizer.cs @@ -566,8 +566,12 @@ namespace OpenSim.Region.Physics.Meshing { byte[] readBuffer = new byte[2048]; inMs.Read(readBuffer, 0, 2); // skip first 2 bytes in header + int readLen = 0; - decompressionStream.CopyTo(outMs); + while ((readLen = decompressionStream.Read(readBuffer, 0, readBuffer.Length)) > 0) + outMs.Write(readBuffer, 0, readLen); + + outMs.Flush(); outMs.Seek(0, SeekOrigin.Begin); From 08750501617ca332ab196b2f25030e3c635c9dd6 Mon Sep 17 00:00:00 2001 From: dahlia Date: Tue, 10 Dec 2013 13:57:18 -0800 Subject: [PATCH 05/24] Add console utility commands "scale scene" and "translate scene". Note that repeated use of these commands will induce floating point accumulation errors. Please back up your region before using. --- OpenSim/Region/Application/OpenSim.cs | 90 ++++++++++++++++++++++++++- 1 file changed, 88 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index c2d9942ba6..0a6ae98e39 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -297,10 +297,20 @@ namespace OpenSim HandleEditScale); m_console.Commands.AddCommand("Objects", false, "rotate scene", - "rotate scene ", - "Rotates all scene objects around x:128, y:128", + "rotate scene [centerX, centerY]", + "Rotates all scene objects around centerX, centerY (defailt 128, 128) (please back up your region before using)", HandleRotateScene); + m_console.Commands.AddCommand("Objects", false, "scale scene", + "scale scene ", + "Scales the scene objects (please back up your region before using)", + HandleScaleScene); + + m_console.Commands.AddCommand("Objects", false, "translate scene", + "translate scene xOffset yOffset zOffset", + "translates the scene objects (please back up your region before using)", + HandleTranslateScene); + m_console.Commands.AddCommand("Users", false, "kick user", "kick user [--force] [message]", "Kick a user off the simulator", @@ -549,6 +559,82 @@ namespace OpenSim }); } + private void HandleScaleScene(string module, string[] args) + { + string usage = "Usage: scale scene "; + + if (args.Length < 3) + { + MainConsole.Instance.Output(usage); + return; + } + + float factor = (float)(Convert.ToSingle(args[2])); + + float minZ = float.MaxValue; + + SceneManager.ForEachSelectedScene(delegate(Scene scene) + { + scene.ForEachSOG(delegate(SceneObjectGroup sog) + { + if (sog.AttachmentPoint == 0) + { + if (sog.RootPart.AbsolutePosition.Z < minZ) + minZ = sog.RootPart.AbsolutePosition.Z; + } + }); + }); + + SceneManager.ForEachSelectedScene(delegate(Scene scene) + { + scene.ForEachSOG(delegate(SceneObjectGroup sog) + { + if (sog.AttachmentPoint == 0) + { + Vector3 tmpRootPos = sog.RootPart.AbsolutePosition; + tmpRootPos.Z -= minZ; + tmpRootPos *= factor; + tmpRootPos.Z += minZ; + + foreach (SceneObjectPart sop in sog.Parts) + { + if (sop.ParentID != 0) + sop.OffsetPosition *= factor; + sop.Scale *= factor; + } + + sog.UpdateGroupPosition(tmpRootPos); + } + }); + }); + } + + private void HandleTranslateScene(string module, string[] args) + { + string usage = "Usage: translate scene "; + + if (args.Length < 5) + { + MainConsole.Instance.Output(usage); + return; + } + + float xOFfset = (float)Convert.ToSingle(args[2]); + float yOffset = (float)Convert.ToSingle(args[3]); + float zOffset = (float)Convert.ToSingle(args[4]); + + Vector3 offset = new Vector3(xOFfset, yOffset, zOffset); + + SceneManager.ForEachSelectedScene(delegate(Scene scene) + { + scene.ForEachSOG(delegate(SceneObjectGroup sog) + { + if (sog.AttachmentPoint == 0) + sog.UpdateGroupPosition(sog.AbsolutePosition + offset); + }); + }); + } + /// /// Creates a new region based on the parameters specified. This will ask the user questions on the console /// From 97934e00e667b6f432340a54671221a970a048d7 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 11 Dec 2013 00:12:36 +0000 Subject: [PATCH 06/24] This is the Avination Entity Transfer Module. Surprisingly, it still compiles but I don't know if it runs. Will probably crash and burn as the supporting code isn't there yet. --- .../EntityTransfer/EntityTransferModule.cs | 445 +++++++++--------- .../Interfaces/IEntityTransferModule.cs | 32 +- 2 files changed, 226 insertions(+), 251 deletions(-) diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index aa8a4db364..ef5239a516 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -409,7 +409,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// /// /// - /// private void TeleportAgentWithinRegion(ScenePresence sp, Vector3 position, Vector3 lookAt, uint teleportFlags) { m_log.DebugFormat( @@ -444,11 +444,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer position.Z = newPosZ; } + if (sp.Flying) + teleportFlags |= (uint)TeleportFlags.IsFlying; + m_entityTransferStateMachine.UpdateInTransit(sp.UUID, AgentTransferState.Transferring); sp.ControllingClient.SendTeleportStart(teleportFlags); sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); + sp.TeleportFlags = (Constants.TeleportFlags)teleportFlags; sp.Velocity = Vector3.Zero; sp.Teleport(position); @@ -652,8 +656,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // This may be a costly operation. The reg.ExternalEndPoint field is not a passive field, // it's actually doing a lot of work. IPEndPoint endPoint = finalDestination.ExternalEndPoint; - - if (endPoint.Address == null) + if (endPoint == null || endPoint.Address == null) { sp.ControllingClient.SendTeleportFailed("Remote Region appears to be down"); @@ -692,6 +695,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer // both regions if (sp.ParentID != (uint)0) sp.StandUp(); + else if (sp.Flying) + teleportFlags |= (uint)TeleportFlags.IsFlying; if (DisableInterRegionTeleportCancellation) teleportFlags |= (uint)TeleportFlags.DisableCancel; @@ -1319,11 +1324,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Teleport Home - public virtual void TriggerTeleportHome(UUID id, IClientAPI client) - { - TeleportHome(id, client); - } - + public virtual void TriggerTeleportHome(UUID id, IClientAPI client) + { + TeleportHome(id, client); + } + public virtual bool TeleportHome(UUID id, IClientAPI client) { m_log.DebugFormat( @@ -1334,6 +1339,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (uinfo != null) { + if (uinfo.HomeRegionID == UUID.Zero) + { + // can't find the Home region: Tell viewer and abort + client.SendTeleportFailed("You don't have a home position set."); + return false; + } GridRegion regionInfo = Scene.GridService.GetRegionByUUID(UUID.Zero, uinfo.HomeRegionID); if (regionInfo == null) { @@ -1353,9 +1364,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else { - m_log.ErrorFormat( - "[ENTITY TRANSFER MODULE]: No grid user information found for {0} {1}. Cannot send home.", - client.Name, client.AgentId); + // can't find the Home region: Tell viewer and abort + client.SendTeleportFailed("Your home region could not be found."); } return false; } @@ -1365,15 +1375,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer #region Agent Crossings - public bool Cross(ScenePresence agent, bool isFlying) + public GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos) { - Scene scene = agent.Scene; - Vector3 pos = agent.AbsolutePosition; + version = String.Empty; + newpos = new Vector3(pos.X, pos.Y, pos.Z); // m_log.DebugFormat( // "[ENTITY TRANSFER MODULE]: Crossing agent {0} at pos {1} in {2}", agent.Name, pos, scene.Name); - Vector3 newpos = new Vector3(pos.X, pos.Y, pos.Z); uint neighbourx = scene.RegionInfo.RegionLocX; uint neighboury = scene.RegionInfo.RegionLocY; const float boundaryDistance = 1.7f; @@ -1394,52 +1403,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) { - Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S); - if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0) - { - neighboury--; - newpos.Y = Constants.RegionSize - enterDistance; - } - else - { - agent.IsInTransit = true; - - neighboury = b.TriggerRegionY; - neighbourx = b.TriggerRegionX; - - Vector3 newposition = pos; - newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; - newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; - agent.ControllingClient.SendAgentAlertMessage( - String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); - InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return true; - } - } - - Border ba = scene.GetCrossedBorder(pos + westCross, Cardinals.W); - if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0) - { - neighbourx--; - newpos.X = Constants.RegionSize - enterDistance; - } - else - { - agent.IsInTransit = true; - - neighboury = ba.TriggerRegionY; - neighbourx = ba.TriggerRegionX; - - Vector3 newposition = pos; - newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; - newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; - agent.ControllingClient.SendAgentAlertMessage( - String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); - InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - - return true; + neighboury--; + newpos.Y = Constants.RegionSize - enterDistance; } + neighbourx--; + newpos.X = Constants.RegionSize - enterDistance; } else if (scene.TestBorderCross(pos + eastCross, Cardinals.E)) { @@ -1449,26 +1418,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (scene.TestBorderCross(pos + southCross, Cardinals.S)) { - Border ba = scene.GetCrossedBorder(pos + southCross, Cardinals.S); - if (ba.TriggerRegionX == 0 && ba.TriggerRegionY == 0) - { - neighboury--; - newpos.Y = Constants.RegionSize - enterDistance; - } - else - { - agent.IsInTransit = true; - - neighboury = ba.TriggerRegionY; - neighbourx = ba.TriggerRegionX; - Vector3 newposition = pos; - newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; - newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; - agent.ControllingClient.SendAgentAlertMessage( - String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); - InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return true; - } + neighboury--; + newpos.Y = Constants.RegionSize - enterDistance; } else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) { @@ -1480,25 +1431,8 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer else if (scene.TestBorderCross(pos + southCross, Cardinals.S)) { Border b = scene.GetCrossedBorder(pos + southCross, Cardinals.S); - if (b.TriggerRegionX == 0 && b.TriggerRegionY == 0) - { - neighboury--; - newpos.Y = Constants.RegionSize - enterDistance; - } - else - { - agent.IsInTransit = true; - - neighboury = b.TriggerRegionY; - neighbourx = b.TriggerRegionX; - Vector3 newposition = pos; - newposition.X += (scene.RegionInfo.RegionLocX - neighbourx) * Constants.RegionSize; - newposition.Y += (scene.RegionInfo.RegionLocY - neighboury) * Constants.RegionSize; - agent.ControllingClient.SendAgentAlertMessage( - String.Format("Moving you to region {0},{1}", neighbourx, neighboury), false); - InformClientToInitiateTeleportToLocation(agent, neighbourx, neighboury, newposition, scene); - return true; - } + neighboury--; + newpos.Y = Constants.RegionSize - enterDistance; } else if (scene.TestBorderCross(pos + northCross, Cardinals.N)) { @@ -1532,19 +1466,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } */ - ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); + xDest = neighbourx; + yDest = neighboury; int x = (int)(neighbourx * Constants.RegionSize), y = (int)(neighboury * Constants.RegionSize); + ulong neighbourHandle = Utils.UIntsToLong((uint)x, (uint)y); + ExpiringCache r; DateTime banUntil; - if (m_bannedRegions.TryGetValue(agent.ControllingClient.AgentId, out r)) + if (m_bannedRegions.TryGetValue(agentID, out r)) { if (r.TryGetValue(neighbourHandle, out banUntil)) { if (DateTime.Now < banUntil) - return false; + return null; r.Remove(neighbourHandle); } } @@ -1556,28 +1493,43 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer GridRegion neighbourRegion = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); string reason; - string version; - if (!scene.SimulationService.QueryAccess(neighbourRegion, agent.ControllingClient.AgentId, newpos, out version, out reason)) + if (!scene.SimulationService.QueryAccess(neighbourRegion, agentID, newpos, out version, out reason)) { - agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); if (r == null) { r = new ExpiringCache(); r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); - m_bannedRegions.Add(agent.ControllingClient.AgentId, r, TimeSpan.FromSeconds(45)); + m_bannedRegions.Add(agentID, r, TimeSpan.FromSeconds(45)); } else { r.Add(neighbourHandle, DateTime.Now + TimeSpan.FromSeconds(15), TimeSpan.FromSeconds(15)); } + return null; + } + + return neighbourRegion; + } + + public bool Cross(ScenePresence agent, bool isFlying) + { + uint x; + uint y; + Vector3 newpos; + string version; + + GridRegion neighbourRegion = GetDestination(agent.Scene, agent.UUID, agent.AbsolutePosition, out x, out y, out version, out newpos); + if (neighbourRegion == null) + { + agent.ControllingClient.SendAlertMessage("Cannot region cross into banned parcel"); return false; } agent.IsInTransit = true; CrossAgentToNewRegionDelegate d = CrossAgentToNewRegionAsync; - d.BeginInvoke(agent, newpos, neighbourx, neighboury, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); + d.BeginInvoke(agent, newpos, neighbourRegion, isFlying, version, CrossAgentToNewRegionCompleted, d); return true; } @@ -1659,52 +1611,49 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer icon.EndInvoke(iar); } - public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version); + public bool CrossAgentToNewRegionPrep(ScenePresence agent, GridRegion neighbourRegion) + { + if (neighbourRegion == null) + return false; + + m_entityTransferStateMachine.SetInTransit(agent.UUID); + + agent.RemoveFromPhysicalScene(); + + return true; + } /// /// This Closes child agents on neighbouring regions /// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// - protected ScenePresence CrossAgentToNewRegionAsync( - ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, + public ScenePresence CrossAgentToNewRegionAsync( + ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version) { - if (neighbourRegion == null) - return agent; - - if (!m_entityTransferStateMachine.SetInTransit(agent.UUID)) + if (!CrossAgentToNewRegionPrep(agent, neighbourRegion)) { - m_log.ErrorFormat( - "[ENTITY TRANSFER MODULE]: Problem crossing user {0} to new region {1} from {2} - agent is already in transit", - agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName); + m_entityTransferStateMachine.ResetFromTransit(agent.UUID); return agent; } - bool transitWasReset = false; + if (!CrossAgentIntoNewRegionMain(agent, pos, neighbourRegion, isFlying)) + { + m_entityTransferStateMachine.ResetFromTransit(agent.UUID); + return agent; + } + CrossAgentToNewRegionPost(agent, pos, neighbourRegion, isFlying, version); + return agent; + } + + public bool CrossAgentIntoNewRegionMain(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying) + { try { - ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); - - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Crossing agent {0} {1} to {2}-{3} running version {4}", - agent.Firstname, agent.Lastname, neighbourx, neighboury, version); - - Scene m_scene = agent.Scene; - - if (!agent.ValidateAttachments()) - m_log.DebugFormat( - "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.", - agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName); - - pos = pos + agent.Velocity; - Vector3 vel2 = new Vector3(agent.Velocity.X, agent.Velocity.Y, 0); - - agent.RemoveFromPhysicalScene(); - - AgentData cAgent = new AgentData(); + AgentData cAgent = new AgentData(); agent.CopyTo(cAgent); - cAgent.Position = pos; + cAgent.Position = pos + agent.Velocity; if (isFlying) cAgent.ControlFlags |= (uint)AgentManager.ControlFlags.AGENT_CONTROL_FLY; @@ -1714,7 +1663,7 @@ 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 (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) + if (!agent.Scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) { // region doesn't take it m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); @@ -1726,72 +1675,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer ReInstantiateScripts(agent); agent.AddToPhysicalScene(isFlying); - return agent; + return false; } - //m_log.Debug("BEFORE CROSS"); - //Scene.DumpChildrenSeeds(UUID); - //DumpKnownRegions(); - 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 agent; - } - - // No turning back - agent.IsChildAgent = true; - - string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); - - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, agent.UUID); - - if (m_eqModule != null) - { - m_eqModule.CrossRegion( - neighbourHandle, pos, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, - capsPath, agent.UUID, agent.ControllingClient.SessionId); - } - else - { - agent.ControllingClient.CrossRegion(neighbourHandle, pos, agent.Velocity, neighbourRegion.ExternalEndPoint, - capsPath); - } - - // SUCCESS! - m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); - - // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. - m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); - - agent.MakeChildAgent(); - - // FIXME: Possibly this should occur lower down after other commands to close other agents, - // but not sure yet what the side effects would be. - m_entityTransferStateMachine.ResetFromTransit(agent.UUID); - transitWasReset = true; - - // now we have a child agent in this region. Request all interesting data about other (root) agents - agent.SendOtherAgentsAvatarDataToMe(); - agent.SendOtherAgentsAppearanceToMe(); - - // Backwards compatibility. Best effort - if (version == "Unknown" || version == string.Empty) - { - m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one..."); - Thread.Sleep(3000); // wait a little now that we're not waiting for the callback - CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); - } - - // Next, let's close the child agent connections that are too far away. - agent.CloseChildAgents(neighbourx, neighboury); - - AgentHasMovedAway(agent, false); - - //m_log.Debug("AFTER CROSS"); - //Scene.DumpChildrenSeeds(UUID); - //DumpKnownRegions(); } catch (Exception e) { @@ -1800,14 +1686,97 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.Name, neighbourRegion.RegionName, agent.Scene.RegionInfo.RegionName, e.Message, e.StackTrace); // TODO: Might be worth attempting other restoration here such as reinstantiation of scripts, etc. - } - finally - { - if (!transitWasReset) - m_entityTransferStateMachine.ResetFromTransit(agent.UUID); + return false; } - return agent; + return true; + } + + public void CrossAgentToNewRegionPost(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, + bool isFlying, string version) + { + agent.ControllingClient.RequestClientInfo(); + + 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; + } + + // No turning back + agent.IsChildAgent = true; + + string capsPath = neighbourRegion.ServerURI + CapsUtil.GetCapsSeedPath(agentcaps); + + 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); + + if (m_eqModule != null) + { + m_eqModule.CrossRegion( + neighbourRegion.RegionHandle, pos + agent.Velocity, vel2 /* agent.Velocity */, neighbourRegion.ExternalEndPoint, + capsPath, agent.UUID, agent.ControllingClient.SessionId); + } + else + { + agent.ControllingClient.CrossRegion(neighbourRegion.RegionHandle, pos + agent.Velocity, agent.Velocity, neighbourRegion.ExternalEndPoint, + capsPath); + } + + // SUCCESS! + m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.ReceivedAtDestination); + + // Unlike a teleport, here we do not wait for the destination region to confirm the receipt. + m_entityTransferStateMachine.UpdateInTransit(agent.UUID, AgentTransferState.CleaningUp); + + agent.MakeChildAgent(); + + // FIXME: Possibly this should occur lower down after other commands to close other agents, + // but not sure yet what the side effects would be. + m_entityTransferStateMachine.ResetFromTransit(agent.UUID); + + // now we have a child agent in this region. Request all interesting data about other (root) agents + agent.SendOtherAgentsAvatarDataToMe(); + agent.SendOtherAgentsAppearanceToMe(); + + // Backwards compatibility. Best effort + if (version == "Unknown" || version == string.Empty) + { + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: neighbor with old version, passing attachments one by one..."); + Thread.Sleep(3000); // wait a little now that we're not waiting for the callback + CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); + } + + // Next, let's close the child agent connections that are too far away. + uint neighbourx; + uint neighboury; + + Utils.LongToUInts(neighbourRegion.RegionHandle, out neighbourx, out neighboury); + + neighbourx /= Constants.RegionSize; + neighboury /= Constants.RegionSize; + + agent.CloseChildAgents(neighbourx, neighboury); + + AgentHasMovedAway(agent, false); + + // 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; } private void CrossAgentToNewRegionCompleted(IAsyncResult iar) @@ -1878,10 +1847,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.Id0 = currentAgentCircuit.Id0; } - InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; - d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true, + IPEndPoint external = region.ExternalEndPoint; + if (external != null) + { + InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; + d.BeginInvoke(sp, agent, region, external, true, InformClientOfNeighbourCompleted, d); + } } #endregion @@ -2478,30 +2451,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer Utils.LongToUInts(newRegionHandle, out x, out y); GridRegion destination = scene.GridService.GetRegionByPosition(scene.RegionInfo.ScopeID, (int)x, (int)y); - if (destination == null || !CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) + if (destination != null) { - m_log.InfoFormat("[ENTITY TRANSFER MODULE] cross region transfer failed for object {0}",grp.UUID); - - // We are going to move the object back to the old position so long as the old position - // is in the region - oldGroupPosition.X = Util.Clamp(oldGroupPosition.X,1.0f,(float)Constants.RegionSize-1); - oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y,1.0f,(float)Constants.RegionSize-1); - oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z,1.0f,4096.0f); - - grp.RootPart.GroupPosition = oldGroupPosition; - - // Need to turn off the physics flags, otherwise the object will continue to attempt to - // move out of the region creating an infinite loop of failed attempts to cross - grp.UpdatePrimFlags(grp.RootPart.LocalId,false,grp.IsTemporary,grp.IsPhantom,false); - - if (grp.RootPart.KeyframeMotion != null) - grp.RootPart.KeyframeMotion.CrossingFailure(); - - grp.ScheduleGroupForFullUpdate(); + if (CrossPrimGroupIntoNewRegion(destination, pos, grp, silent)) + return; // we did it } + + // no one or failed lets go back and tell physics to go on + oldGroupPosition.X = Util.Clamp(oldGroupPosition.X, 0.5f, (float)Constants.RegionSize - 0.5f); + oldGroupPosition.Y = Util.Clamp(oldGroupPosition.Y, 0.5f, (float)Constants.RegionSize - 0.5f); + oldGroupPosition.Z = Util.Clamp(oldGroupPosition.Z, 0.5f, 4096.0f); + + grp.AbsolutePosition = oldGroupPosition; + grp.Velocity = Vector3.Zero; + + if (grp.RootPart.PhysActor != null) + grp.RootPart.PhysActor.CrossingFailure(); + + if (grp.RootPart.KeyframeMotion != null) + grp.RootPart.KeyframeMotion.CrossingFailure(); + + grp.ScheduleGroupForFullUpdate(); } + /// /// Move the given scene object into a new region /// @@ -2552,17 +2526,30 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer grp, e); } } +/* + * done on caller ( not in attachments crossing for now) else { + if (!grp.IsDeleted) { PhysicsActor pa = grp.RootPart.PhysActor; if (pa != null) + { pa.CrossingFailure(); + if (grp.RootPart.KeyframeMotion != null) + { + // moved to KeyframeMotion.CrossingFailure +// grp.RootPart.Velocity = Vector3.Zero; + grp.RootPart.KeyframeMotion.CrossingFailure(); +// grp.SendGroupRootTerseUpdate(); + } + } } m_log.ErrorFormat("[ENTITY TRANSFER MODULE]: Prim crossing failed for {0}", grp); } + */ } else { diff --git a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs index 1c43a25e31..1949a9007a 100644 --- a/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEntityTransferModule.cs @@ -35,6 +35,8 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.Framework.Interfaces { + public delegate ScenePresence CrossAgentToNewRegionDelegate(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); + public interface IEntityTransferModule { /// @@ -50,30 +52,11 @@ namespace OpenSim.Region.Framework.Interfaces /// void Teleport(ScenePresence agent, ulong regionHandle, Vector3 position, Vector3 lookAt, uint teleportFlags); - /// - /// Teleport an agent directly to a given region without checking whether the region should be subsituted. - /// - /// - /// Please use Teleport() instead unless you know exactly what you're doing. - /// Do not use for same region teleports. - /// - /// - /// - /// /param> - /// - /// - /// - void DoTeleport( - ScenePresence sp, GridRegion reg, GridRegion finalDestination, - Vector3 position, Vector3 lookAt, uint teleportFlags); - - /// - /// Teleports the agent for the given client to their home destination. - /// - /// - /// bool TeleportHome(UUID id, IClientAPI client); + void DoTeleport(ScenePresence sp, GridRegion reg, GridRegion finalDestination, + Vector3 position, Vector3 lookAt, uint teleportFlags); + /// /// Show whether the given agent is being teleported. /// @@ -89,7 +72,12 @@ namespace OpenSim.Region.Framework.Interfaces void EnableChildAgent(ScenePresence agent, GridRegion region); + GridRegion GetDestination(Scene scene, UUID agentID, Vector3 pos, out uint xDest, out uint yDest, out string version, out Vector3 newpos); + void Cross(SceneObjectGroup sog, Vector3 position, bool silent); + + ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, GridRegion neighbourRegion, bool isFlying, string version); + } public interface IUserAgentVerificationModule From 5b73b9c4a85335ba837280688b903fef44be8f35 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 11 Dec 2013 01:39:56 +0000 Subject: [PATCH 07/24] Committing the Avination Scene Presence and related texture code - Parts of region crossing code - New bakes handling code - Bakes now sent from sim to sim without central storage - Appearance handling changes - Some changes to sitting - A number of unrelated fixes and improvements --- OpenSim/Framework/AvatarAppearance.cs | 313 +++-- OpenSim/Framework/ChildAgentDataUpdate.cs | 18 +- OpenSim/Framework/IClientAPI.cs | 2 +- OpenSim/Framework/IImprovedAssetCache.cs | 1 + OpenSim/Framework/ILandObject.cs | 1 + .../ClientStack/Linden/UDP/LLClientView.cs | 17 +- .../CoreModules/Asset/CenomeAssetCache.cs | 6 + .../CoreModules/Asset/CoreAssetCache.cs | 4 + .../CoreModules/Asset/FlotsamAssetCache.cs | 169 ++- .../Asset/GlynnTuckerAssetCache.cs | 5 + .../AvatarFactory/AvatarFactoryModule.cs | 560 +++++++-- .../Tests/AvatarFactoryModuleTests.cs | 8 +- .../CoreModules/World/Land/LandObject.cs | 13 + .../Interfaces/IAvatarFactoryModule.cs | 6 +- .../Framework/Scenes/SceneObjectGroup.cs | 42 + .../Region/Framework/Scenes/ScenePresence.cs | 1067 +++++++++++------ .../Server/IRCClientView.cs | 2 +- .../World/NPC/Tests/NPCModuleTests.cs | 2 + .../Tests/Performance/NPCPerformanceTests.cs | 4 +- 19 files changed, 1621 insertions(+), 619 deletions(-) diff --git a/OpenSim/Framework/AvatarAppearance.cs b/OpenSim/Framework/AvatarAppearance.cs index 157feb552f..b7a0adface 100644 --- a/OpenSim/Framework/AvatarAppearance.cs +++ b/OpenSim/Framework/AvatarAppearance.cs @@ -40,8 +40,17 @@ namespace OpenSim.Framework /// public class AvatarAppearance { + // SL box diferent to size + const float AVBOXAJUST = 0.2f; + // constrains for ubitode physics + const float AVBOXMINX = 0.2f; + const float AVBOXMINY = 0.3f; + const float AVBOXMINZ = 1.2f; + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + // this is viewer capabilities and weared things dependent + // should be only used as initial default value ( V1 viewers ) public readonly static int VISUALPARAM_COUNT = 218; public readonly static int TEXTURE_COUNT = 21; @@ -53,7 +62,12 @@ namespace OpenSim.Framework protected AvatarWearable[] m_wearables; protected Dictionary> m_attachments; protected float m_avatarHeight = 0; - protected UUID[] m_texturehashes; + protected Vector3 m_avatarSize = new Vector3(0.45f, 0.6f, 1.9f); // sl Z cloud value + protected Vector3 m_avatarBoxSize = new Vector3(0.45f, 0.6f, 1.9f); + protected float m_avatarFeetOffset = 0; + protected float m_avatarAnimOffset = 0; + protected WearableCacheItem[] m_cacheitems; + protected bool m_cacheItemsDirty = true; public virtual int Serial { @@ -67,6 +81,21 @@ namespace OpenSim.Framework set { m_visualparams = value; } } + public virtual Vector3 AvatarSize + { + get { return m_avatarSize; } + } + + public virtual Vector3 AvatarBoxSize + { + get { return m_avatarBoxSize; } + } + + public virtual float AvatarFeetOffset + { + get { return m_avatarFeetOffset + m_avatarAnimOffset; } + } + public virtual Primitive.TextureEntry Texture { get { return m_texture; } @@ -88,6 +117,18 @@ namespace OpenSim.Framework get { return m_avatarHeight; } set { m_avatarHeight = value; } } + + public virtual WearableCacheItem[] WearableCacheItems + { + get { return m_cacheitems; } + set { m_cacheitems = value; } + } + + public virtual bool WearableCacheItemsDirty + { + get { return m_cacheItemsDirty; } + set { m_cacheItemsDirty = value; } + } public AvatarAppearance() { @@ -97,10 +138,9 @@ namespace OpenSim.Framework SetDefaultWearables(); SetDefaultTexture(); SetDefaultParams(); - SetHeight(); +// SetHeight(); + SetSize(new Vector3(0.45f,0.6f,1.9f)); m_attachments = new Dictionary>(); - - ResetTextureHashes(); } public AvatarAppearance(OSDMap map) @@ -108,7 +148,35 @@ namespace OpenSim.Framework // m_log.WarnFormat("[AVATAR APPEARANCE]: create appearance from OSDMap"); Unpack(map); - SetHeight(); +// SetHeight(); done in Unpack + } + + public AvatarAppearance(AvatarWearable[] wearables, Primitive.TextureEntry textureEntry, byte[] visualParams) + { +// m_log.WarnFormat("[AVATAR APPEARANCE] create initialized appearance"); + + m_serial = 0; + + if (wearables != null) + m_wearables = wearables; + else + SetDefaultWearables(); + + if (textureEntry != null) + m_texture = textureEntry; + else + SetDefaultTexture(); + + if (visualParams != null) + m_visualparams = visualParams; + else + SetDefaultParams(); + +// SetHeight(); + if(m_avatarHeight == 0) + SetSize(new Vector3(0.45f,0.6f,1.9f)); + + m_attachments = new Dictionary>(); } public AvatarAppearance(AvatarAppearance appearance) : this(appearance, true) @@ -125,11 +193,10 @@ namespace OpenSim.Framework SetDefaultWearables(); SetDefaultTexture(); SetDefaultParams(); - SetHeight(); +// SetHeight(); + SetSize(new Vector3(0.45f, 0.6f, 1.9f)); m_attachments = new Dictionary>(); - ResetTextureHashes(); - return; } @@ -145,10 +212,6 @@ namespace OpenSim.Framework SetWearable(i,appearance.Wearables[i]); } - m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT]; - for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) - m_texturehashes[i] = new UUID(appearance.m_texturehashes[i]); - m_texture = null; if (appearance.Texture != null) { @@ -160,7 +223,8 @@ namespace OpenSim.Framework if (appearance.VisualParams != null) m_visualparams = (byte[])appearance.VisualParams.Clone(); - m_avatarHeight = appearance.m_avatarHeight; +// m_avatarHeight = appearance.m_avatarHeight; + SetSize(appearance.AvatarSize); // Copy the attachment, force append mode since that ensures consistency m_attachments = new Dictionary>(); @@ -183,37 +247,6 @@ namespace OpenSim.Framework } } - public void ResetTextureHashes() - { - m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT]; - for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) - m_texturehashes[i] = UUID.Zero; - } - - public UUID GetTextureHash(int textureIndex) - { - return m_texturehashes[NormalizeBakedTextureIndex(textureIndex)]; - } - - public void SetTextureHash(int textureIndex, UUID textureHash) - { - m_texturehashes[NormalizeBakedTextureIndex(textureIndex)] = new UUID(textureHash); - } - - /// - /// Normalizes the texture index to the actual bake index, this is done to - /// accommodate older viewers that send the BAKE_INDICES index rather than - /// the actual texture index - /// - private int NormalizeBakedTextureIndex(int textureIndex) - { - // Earlier viewer send the index into the baked index array, just trying to be careful here - if (textureIndex < BAKE_INDICES.Length) - return BAKE_INDICES[textureIndex]; - - return textureIndex; - } - public void ClearWearables() { m_wearables = new AvatarWearable[AvatarWearable.MAX_WEARABLES]; @@ -237,7 +270,12 @@ namespace OpenSim.Framework m_serial = 0; SetDefaultTexture(); - ResetTextureHashes(); + + //for (int i = 0; i < BAKE_INDICES.Length; i++) + // { + // int idx = BAKE_INDICES[i]; + // m_texture.FaceTextures[idx].TextureID = UUID.Zero; + // } } protected virtual void SetDefaultParams() @@ -249,6 +287,21 @@ namespace OpenSim.Framework // } } + /// + /// Invalidate all of the baked textures in the appearance, useful + /// if you know that none are valid + /// + public virtual void ResetBakedTextures() + { + SetDefaultTexture(); + + //for (int i = 0; i < BAKE_INDICES.Length; i++) + // { + // int idx = BAKE_INDICES[i]; + // m_texture.FaceTextures[idx].TextureID = UUID.Zero; + // } + } + protected virtual void SetDefaultTexture() { m_texture = new Primitive.TextureEntry(new UUID(AppearanceManager.DEFAULT_AVATAR_TEXTURE)); @@ -313,22 +366,33 @@ namespace OpenSim.Framework // made. We determine if any of the visual parameters actually // changed to know if the appearance should be saved later bool changed = false; - for (int i = 0; i < AvatarAppearance.VISUALPARAM_COUNT; i++) + + int newsize = visualParams.Length; + + if (newsize != m_visualparams.Length) { - if (visualParams[i] != m_visualparams[i]) + changed = true; + m_visualparams = (byte[])visualParams.Clone(); + } + else + { + + for (int i = 0; i < newsize; i++) { -// DEBUG ON -// m_log.WarnFormat("[AVATARAPPEARANCE] vparams changed [{0}] {1} ==> {2}", -// i,m_visualparams[i],visualParams[i]); -// DEBUG OFF - m_visualparams[i] = visualParams[i]; - changed = true; + if (visualParams[i] != m_visualparams[i]) + { + // DEBUG ON + // m_log.WarnFormat("[AVATARAPPEARANCE] vparams changed [{0}] {1} ==> {2}", + // i,m_visualparams[i],visualParams[i]); + // DEBUG OFF + m_visualparams[i] = visualParams[i]; + changed = true; + } } } - // Reset the height if the visual parameters actually changed - if (changed) - SetHeight(); +// if (changed) +// SetHeight(); return changed; } @@ -344,6 +408,7 @@ namespace OpenSim.Framework /// public virtual void SetHeight() { +/* // Start with shortest possible female avatar height m_avatarHeight = 1.14597f; // Add offset for male avatars @@ -356,6 +421,35 @@ namespace OpenSim.Framework + 0.07f * (float)m_visualparams[(int)VPElement.SHOES_PLATFORM_HEIGHT] / 255.0f + 0.08f * (float)m_visualparams[(int)VPElement.SHOES_HEEL_HEIGHT] / 255.0f + 0.076f * (float)m_visualparams[(int)VPElement.SHAPE_NECK_LENGTH] / 255.0f; +*/ + } + + public void SetSize(Vector3 avSize) + { + if (avSize.X > 32f) + avSize.X = 32f; + else if (avSize.X < 0.1f) + avSize.X = 0.1f; + + if (avSize.Y > 32f) + avSize.Y = 32f; + else if (avSize.Y < 0.1f) + avSize.Y = 0.1f; + if (avSize.Z > 32f) + avSize.Z = 32f; + else if (avSize.Z < 0.1f) + avSize.Z = 0.1f; + + m_avatarSize = avSize; + m_avatarBoxSize = avSize; + m_avatarBoxSize.Z += AVBOXAJUST; + if (m_avatarBoxSize.X < AVBOXMINX) + m_avatarBoxSize.X = AVBOXMINX; + if (m_avatarBoxSize.Y < AVBOXMINY) + m_avatarBoxSize.Y = AVBOXMINY; + if (m_avatarBoxSize.Z < AVBOXMINZ) + m_avatarBoxSize.Z = AVBOXMINZ; + m_avatarHeight = m_avatarSize.Z; } public virtual void SetWearable(int wearableId, AvatarWearable wearable) @@ -386,7 +480,8 @@ namespace OpenSim.Framework } s += "Visual Params: "; - for (uint j = 0; j < AvatarAppearance.VISUALPARAM_COUNT; j++) + // for (uint j = 0; j < AvatarAppearance.VISUALPARAM_COUNT; j++) + for (uint j = 0; j < m_visualparams.Length; j++) s += String.Format("{0},",m_visualparams[j]); s += "\n"; @@ -402,18 +497,16 @@ namespace OpenSim.Framework /// public List GetAttachments() { - List alist = new List(); - lock (m_attachments) { + List alist = new List(); foreach (KeyValuePair> kvp in m_attachments) { foreach (AvatarAttachment attach in kvp.Value) alist.Add(new AvatarAttachment(attach)); } - } - - return alist; + return alist; + } } internal void AppendAttachment(AvatarAttachment attach) @@ -557,7 +650,6 @@ namespace OpenSim.Framework return kvp.Key; } } - return 0; } @@ -607,12 +699,6 @@ namespace OpenSim.Framework data["serial"] = OSD.FromInteger(m_serial); data["height"] = OSD.FromReal(m_avatarHeight); - // Hashes - OSDArray hashes = new OSDArray(AvatarAppearance.TEXTURE_COUNT); - for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) - hashes.Add(OSD.FromUUID(m_texturehashes[i])); - data["hashes"] = hashes; - // Wearables OSDArray wears = new OSDArray(AvatarWearable.MAX_WEARABLES); for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) @@ -634,12 +720,14 @@ namespace OpenSim.Framework OSDBinary visualparams = new OSDBinary(m_visualparams); data["visualparams"] = visualparams; - // Attachments - List attachments = GetAttachments(); - OSDArray attachs = new OSDArray(attachments.Count); - foreach (AvatarAttachment attach in GetAttachments()) - attachs.Add(attach.Pack()); - data["attachments"] = attachs; + lock (m_attachments) + { + // Attachments + OSDArray attachs = new OSDArray(m_attachments.Count); + foreach (AvatarAttachment attach in GetAttachments()) + attachs.Add(attach.Pack()); + data["attachments"] = attachs; + } return data; } @@ -653,29 +741,11 @@ namespace OpenSim.Framework if ((data != null) && (data["serial"] != null)) m_serial = data["serial"].AsInteger(); if ((data != null) && (data["height"] != null)) - m_avatarHeight = (float)data["height"].AsReal(); +// m_avatarHeight = (float)data["height"].AsReal(); + SetSize(new Vector3(0.45f,0.6f, (float)data["height"].AsReal())); try { - // Hashes - m_texturehashes = new UUID[AvatarAppearance.TEXTURE_COUNT]; - if ((data != null) && (data["hashes"] != null) && (data["hashes"]).Type == OSDType.Array) - { - OSDArray hashes = (OSDArray)(data["hashes"]); - for (int i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) - { - UUID hashID = UUID.Zero; - if (i < hashes.Count && hashes[i] != null) - hashID = hashes[i].AsUUID(); - m_texturehashes[i] = hashID; - } - } - else - { - for (uint i = 0; i < AvatarAppearance.TEXTURE_COUNT; i++) - m_texturehashes[i] = UUID.Zero; - } - // Wearables SetDefaultWearables(); if ((data != null) && (data["wearables"] != null) && (data["wearables"]).Type == OSDType.Array) @@ -1505,7 +1575,58 @@ namespace OpenSim.Framework SHAPE_EYELID_INNER_CORNER_UP = 214, SKIRT_SKIRT_RED = 215, SKIRT_SKIRT_GREEN = 216, - SKIRT_SKIRT_BLUE = 217 + SKIRT_SKIRT_BLUE = 217, + + /// + /// Avatar Physics section. These are 0 type visual params which get transmitted. + /// + + /// + /// Breast Part 1 + /// + BREAST_PHYSICS_MASS = 218, + BREAST_PHYSICS_GRAVITY = 219, + BREAST_PHYSICS_DRAG = 220, + BREAST_PHYSICS_UPDOWN_MAX_EFFECT = 221, + BREAST_PHYSICS_UPDOWN_SPRING = 222, + BREAST_PHYSICS_UPDOWN_GAIN = 223, + BREAST_PHYSICS_UPDOWN_DAMPING = 224, + BREAST_PHYSICS_INOUT_MAX_EFFECT = 225, + BREAST_PHYSICS_INOUT_SPRING = 226, + BREAST_PHYSICS_INOUT_GAIN = 227, + BREAST_PHYSICS_INOUT_DAMPING = 228, + /// + /// Belly + /// + BELLY_PHYISCS_MASS = 229, + BELLY_PHYSICS_GRAVITY = 230, + BELLY_PHYSICS_DRAG = 231, + BELLY_PHYISCS_UPDOWN_MAX_EFFECT = 232, + BELLY_PHYSICS_UPDOWN_SPRING = 233, + BELLY_PHYSICS_UPDOWN_GAIN = 234, + BELLY_PHYSICS_UPDOWN_DAMPING = 235, + + /// + /// Butt + /// + BUTT_PHYSICS_MASS = 236, + BUTT_PHYSICS_GRAVITY = 237, + BUTT_PHYSICS_DRAG = 238, + BUTT_PHYSICS_UPDOWN_MAX_EFFECT = 239, + BUTT_PHYSICS_UPDOWN_SPRING = 240, + BUTT_PHYSICS_UPDOWN_GAIN = 241, + BUTT_PHYSICS_UPDOWN_DAMPING = 242, + BUTT_PHYSICS_LEFTRIGHT_MAX_EFFECT = 243, + BUTT_PHYSICS_LEFTRIGHT_SPRING = 244, + BUTT_PHYSICS_LEFTRIGHT_GAIN = 245, + BUTT_PHYSICS_LEFTRIGHT_DAMPING = 246, + /// + /// Breast Part 2 + /// + BREAST_PHYSICS_LEFTRIGHT_MAX_EFFECT = 247, + BREAST_PHYSICS_LEFTRIGHT_SPRING= 248, + BREAST_PHYSICS_LEFTRIGHT_GAIN = 249, + BREAST_PHYSICS_LEFTRIGHT_DAMPING = 250 } #endregion } diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index 18d008c654..2a8e67dd61 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -230,12 +230,14 @@ namespace OpenSim.Framework public class ControllerData { + public UUID ObjectID; public UUID ItemID; public uint IgnoreControls; public uint EventControls; - public ControllerData(UUID item, uint ignore, uint ev) + public ControllerData(UUID obj, UUID item, uint ignore, uint ev) { + ObjectID = obj; ItemID = item; IgnoreControls = ignore; EventControls = ev; @@ -249,6 +251,7 @@ namespace OpenSim.Framework public OSDMap PackUpdateMessage() { OSDMap controldata = new OSDMap(); + controldata["object"] = OSD.FromUUID(ObjectID); controldata["item"] = OSD.FromUUID(ItemID); controldata["ignore"] = OSD.FromInteger(IgnoreControls); controldata["event"] = OSD.FromInteger(EventControls); @@ -259,6 +262,8 @@ namespace OpenSim.Framework public void UnpackUpdateMessage(OSDMap args) { + if (args["object"] != null) + ObjectID = args["object"].AsUUID(); if (args["item"] != null) ItemID = args["item"].AsUUID(); if (args["ignore"] != null) @@ -317,6 +322,8 @@ namespace OpenSim.Framework public Animation AnimState = null; public UUID GranterID; + public UUID ParentPart; + public Vector3 SitOffset; // Appearance public AvatarAppearance Appearance; @@ -488,6 +495,10 @@ namespace OpenSim.Framework } args["attach_objects"] = attObjs; } + + args["parent_part"] = OSD.FromUUID(ParentPart); + args["sit_offset"] = OSD.FromString(SitOffset.ToString()); + return args; } @@ -719,6 +730,11 @@ namespace OpenSim.Framework } } } + + if (args["parent_part"] != null) + ParentPart = args["parent_part"].AsUUID(); + if (args["sit_offset"] != null) + Vector3.TryParse(args["sit_offset"].AsString(), out SitOffset); } public AgentData() diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 98358e512b..e36edb247d 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -66,7 +66,7 @@ namespace OpenSim.Framework public delegate void CachedTextureRequest(IClientAPI remoteClient, int serial, List cachedTextureRequest); - public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, List cachedTextureData); + public delegate void SetAppearance(IClientAPI remoteClient, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 AvSize, WearableCacheItem[] CacheItems); public delegate void StartAnim(IClientAPI remoteClient, UUID animID); diff --git a/OpenSim/Framework/IImprovedAssetCache.cs b/OpenSim/Framework/IImprovedAssetCache.cs index 251215a559..a0b8b55aaa 100644 --- a/OpenSim/Framework/IImprovedAssetCache.cs +++ b/OpenSim/Framework/IImprovedAssetCache.cs @@ -33,6 +33,7 @@ namespace OpenSim.Framework { void Cache(AssetBase asset); AssetBase Get(string id); + bool Check(string id); void Expire(string id); void Clear(); } diff --git a/OpenSim/Framework/ILandObject.cs b/OpenSim/Framework/ILandObject.cs index 4f98d7bb30..7a24d1ec6a 100644 --- a/OpenSim/Framework/ILandObject.cs +++ b/OpenSim/Framework/ILandObject.cs @@ -70,6 +70,7 @@ namespace OpenSim.Framework void UpdateLandProperties(LandUpdateArgs args, IClientAPI remote_client); bool IsEitherBannedOrRestricted(UUID avatar); bool IsBannedFromLand(UUID avatar); + bool CanBeOnThisLand(UUID avatar, float posHeight); bool IsRestrictedFromLand(UUID avatar); bool IsInLandAccessList(UUID avatar); void SendLandUpdateToClient(IClientAPI remote_client); diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index a04ded5b9a..6cb733279c 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -6437,26 +6437,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP // Temporarily protect ourselves from the mantis #951 failure. // However, we could do this for several other handlers where a failure isn't terminal // for the client session anyway, in order to protect ourselves against bad code in plugins + Vector3 avSize = appear.AgentData.Size; try { byte[] visualparams = new byte[appear.VisualParam.Length]; for (int i = 0; i < appear.VisualParam.Length; i++) visualparams[i] = appear.VisualParam[i].ParamValue; + //var b = appear.WearableData[0]; Primitive.TextureEntry te = null; if (appear.ObjectData.TextureEntry.Length > 1) te = new Primitive.TextureEntry(appear.ObjectData.TextureEntry, 0, appear.ObjectData.TextureEntry.Length); - List hashes = new List(); - for (int i = 0; i < appear.WearableData.Length; i++) - { - CachedTextureRequestArg arg = new CachedTextureRequestArg(); - arg.BakedTextureIndex = appear.WearableData[i].TextureIndex; - arg.WearableHashID = appear.WearableData[i].CacheID; - hashes.Add(arg); - } + WearableCacheItem[] cacheitems = new WearableCacheItem[appear.WearableData.Length]; + for (int i=0; i /// Cache asset. /// diff --git a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs index 9742a5caa4..58ce61ac4e 100644 --- a/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/CoreAssetCache.cs @@ -112,6 +112,10 @@ namespace OpenSim.Region.CoreModules.Asset //////////////////////////////////////////////////////////// // IImprovedAssetCache // + public bool Check(string id) + { + return false; + } public void Cache(AssetBase asset) { diff --git a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs index 08d4fc0c0c..f1fee6322c 100644 --- a/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/FlotsamAssetCache.cs @@ -248,57 +248,70 @@ namespace OpenSim.Region.CoreModules.Asset private void UpdateFileCache(string key, AssetBase asset) { - string filename = GetFileName(asset.ID); - - try + // TODO: Spawn this off to some seperate thread to do the actual writing + if (asset != null) { - // If the file is already cached just update access time. - if (File.Exists(filename)) + string filename = GetFileName(key); + + try { - lock (m_CurrentlyWriting) + // If the file is already cached, don't cache it, just touch it so access time is updated + if (File.Exists(filename)) { - if (!m_CurrentlyWriting.Contains(filename)) - File.SetLastAccessTime(filename, DateTime.Now); - } - } - else - { - // Once we start writing, make sure we flag that we're writing - // that object to the cache so that we don't try to write the - // same file multiple times. - lock (m_CurrentlyWriting) - { -#if WAIT_ON_INPROGRESS_REQUESTS - if (m_CurrentlyWriting.ContainsKey(filename)) + // We don't really want to know about sharing + // violations here. If the file is locked, then + // the other thread has updated the time for us. + try { - return; + lock (m_CurrentlyWriting) + { + if (!m_CurrentlyWriting.Contains(filename)) + File.SetLastAccessTime(filename, DateTime.Now); + } } - else + catch { - m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); - } + } + } else { + + // Once we start writing, make sure we flag that we're writing + // that object to the cache so that we don't try to write the + // same file multiple times. + lock (m_CurrentlyWriting) + { +#if WAIT_ON_INPROGRESS_REQUESTS + if (m_CurrentlyWriting.ContainsKey(filename)) + { + return; + } + else + { + m_CurrentlyWriting.Add(filename, new ManualResetEvent(false)); + } #else - if (m_CurrentlyWriting.Contains(filename)) - { - return; - } - else - { - m_CurrentlyWriting.Add(filename); - } + if (m_CurrentlyWriting.Contains(filename)) + { + return; + } + else + { + m_CurrentlyWriting.Add(filename); + } #endif - } - Util.FireAndForget( - delegate { WriteFileCache(filename, asset); }); + } + + Util.FireAndForget( + delegate { WriteFileCache(filename, asset); }); + } + } + catch (Exception e) + { + m_log.ErrorFormat( + "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}", + asset.ID, e.Message, e.StackTrace); } - } - catch (Exception e) - { - m_log.WarnFormat( - "[FLOTSAM ASSET CACHE]: Failed to update cache for asset {0}. Exception {1} {2}", - asset.ID, e.Message, e.StackTrace); } } @@ -332,6 +345,17 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + private bool CheckFromMemoryCache(string id) + { + AssetBase asset = null; + + if (m_MemoryCache.TryGetValue(id, out asset)) + return true; + + return false; + } + + /// /// Try to get an asset from the file cache. /// @@ -396,6 +420,7 @@ namespace OpenSim.Region.CoreModules.Asset m_log.WarnFormat( "[FLOTSAM ASSET CACHE]: Failed to get file {0} for asset {1}. Exception {2} {3}", filename, id, e.Message, e.StackTrace); + } finally { @@ -407,6 +432,50 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + private bool CheckFromFileCache(string id) + { + bool found = false; + + string filename = GetFileName(id); + if (File.Exists(filename)) + { + // actually check if we can open it, and so update expire + FileStream stream = null; + try + { + stream = File.Open(filename, FileMode.Open, FileAccess.Read, FileShare.Read); + if (stream != null) + { + found = true; + stream.Close(); + } + + } + catch (System.Runtime.Serialization.SerializationException e) + { + found = false; + m_log.ErrorFormat( + "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", + filename, id, e.Message, e.StackTrace); + + // If there was a problem deserializing the asset, the asset may + // either be corrupted OR was serialized under an old format + // {different version of AssetBase} -- we should attempt to + // delete it and re-cache + File.Delete(filename); + } + catch (Exception e) + { + found = false; + m_log.ErrorFormat( + "[FLOTSAM ASSET CACHE]: Failed to check file {0} for asset {1}. Exception {2} {3}", + filename, id, e.Message, e.StackTrace); + } + } + + return found; + } + public AssetBase Get(string id) { m_Requests++; @@ -434,11 +503,26 @@ namespace OpenSim.Region.CoreModules.Asset return asset; } + public bool Check(string id) + { + if (m_MemoryCacheEnabled && CheckFromMemoryCache(id)) + return true; + + if (m_FileCacheEnabled && CheckFromFileCache(id)) + return true; + return false; + } + public AssetBase GetCached(string id) { return Get(id); } + public AssetBase CheckCached(string id) + { + return Get(id); + } + public void Expire(string id) { if (m_LogLevel >= 2) @@ -983,6 +1067,11 @@ namespace OpenSim.Region.CoreModules.Asset return asset.Data; } + public bool CheckData(string id) + { + return Check(id); ; + } + public bool Get(string id, object sender, AssetRetrieved handler) { AssetBase asset = Get(id); diff --git a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs index 9592ca0019..ce9b5467f6 100644 --- a/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs +++ b/OpenSim/Region/CoreModules/Asset/GlynnTuckerAssetCache.cs @@ -115,6 +115,11 @@ namespace OpenSim.Region.CoreModules.Asset // IImprovedAssetCache // + public bool Check(string id) + { + return false; + } + public void Cache(AssetBase asset) { if (asset != null) diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index aea768eef4..09cc9983a8 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -145,9 +145,24 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// /// /// - public void SetAppearance(IScenePresence sp, AvatarAppearance appearance) + public void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems) { - DoSetAppearance(sp, appearance.Texture, appearance.VisualParams, new List()); + SetAppearance(sp, appearance.Texture, appearance.VisualParams, cacheItems); + } + + + public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) + { + float oldoff = sp.Appearance.AvatarFeetOffset; + Vector3 oldbox = sp.Appearance.AvatarBoxSize; + + SetAppearance(sp, textureEntry, visualParams, cacheItems); + sp.Appearance.SetSize(avSize); + + float off = sp.Appearance.AvatarFeetOffset; + Vector3 box = sp.Appearance.AvatarBoxSize; + if (oldoff != off || oldbox != box) + ((ScenePresence)sp).SetSize(box, off); } /// @@ -156,22 +171,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// /// /// - public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams) + public void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems) { - DoSetAppearance(sp, textureEntry, visualParams, new List()); - } - - /// - /// Set appearance data (texture asset IDs and slider settings) - /// - /// - /// - /// - protected void DoSetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, List hashes) - { - // m_log.DebugFormat( - // "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", - // sp.Name, textureEntry, visualParams); +// m_log.DebugFormat( +// "[AVFACTORY]: start SetAppearance for {0}, te {1}, visualParams {2}", +// sp.Name, textureEntry, visualParams); // TODO: This is probably not necessary any longer, just assume the // textureEntry set implies that the appearance transaction is complete @@ -190,36 +194,38 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory // m_log.DebugFormat( // "[AVFACTORY]: Setting visual params for {0} to {1}", // client.Name, string.Join(", ", visualParamsStrings)); - +/* float oldHeight = sp.Appearance.AvatarHeight; changed = sp.Appearance.SetVisualParams(visualParams); if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) ((ScenePresence)sp).SetHeight(sp.Appearance.AvatarHeight); - } + */ +// float oldoff = sp.Appearance.AvatarFeetOffset; +// Vector3 oldbox = sp.Appearance.AvatarBoxSize; + changed = sp.Appearance.SetVisualParams(visualParams); +// float off = sp.Appearance.AvatarFeetOffset; +// Vector3 box = sp.Appearance.AvatarBoxSize; +// if(oldoff != off || oldbox != box) +// ((ScenePresence)sp).SetSize(box,off); + } + // Process the baked texture array if (textureEntry != null) { - // m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); - // WriteBakedTexturesReport(sp, m_log.DebugFormat); + m_log.DebugFormat("[AVFACTORY]: Received texture update for {0} {1}", sp.Name, sp.UUID); + +// WriteBakedTexturesReport(sp, m_log.DebugFormat); changed = sp.Appearance.SetTextureEntries(textureEntry) || changed; - // WriteBakedTexturesReport(sp, m_log.DebugFormat); +// WriteBakedTexturesReport(sp, m_log.DebugFormat); // If bake textures are missing and this is not an NPC, request a rebake from client if (!ValidateBakedTextureCache(sp) && (((ScenePresence)sp).PresenceType != PresenceType.Npc)) RequestRebake(sp, true); - // Save the wearble hashes in the appearance - sp.Appearance.ResetTextureHashes(); - if (m_reusetextures) - { - foreach (CachedTextureRequestArg arg in hashes) - sp.Appearance.SetTextureHash(arg.BakedTextureIndex,arg.WearableHashID); - } - // This appears to be set only in the final stage of the appearance // update transaction. In theory, we should be able to do an immediate // appearance send and save here. @@ -253,13 +259,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public bool SendAppearance(UUID agentId) { - // m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId); +// m_log.DebugFormat("[AVFACTORY]: Sending appearance for {0}", agentId); ScenePresence sp = m_scene.GetScenePresence(agentId); if (sp == null) { // This is expected if the user has gone away. - // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId); +// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentId); return false; } @@ -277,6 +283,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory return GetBakedTextureFaces(sp); } + public WearableCacheItem[] GetCachedItems(UUID agentId) + { + ScenePresence sp = m_scene.GetScenePresence(agentId); + WearableCacheItem[] items = sp.Appearance.WearableCacheItems; + //foreach (WearableCacheItem item in items) + //{ + + //} + return items; + } + public bool SaveBakedTextures(UUID agentId) { ScenePresence sp = m_scene.GetScenePresence(agentId); @@ -336,7 +353,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// public void QueueAppearanceSend(UUID agentid) { - // m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); +// m_log.DebugFormat("[AVFACTORY]: Queue appearance send for {0}", agentid); // 10000 ticks per millisecond, 1000 milliseconds per second long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_sendtime * 1000 * 10000); @@ -349,7 +366,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public void QueueAppearanceSave(UUID agentid) { - // m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid); +// m_log.DebugFormat("[AVFACTORY]: Queueing appearance save for {0}", agentid); // 10000 ticks per millisecond, 1000 milliseconds per second long timestamp = DateTime.Now.Ticks + Convert.ToInt64(m_savetime * 1000 * 10000); @@ -363,6 +380,53 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public bool ValidateBakedTextureCache(IScenePresence sp) { bool defonly = true; // are we only using default textures + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); + IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); + WearableCacheItem[] wearableCache = null; + + // Cache wearable data for teleport. + // Only makes sense if there's a bake module and a cache module + if (bakedModule != null && cache != null) + { + try + { + wearableCache = bakedModule.Get(sp.UUID); + } + catch (Exception) + { + + } + if (wearableCache != null) + { + for (int i = 0; i < wearableCache.Length; i++) + { + cache.Cache(wearableCache[i].TextureAsset); + } + } + } + /* + IBakedTextureModule bakedModule = m_scene.RequestModuleInterface(); + if (invService.GetRootFolder(userID) != null) + { + WearableCacheItem[] wearableCache = null; + if (bakedModule != null) + { + try + { + wearableCache = bakedModule.Get(userID); + appearance.WearableCacheItems = wearableCache; + appearance.WearableCacheItemsDirty = false; + foreach (WearableCacheItem item in wearableCache) + { + appearance.Texture.FaceTextures[item.TextureIndex].TextureID = item.TextureID; + } + } + catch (Exception) + { + + } + } + */ // Process the texture entry for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) @@ -370,13 +434,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory int idx = AvatarAppearance.BAKE_INDICES[i]; Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[idx]; - // if there is no texture entry, skip it + // No face, so lets check our baked service cache, teleport or login. if (face == null) - continue; + { + if (wearableCache != null) + { + // If we find the an appearance item, set it as the textureentry and the face + WearableCacheItem searchitem = WearableCacheItem.SearchTextureIndex((uint) idx, wearableCache); + if (searchitem != null) + { + sp.Appearance.Texture.FaceTextures[idx] = sp.Appearance.Texture.CreateFace((uint) idx); + sp.Appearance.Texture.FaceTextures[idx].TextureID = searchitem.TextureID; + face = sp.Appearance.Texture.FaceTextures[idx]; + } + else + { + // if there is no texture entry and no baked cache, skip it + continue; + } + } + else + { + //No texture entry face and no cache. Skip this face. + continue; + } + } + - // m_log.DebugFormat( - // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", - // face.TextureID, idx, client.Name, client.AgentId); +// m_log.DebugFormat( +// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", +// face.TextureID, idx, client.Name, client.AgentId); // if the texture is one of the "defaults" then skip it // this should probably be more intelligent (skirt texture doesnt matter @@ -387,11 +474,19 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory defonly = false; // found a non-default texture reference - if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) - return false; + if (cache != null) + { + if (!cache.Check(face.TextureID.ToString())) + return false; + } + else + { + if (m_scene.AssetService.Get(face.TextureID.ToString()) == null) + return false; + } } - // m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); +// m_log.DebugFormat("[AVFACTORY]: Completed texture check for {0} {1}", sp.Name, sp.UUID); // If we only found default textures, then the appearance is not cached return (defonly ? false : true); @@ -400,6 +495,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public int RequestRebake(IScenePresence sp, bool missingTexturesOnly) { int texturesRebaked = 0; + IImprovedAssetCache cache = m_scene.RequestModuleInterface(); for (int i = 0; i < AvatarAppearance.BAKE_INDICES.Length; i++) { @@ -410,9 +506,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (face == null) continue; - // m_log.DebugFormat( - // "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", - // face.TextureID, idx, client.Name, client.AgentId); +// m_log.DebugFormat( +// "[AVFACTORY]: Looking for texture {0}, id {1} for {2} {3}", +// face.TextureID, idx, client.Name, client.AgentId); // if the texture is one of the "defaults" then skip it // this should probably be more intelligent (skirt texture doesnt matter @@ -423,21 +519,36 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (missingTexturesOnly) { - if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + if (cache != null) { - continue; + if (cache.Check(face.TextureID.ToString())) + continue; + else + { + m_log.DebugFormat( + "[AVFACTORY]: Missing baked texture {0} ({1}) for {2}, requesting rebake.", + face.TextureID, idx, sp.Name); + } } 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); + if (m_scene.AssetService.Get(face.TextureID.ToString()) != null) + { + 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); + } } } else @@ -476,9 +587,9 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (bakeType == BakeType.Unknown) continue; - // m_log.DebugFormat( - // "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}", - // acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); +// m_log.DebugFormat( +// "[AVFACTORY]: NPC avatar {0} has texture id {1} : {2}", +// acd.AgentID, i, acd.Appearance.Texture.FaceTextures[i]); int ftIndex = (int)AppearanceManager.BakeTypeToAgentTextureIndex(bakeType); Primitive.TextureEntryFace texture = faceTextures[ftIndex]; // this will be null if there's no such baked texture @@ -502,7 +613,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory UUID avatarID = kvp.Key; long sendTime = kvp.Value; - // m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now); +// m_log.DebugFormat("[AVFACTORY]: Handling queued appearance updates for {0}, update delta to now is {1}", avatarID, sendTime - now); if (sendTime < now) { @@ -548,11 +659,11 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (sp == null) { // This is expected if the user has gone away. - // m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); +// m_log.DebugFormat("[AVFACTORY]: Agent {0} no longer in the scene", agentid); return; } - // m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); +// m_log.DebugFormat("[AVFACTORY]: Saving appearance for avatar {0}", agentid); // This could take awhile since it needs to pull inventory // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape @@ -579,26 +690,70 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) { IInventoryService invService = m_scene.InventoryService; - + bool resetwearable = false; if (invService.GetRootFolder(userID) != null) { for (int i = 0; i < AvatarWearable.MAX_WEARABLES; i++) { for (int j = 0; j < appearance.Wearables[i].Count; j++) { + // Check if the default wearables are not set if (appearance.Wearables[i][j].ItemID == UUID.Zero) - continue; + { + switch ((WearableType) i) + { + case WearableType.Eyes: + case WearableType.Hair: + case WearableType.Shape: + case WearableType.Skin: + //case WearableType.Underpants: + TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); + resetwearable = true; + m_log.Warn("[AVFACTORY]: UUID.Zero Wearables, passing fake values."); + resetwearable = true; + break; - // Ignore ruth's assets + } + continue; + } + + // Ignore ruth's assets except for the body parts! missing body parts fail avatar appearance on V1 if (appearance.Wearables[i][j].ItemID == AvatarWearable.DefaultWearables[i][0].ItemID) - continue; + { + switch ((WearableType)i) + { + case WearableType.Eyes: + case WearableType.Hair: + case WearableType.Shape: + case WearableType.Skin: + //case WearableType.Underpants: + TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); + + m_log.WarnFormat("[AVFACTORY]: {0} Default Wearables, passing existing values.", (WearableType)i); + resetwearable = true; + break; + } + continue; + } + InventoryItemBase baseItem = new InventoryItemBase(appearance.Wearables[i][j].ItemID, userID); baseItem = invService.GetItem(baseItem); if (baseItem != null) { appearance.Wearables[i].Add(appearance.Wearables[i][j].ItemID, baseItem.AssetID); + int unmodifiedWearableIndexForClosure = i; + m_scene.AssetService.Get(baseItem.AssetID.ToString(), this, + delegate(string x, object y, AssetBase z) + { + if (z == null) + { + TryAndRepairBrokenWearable( + (WearableType)unmodifiedWearableIndexForClosure, invService, + userID, appearance); + } + }); } else { @@ -606,17 +761,236 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory "[AVFACTORY]: Can't find inventory item {0} for {1}, setting to default", appearance.Wearables[i][j].ItemID, (WearableType)i); - appearance.Wearables[i].RemoveItem(appearance.Wearables[i][j].ItemID); + TryAndRepairBrokenWearable((WearableType)i, invService, userID, appearance); + resetwearable = true; + } } } + + // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... + if (appearance.Wearables[(int) WearableType.Eyes] == null) + { + m_log.WarnFormat("[AVFACTORY]: {0} Eyes are Null, passing existing values.", (WearableType.Eyes)); + + TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); + resetwearable = true; + } + else + { + if (appearance.Wearables[(int) WearableType.Eyes][0].ItemID == UUID.Zero) + { + m_log.WarnFormat("[AVFACTORY]: Eyes are UUID.Zero are broken, {0} {1}", + appearance.Wearables[(int) WearableType.Eyes][0].ItemID, + appearance.Wearables[(int) WearableType.Eyes][0].AssetID); + TryAndRepairBrokenWearable(WearableType.Eyes, invService, userID, appearance); + resetwearable = true; + + } + + } + // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... + if (appearance.Wearables[(int)WearableType.Shape] == null) + { + m_log.WarnFormat("[AVFACTORY]: {0} shape is Null, passing existing values.", (WearableType.Shape)); + + TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); + resetwearable = true; + } + else + { + if (appearance.Wearables[(int)WearableType.Shape][0].ItemID == UUID.Zero) + { + m_log.WarnFormat("[AVFACTORY]: Shape is UUID.Zero and broken, {0} {1}", + appearance.Wearables[(int)WearableType.Shape][0].ItemID, + appearance.Wearables[(int)WearableType.Shape][0].AssetID); + TryAndRepairBrokenWearable(WearableType.Shape, invService, userID, appearance); + resetwearable = true; + + } + + } + // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... + if (appearance.Wearables[(int)WearableType.Hair] == null) + { + m_log.WarnFormat("[AVFACTORY]: {0} Hair is Null, passing existing values.", (WearableType.Hair)); + + TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); + resetwearable = true; + } + else + { + if (appearance.Wearables[(int)WearableType.Hair][0].ItemID == UUID.Zero) + { + m_log.WarnFormat("[AVFACTORY]: Hair is UUID.Zero and broken, {0} {1}", + appearance.Wearables[(int)WearableType.Hair][0].ItemID, + appearance.Wearables[(int)WearableType.Hair][0].AssetID); + TryAndRepairBrokenWearable(WearableType.Hair, invService, userID, appearance); + resetwearable = true; + + } + + } + // I don't know why we have to test for this again... but the above switches do not capture these scenarios for some reason.... + if (appearance.Wearables[(int)WearableType.Skin] == null) + { + m_log.WarnFormat("[AVFACTORY]: {0} Skin is Null, passing existing values.", (WearableType.Skin)); + + TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); + resetwearable = true; + } + else + { + if (appearance.Wearables[(int)WearableType.Skin][0].ItemID == UUID.Zero) + { + m_log.WarnFormat("[AVFACTORY]: Skin is UUID.Zero and broken, {0} {1}", + appearance.Wearables[(int)WearableType.Skin][0].ItemID, + appearance.Wearables[(int)WearableType.Skin][0].AssetID); + TryAndRepairBrokenWearable(WearableType.Skin, invService, userID, appearance); + resetwearable = true; + + } + + } + if (resetwearable) + { + ScenePresence presence = null; + if (m_scene.TryGetScenePresence(userID, out presence)) + { + presence.ControllingClient.SendWearables(presence.Appearance.Wearables, + presence.Appearance.Serial++); + } + } + } else { m_log.WarnFormat("[AVFACTORY]: user {0} has no inventory, appearance isn't going to work", userID); } } + private void TryAndRepairBrokenWearable(WearableType type, IInventoryService invService, UUID userID,AvatarAppearance appearance) + { + UUID defaultwearable = GetDefaultItem(type); + if (defaultwearable != UUID.Zero) + { + UUID newInvItem = UUID.Random(); + InventoryItemBase itembase = new InventoryItemBase(newInvItem, userID) + { + AssetID = + defaultwearable, + AssetType + = + (int) + AssetType + .Bodypart, + CreatorId + = + userID + .ToString + (), + //InvType = (int)InventoryType.Wearable, + Description + = + "Failed Wearable Replacement", + Folder = + invService + .GetFolderForType + (userID, + AssetType + .Bodypart) + .ID, + Flags = (uint) type, + Name = Enum.GetName(typeof (WearableType), type), + BasePermissions = (uint) PermissionMask.Copy, + CurrentPermissions = (uint) PermissionMask.Copy, + EveryOnePermissions = (uint) PermissionMask.Copy, + GroupPermissions = (uint) PermissionMask.Copy, + NextPermissions = (uint) PermissionMask.Copy + }; + invService.AddItem(itembase); + UUID LinkInvItem = UUID.Random(); + itembase = new InventoryItemBase(LinkInvItem, userID) + { + AssetID = + newInvItem, + AssetType + = + (int) + AssetType + .Link, + CreatorId + = + userID + .ToString + (), + InvType = (int) InventoryType.Wearable, + + Description + = + "Failed Wearable Replacement", + Folder = + invService + .GetFolderForType + (userID, + AssetType + .CurrentOutfitFolder) + .ID, + Flags = (uint) type, + Name = Enum.GetName(typeof (WearableType), type), + BasePermissions = (uint) PermissionMask.Copy, + CurrentPermissions = (uint) PermissionMask.Copy, + EveryOnePermissions = (uint) PermissionMask.Copy, + GroupPermissions = (uint) PermissionMask.Copy, + NextPermissions = (uint) PermissionMask.Copy + }; + invService.AddItem(itembase); + appearance.Wearables[(int)type] = new AvatarWearable(newInvItem, GetDefaultItem(type)); + ScenePresence presence = null; + if (m_scene.TryGetScenePresence(userID, out presence)) + { + m_scene.SendInventoryUpdate(presence.ControllingClient, + invService.GetFolderForType(userID, + AssetType + .CurrentOutfitFolder), + false, true); + } + } + } + private UUID GetDefaultItem(WearableType wearable) + { + // These are ruth + UUID ret = UUID.Zero; + switch (wearable) + { + case WearableType.Eyes: + ret = new UUID("4bb6fa4d-1cd2-498a-a84c-95c1a0e745a7"); + break; + case WearableType.Hair: + ret = new UUID("d342e6c0-b9d2-11dc-95ff-0800200c9a66"); + break; + case WearableType.Pants: + ret = new UUID("00000000-38f9-1111-024e-222222111120"); + break; + case WearableType.Shape: + ret = new UUID("66c41e39-38f9-f75a-024e-585989bfab73"); + break; + case WearableType.Shirt: + ret = new UUID("00000000-38f9-1111-024e-222222111110"); + break; + case WearableType.Skin: + ret = new UUID("77c41e39-38f9-f75a-024e-585989bbabbb"); + break; + case WearableType.Undershirt: + ret = new UUID("16499ebb-3208-ec27-2def-481881728f47"); + break; + case WearableType.Underpants: + ret = new UUID("4ac2e9c7-3671-d229-316a-67717730841d"); + break; + } + + return ret; + } #endregion #region Client Event Handlers @@ -626,12 +1000,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// private void Client_OnRequestWearables(IClientAPI client) { - // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); - ScenePresence sp = m_scene.GetScenePresence(client.AgentId); - if (sp != null) - client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); - else - m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); + Util.FireAndForget(delegate(object x) + { + Thread.Sleep(4000); + + // m_log.DebugFormat("[AVFACTORY]: Client_OnRequestWearables called for {0} ({1})", client.Name, client.AgentId); + ScenePresence sp = m_scene.GetScenePresence(client.AgentId); + if (sp != null) + client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); + else + m_log.WarnFormat("[AVFACTORY]: Client_OnRequestWearables unable to find presence for {0}", client.AgentId); + }); } /// @@ -640,12 +1019,12 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// /// /// - private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, List hashes) + private void Client_OnSetAppearance(IClientAPI client, Primitive.TextureEntry textureEntry, byte[] visualParams, Vector3 avSize, WearableCacheItem[] cacheItems) { // m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance called for {0} ({1})", client.Name, client.AgentId); ScenePresence sp = m_scene.GetScenePresence(client.AgentId); if (sp != null) - DoSetAppearance(sp, textureEntry, visualParams, hashes); + SetAppearance(sp, textureEntry, visualParams,avSize, cacheItems); else m_log.WarnFormat("[AVFACTORY]: Client_OnSetAppearance unable to find presence for {0}", client.AgentId); } @@ -702,7 +1081,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory /// private void Client_OnCachedTextureRequest(IClientAPI client, int serial, List cachedTextureRequest) { - // m_log.DebugFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId); + // m_log.WarnFormat("[AVFACTORY]: Client_OnCachedTextureRequest called for {0} ({1})", client.Name, client.AgentId); ScenePresence sp = m_scene.GetScenePresence(client.AgentId); List cachedTextureResponse = new List(); @@ -713,20 +1092,23 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory if (m_reusetextures) { - if (sp.Appearance.GetTextureHash(index) == request.WearableHashID) - { - Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index]; - if (face != null) - texture = face.TextureID; - } - else - { - // We know that that hash is wrong, null it out - // and wait for the setappearance call - sp.Appearance.SetTextureHash(index,UUID.Zero); - } + // this is the most insanely dumb way to do this... however it seems to + // actually work. if the appearance has been reset because wearables have + // changed then the texture entries are zero'd out until the bakes are + // uploaded. on login, if the textures exist in the cache (eg if you logged + // into the simulator recently, then the appearance will pull those and send + // them back in the packet and you won't have to rebake. if the textures aren't + // in the cache then the intial makeroot() call in scenepresence will zero + // them out. + // + // a better solution (though how much better is an open question) is to + // store the hashes in the appearance and compare them. Thats's coming. - // m_log.WarnFormat("[AVFACTORY]: use texture {0} for index {1}; hash={2}",texture,index,request.WearableHashID); + Primitive.TextureEntryFace face = sp.Appearance.Texture.FaceTextures[index]; + if (face != null) + texture = face.TextureID; + + // m_log.WarnFormat("[AVFACTORY]: reuse texture {0} for index {1}",texture,index); } CachedTextureResponseArg response = new CachedTextureResponseArg(); diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs index 1830d41880..ff4c6c9972 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/Tests/AvatarFactoryModuleTests.cs @@ -61,10 +61,10 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory for (byte i = 0; i < visualParams.Length; i++) visualParams[i] = i; - afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams); +// afm.SetAppearance(sp, new Primitive.TextureEntry(TestHelpers.ParseTail(0x10)), visualParams); // TODO: Check baked texture - Assert.AreEqual(visualParams, sp.Appearance.VisualParams); +// Assert.AreEqual(visualParams, sp.Appearance.VisualParams); } [Test] @@ -102,6 +102,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory Primitive.TextureEntryFace eyesFace = bakedTextureEntry.CreateFace(eyesFaceIndex); eyesFace.TextureID = eyesTextureId; +/* afm.SetAppearance(sp, bakedTextureEntry, visualParams); afm.SaveBakedTextures(userId); // Dictionary bakedTextures = afm.GetBakedTextureFaces(userId); @@ -113,6 +114,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory Assert.That(eyesBake, Is.Not.Null); Assert.That(eyesBake.Temporary, Is.False); Assert.That(eyesBake.Local, Is.False); +*/ } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index e55c9ed87f..e54c849535 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -414,6 +414,19 @@ namespace OpenSim.Region.CoreModules.World.Land return false; } + public bool CanBeOnThisLand(UUID avatar, float posHeight) + { + if (posHeight < LandChannel.BAN_LINE_SAFETY_HIEGHT && IsBannedFromLand(avatar)) + { + return false; + } + else if (IsRestrictedFromLand(avatar)) + { + return false; + } + return true; + } + public bool HasGroupAccess(UUID avatar) { if (LandData.GroupID != UUID.Zero && (LandData.Flags & (uint)ParcelFlags.UseAccessGroup) == (uint)ParcelFlags.UseAccessGroup) diff --git a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs index 34aca33349..d25c930d8b 100644 --- a/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAvatarFactoryModule.cs @@ -35,8 +35,8 @@ namespace OpenSim.Region.Framework.Interfaces public interface IAvatarFactoryModule { - void SetAppearance(IScenePresence sp, AvatarAppearance appearance); - void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams); + void SetAppearance(IScenePresence sp, AvatarAppearance appearance, WearableCacheItem[] cacheItems); + void SetAppearance(IScenePresence sp, Primitive.TextureEntry textureEntry, byte[] visualParams, WearableCacheItem[] cacheItems); /// /// Send the appearance of an avatar to others in the scene. @@ -52,6 +52,8 @@ namespace OpenSim.Region.Framework.Interfaces /// An empty list if this agent has no baked textures (e.g. because it's a child agent) Dictionary GetBakedTextureFaces(UUID agentId); + + WearableCacheItem[] GetCachedItems(UUID agentId); /// /// Save the baked textures for the given agent permanently in the asset database. /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 4b4e4ba9c6..f16a8e6e2f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -118,6 +118,7 @@ namespace OpenSim.Region.Framework.Scenes private bool m_hasGroupChanged = false; private long timeFirstChanged; private long timeLastChanged; + private List m_linkedAvatars = new List(); /// /// This indicates whether the object has changed such that it needs to be repersisted to permenant storage @@ -1096,6 +1097,7 @@ namespace OpenSim.Region.Framework.Scenes } } + /// /// /// @@ -1105,6 +1107,46 @@ namespace OpenSim.Region.Framework.Scenes part.ParentID = m_rootPart.LocalId; part.ClearUndoState(); } + /// + /// Add the avatar to this linkset (avatar is sat). + /// + /// + public void AddAvatar(UUID agentID) + { + ScenePresence presence; + if (m_scene.TryGetScenePresence(agentID, out presence)) + { + if (!m_linkedAvatars.Contains(presence)) + { + m_linkedAvatars.Add(presence); + } + } + } + + /// + /// Delete the avatar from this linkset (avatar is unsat). + /// + /// + public void DeleteAvatar(UUID agentID) + { + ScenePresence presence; + if (m_scene.TryGetScenePresence(agentID, out presence)) + { + if (m_linkedAvatars.Contains(presence)) + { + m_linkedAvatars.Remove(presence); + } + } + } + + /// + /// Returns the list of linked presences (avatars sat on this group) + /// + /// + public List GetLinkedAvatars() + { + return m_linkedAvatars; + } public ushort GetTimeDilation() { diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 7ed3a4b113..edb8ca8a2c 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -65,6 +65,7 @@ namespace OpenSim.Region.Framework.Scenes struct ScriptControllers { + public UUID objectID; public UUID itemID; public ScriptControlled ignoreControls; public ScriptControlled eventControls; @@ -120,7 +121,7 @@ namespace OpenSim.Region.Framework.Scenes /// rotation, prim cut, prim twist, prim taper, and prim shear. See mantis /// issue #1716 /// - public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.418f); + public static readonly Vector3 SIT_TARGET_ADJUSTMENT = new Vector3(0.0f, 0.0f, 0.4f); /// /// Movement updates for agents in neighboring regions are sent directly to clients. @@ -142,8 +143,6 @@ namespace OpenSim.Region.Framework.Scenes /// /// TODO: For some reason, we effectively have a list both here and in Appearance. Need to work out if this is /// necessary. - /// NOTE: To avoid deadlocks, do not lock m_attachments and then perform other tasks under that lock. Take a copy - /// of the list and act on that instead. /// private List m_attachments = new List(); @@ -162,6 +161,10 @@ namespace OpenSim.Region.Framework.Scenes private Vector3 m_lastPosition; private Quaternion m_lastRotation; private Vector3 m_lastVelocity; + private Vector3 m_lastSize = new Vector3(0.45f,0.6f,1.9f); + + private bool m_followCamAuto = false; + private Vector3? m_forceToApply; private int m_userFlags; @@ -194,6 +197,7 @@ namespace OpenSim.Region.Framework.Scenes // private int m_lastColCount = -1; //KF: Look for Collision chnages // private int m_updateCount = 0; //KF: Update Anims for a while // private static readonly int UPDATE_COUNT = 10; // how many frames to update for + private List m_lastColliders = new List(); private TeleportFlags m_teleportFlags; public TeleportFlags TeleportFlags @@ -249,8 +253,6 @@ namespace OpenSim.Region.Framework.Scenes /// public bool LandAtTarget { get; private set; } - private bool m_followCamAuto; - private int m_movementUpdateCount; private const int NumMovementsBetweenRayCast = 5; @@ -258,6 +260,13 @@ namespace OpenSim.Region.Framework.Scenes //private int m_moveToPositionStateStatus; //***************************************************** + private bool m_collisionEventFlag = false; + private object m_collisionEventLock = new Object(); + + private int m_movementAnimationUpdateCounter = 0; + + public Vector3 PrevSitOffset { get; set; } + protected AvatarAppearance m_appearance; public AvatarAppearance Appearance @@ -397,6 +406,9 @@ namespace OpenSim.Region.Framework.Scenes /// protected Vector3 m_lastCameraPosition; + private Vector4 m_lastCameraCollisionPlane = new Vector4(0f, 0f, 0f, 1); + private bool m_doingCamRayCast = false; + public Vector3 CameraPosition { get; set; } public Quaternion CameraRotation @@ -477,6 +489,10 @@ namespace OpenSim.Region.Framework.Scenes get { return (IClientCore)ControllingClient; } } + public UUID COF { get; set; } + +// public Vector3 ParentPosition { get; set; } + /// /// Position of this avatar relative to the region the avatar is in /// @@ -603,7 +619,24 @@ namespace OpenSim.Region.Framework.Scenes // Scene.RegionInfo.RegionName, Name, m_velocity); } } +/* + public override Vector3 AngularVelocity + { + get + { + if (PhysicsActor != null) + { + m_rotationalvelocity = PhysicsActor.RotationalVelocity; + // m_log.DebugFormat( + // "[SCENE PRESENCE]: Set velocity {0} for {1} in {2} via getting Velocity!", + // m_velocity, Name, Scene.RegionInfo.RegionName); + } + + return m_rotationalvelocity; + } + } +*/ private Quaternion m_bodyRot = Quaternion.Identity; /// @@ -626,8 +659,16 @@ namespace OpenSim.Region.Framework.Scenes m_bodyRot = value; if (PhysicsActor != null) - PhysicsActor.Orientation = m_bodyRot; - + { + try + { + PhysicsActor.Orientation = m_bodyRot; + } + catch (Exception e) + { + m_log.Error("[SCENE PRESENCE]: Orientation " + e.Message); + } + } // m_log.DebugFormat("[SCENE PRESENCE]: Body rot for {0} set to {1}", Name, m_bodyRot); } } @@ -641,12 +682,20 @@ namespace OpenSim.Region.Framework.Scenes } public bool IsChildAgent { get; set; } + public bool IsLoggingIn { get; set; } /// /// If the avatar is sitting, the local ID of the prim that it's sitting on. If not sitting then zero. /// public uint ParentID { get; set; } + public UUID ParentUUID + { + get { return m_parentUUID; } + set { m_parentUUID = value; } + } + private UUID m_parentUUID = UUID.Zero; + /// /// Are we sitting on an object? /// @@ -804,6 +853,7 @@ namespace OpenSim.Region.Framework.Scenes AttachmentsSyncLock = new Object(); AllowMovement = true; IsChildAgent = true; + IsLoggingIn = false; m_sendCoarseLocationsMethod = SendCoarseLocationsDefault; Animator = new ScenePresenceAnimator(this); PresenceType = type; @@ -849,6 +899,33 @@ namespace OpenSim.Region.Framework.Scenes m_stateMachine = new ScenePresenceStateMachine(this); } + private void RegionHeartbeatEnd(Scene scene) + { + if (IsChildAgent) + return; + + m_movementAnimationUpdateCounter ++; + if (m_movementAnimationUpdateCounter >= 2) + { + m_movementAnimationUpdateCounter = 0; + if (Animator != null) + { + // If the parentID == 0 we are not sitting + // if !SitGournd then we are not sitting on the ground + // Fairly straightforward, now here comes the twist + // if ParentUUID is NOT UUID.Zero, we are looking to + // be sat on an object that isn't there yet. Should + // be treated as if sat. + if(ParentID == 0 && !SitGround && ParentUUID == UUID.Zero) // skip it if sitting + Animator.UpdateMovementAnimations(); + } + else + { + m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; + } + } + } + public void RegisterToEvents() { ControllingClient.OnCompleteMovementToRegion += CompleteMovement; @@ -919,6 +996,38 @@ namespace OpenSim.Region.Framework.Scenes // "[SCENE]: Upgrading child to root agent for {0} in {1}", // Name, m_scene.RegionInfo.RegionName); + if (ParentUUID != UUID.Zero) + { + m_log.DebugFormat("[SCENE PRESENCE]: Sitting avatar back on prim {0}", ParentUUID); + SceneObjectPart part = m_scene.GetSceneObjectPart(ParentUUID); + if (part == null) + { + m_log.ErrorFormat("[SCENE PRESENCE]: Can't find prim {0} to sit on", ParentUUID); + } + else + { + part.ParentGroup.AddAvatar(UUID); + if (part.SitTargetPosition != Vector3.Zero) + part.SitTargetAvatar = UUID; +// ParentPosition = part.GetWorldPosition(); + ParentID = part.LocalId; + ParentPart = part; + m_pos = PrevSitOffset; +// pos = ParentPosition; + pos = part.GetWorldPosition(); + } + ParentUUID = UUID.Zero; + + IsChildAgent = false; + +// Animator.TrySetMovementAnimation("SIT"); + } + else + { + IsChildAgent = false; + IsLoggingIn = false; + } + //m_log.DebugFormat("[SCENE]: known regions in {0}: {1}", Scene.RegionInfo.RegionName, KnownChildRegionHandles.Count); IsChildAgent = false; @@ -936,70 +1045,106 @@ namespace OpenSim.Region.Framework.Scenes m_scene.EventManager.TriggerSetRootAgentScene(m_uuid, m_scene); - // Moved this from SendInitialData to ensure that Appearance is initialized - // before the inventory is processed in MakeRootAgent. This fixes a race condition - // related to the handling of attachments - //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); + UUID groupUUID = UUID.Zero; + string GroupName = string.Empty; + ulong groupPowers = 0; - if (m_scene.TestBorderCross(pos, Cardinals.E)) + // ---------------------------------- + // Previous Agent Difference - AGNI sends an unsolicited AgentDataUpdate upon root agent status + try { - Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); - pos.X = crossedBorder.BorderLine.Z - 1; + if (gm != null) + { + groupUUID = ControllingClient.ActiveGroupId; + GroupRecord record = gm.GetGroupRecord(groupUUID); + if (record != null) + GroupName = record.GroupName; + GroupMembershipData groupMembershipData = gm.GetMembershipData(groupUUID, m_uuid); + if (groupMembershipData != null) + groupPowers = groupMembershipData.GroupPowers; + } + ControllingClient.SendAgentDataUpdate(m_uuid, groupUUID, Firstname, Lastname, groupPowers, GroupName, + Grouptitle); } - - if (m_scene.TestBorderCross(pos, Cardinals.N)) + catch (Exception e) { - Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); - pos.Y = crossedBorder.BorderLine.Z - 1; + m_log.Debug("[AGENTUPDATE]: " + e.ToString()); } + // ------------------------------------ - CheckAndAdjustLandingPoint(ref pos); - - if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) + if (ParentID == 0) { - m_log.WarnFormat( - "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", - pos, Name, UUID); + // Moved this from SendInitialData to ensure that Appearance is initialized + // before the inventory is processed in MakeRootAgent. This fixes a race condition + // related to the handling of attachments + //m_scene.GetAvatarAppearance(ControllingClient, out Appearance); + if (m_scene.TestBorderCross(pos, Cardinals.E)) + { + Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.E); + pos.X = crossedBorder.BorderLine.Z - 1; + } - if (pos.X < 0f) pos.X = 0f; - if (pos.Y < 0f) pos.Y = 0f; - if (pos.Z < 0f) pos.Z = 0f; + if (m_scene.TestBorderCross(pos, Cardinals.N)) + { + Border crossedBorder = m_scene.GetCrossedBorder(pos, Cardinals.N); + pos.Y = crossedBorder.BorderLine.Z - 1; + } + + CheckAndAdjustLandingPoint(ref pos); + + if (pos.X < 0f || pos.Y < 0f || pos.Z < 0f) + { + m_log.WarnFormat( + "[SCENE PRESENCE]: MakeRootAgent() was given an illegal position of {0} for avatar {1}, {2}. Clamping", + pos, Name, UUID); + + if (pos.X < 0f) pos.X = 0f; + if (pos.Y < 0f) pos.Y = 0f; + if (pos.Z < 0f) pos.Z = 0f; + } + + float localAVHeight = 1.56f; + if (Appearance.AvatarHeight > 0) + localAVHeight = Appearance.AvatarHeight; + + float posZLimit = 0; + + if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) + posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; + + float newPosZ = posZLimit + localAVHeight / 2; + if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) + { + pos.Z = newPosZ; + } + AbsolutePosition = pos; + + if (m_teleportFlags == TeleportFlags.Default) + { + Vector3 vel = Velocity; + AddToPhysicalScene(isFlying); + if (PhysicsActor != null) + PhysicsActor.SetMomentum(vel); + } + else + AddToPhysicalScene(isFlying); + + // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a + // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it + // since it requires a physics actor to be present. If it is left any later, then physics appears to reset + // the value to a negative position which does not trigger the border cross. + // This may not be the best location for this. + CheckForBorderCrossing(); + + if (ForceFly) + { + Flying = true; + } + else if (FlyDisabled) + { + Flying = false; + } } - - float localAVHeight = 1.56f; - if (Appearance.AvatarHeight > 0) - localAVHeight = Appearance.AvatarHeight; - - float posZLimit = 0; - - if (pos.X < Constants.RegionSize && pos.Y < Constants.RegionSize) - posZLimit = (float)m_scene.Heightmap[(int)pos.X, (int)pos.Y]; - - float newPosZ = posZLimit + localAVHeight / 2; - if (posZLimit >= (pos.Z - (localAVHeight / 2)) && !(Single.IsInfinity(newPosZ) || Single.IsNaN(newPosZ))) - { - pos.Z = newPosZ; - } - AbsolutePosition = pos; - - AddToPhysicalScene(isFlying); - - // XXX: This is to trigger any secondary teleport needed for a megaregion when the user has teleported to a - // location outside the 'root region' (the south-west 256x256 corner). This is the earlist we can do it - // since it requires a physics actor to be present. If it is left any later, then physics appears to reset - // the value to a negative position which does not trigger the border cross. - // This may not be the best location for this. - CheckForBorderCrossing(); - - if (ForceFly) - { - Flying = true; - } - else if (FlyDisabled) - { - Flying = false; - } - // Don't send an animation pack here, since on a region crossing this will sometimes cause a flying // avatar to return to the standing position in mid-air. On login it looks like this is being sent // elsewhere anyway @@ -1031,31 +1176,28 @@ namespace OpenSim.Region.Framework.Scenes // and CHANGED_REGION) when the attachments have been rezzed in the new region. This cannot currently // be done in AttachmentsModule.CopyAttachments(AgentData ad, IScenePresence sp) itself since we are // not transporting the required data. - // - // We must take a copy of the attachments list here (rather than locking) to avoid a deadlock where a script in one of - // the attachments may start processing an event (which locks ScriptInstance.m_Script) that then calls a method here - // which needs to lock m_attachments. ResumeScripts() needs to take a ScriptInstance.m_Script lock to try to unset the Suspend status. - // - // FIXME: In theory, this deadlock should not arise since scripts should not be processing events until ResumeScripts(). - // But XEngine starts all scripts unsuspended. Starting them suspended will not currently work because script rezzing - // is placed in an asynchronous queue in XEngine and so the ResumeScripts() call will almost certainly execute before the - // script is rezzed. This means the ResumeScripts() does absolutely nothing when using XEngine. - List attachments = GetAttachments(); - - if (attachments.Count > 0) + lock (m_attachments) { - m_log.DebugFormat( - "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); - - // Resume scripts - foreach (SceneObjectGroup sog in attachments) + if (HasAttachments()) { - sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); - sog.ResumeScripts(); + m_log.DebugFormat( + "[SCENE PRESENCE]: Restarting scripts in attachments for {0} in {1}", Name, Scene.Name); + + // Resume scripts + Util.FireAndForget(delegate(object x) { + foreach (SceneObjectGroup sog in m_attachments) + { + sog.ScheduleGroupForFullUpdate(); + sog.RootPart.ParentGroup.CreateScriptInstances(0, false, m_scene.DefaultScriptEngine, GetStateSource()); + sog.ResumeScripts(); + } + }); } } } + SendAvatarDataToAllAgents(); + // send the animations of the other presences to me m_scene.ForEachRootScenePresence(delegate(ScenePresence presence) { @@ -1066,6 +1208,7 @@ namespace OpenSim.Region.Framework.Scenes // If we don't reset the movement flag here, an avatar that crosses to a neighbouring sim and returns will // stall on the border crossing since the existing child agent will still have the last movement // recorded, which stops the input from being processed. + MovementFlag = 0; m_scene.EventManager.TriggerOnMakeRootAgent(this); @@ -1097,12 +1240,16 @@ namespace OpenSim.Region.Framework.Scenes /// public void MakeChildAgent() { + m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; + m_log.DebugFormat("[SCENE PRESENCE]: Making {0} a child agent in {1}", Name, Scene.RegionInfo.RegionName); // Reset these so that teleporting in and walking out isn't seen // as teleporting back TeleportFlags = TeleportFlags.Default; + MovementFlag = 0; + // It looks like Animator is set to null somewhere, and MakeChild // is called after that. Probably in aborted teleports. if (Animator == null) @@ -1110,6 +1257,7 @@ namespace OpenSim.Region.Framework.Scenes else Animator.ResetAnimations(); + // m_log.DebugFormat( // "[SCENE PRESENCE]: Downgrading root agent {0}, {1} to a child agent in {2}", // Name, UUID, m_scene.RegionInfo.RegionName); @@ -1121,6 +1269,7 @@ namespace OpenSim.Region.Framework.Scenes IsChildAgent = true; m_scene.SwapRootAgentCount(true); RemoveFromPhysicalScene(); + ParentID = 0; // Child agents can't be sitting // FIXME: Set RegionHandle to the region handle of the scene this agent is moving into @@ -1136,9 +1285,9 @@ namespace OpenSim.Region.Framework.Scenes { // PhysicsActor.OnRequestTerseUpdate -= SendTerseUpdateToAllClients; PhysicsActor.OnOutOfBounds -= OutOfBoundsCall; - m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); - PhysicsActor.UnSubscribeEvents(); PhysicsActor.OnCollisionUpdate -= PhysicsCollisionUpdate; + PhysicsActor.UnSubscribeEvents(); + m_scene.PhysicsScene.RemoveAvatar(PhysicsActor); PhysicsActor = null; } // else @@ -1155,7 +1304,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void Teleport(Vector3 pos) { - TeleportWithMomentum(pos, null); + TeleportWithMomentum(pos, Vector3.Zero); } public void TeleportWithMomentum(Vector3 pos, Vector3? v) @@ -1179,6 +1328,41 @@ namespace OpenSim.Region.Framework.Scenes SendTerseUpdateToAllClients(); } + public void avnLocalTeleport(Vector3 newpos, Vector3? newvel, bool rotateToVelXY) + { + CheckLandingPoint(ref newpos); + AbsolutePosition = newpos; + + if (newvel.HasValue) + { + if ((Vector3)newvel == Vector3.Zero) + { + if (PhysicsActor != null) + PhysicsActor.SetMomentum(Vector3.Zero); + m_velocity = Vector3.Zero; + } + else + { + if (PhysicsActor != null) + PhysicsActor.SetMomentum((Vector3)newvel); + m_velocity = (Vector3)newvel; + + if (rotateToVelXY) + { + Vector3 lookAt = (Vector3)newvel; + lookAt.Z = 0; + lookAt.Normalize(); + ControllingClient.SendLocalTeleport(newpos, lookAt, (uint)TeleportFlags.ViaLocation); + return; + } + } + } + + SendTerseUpdateToAllClients(); + } + + + public void StopFlying() { Vector3 pos = AbsolutePosition; @@ -1367,6 +1551,14 @@ namespace OpenSim.Region.Framework.Scenes PhysicsActor.Size = new Vector3(0.45f, 0.6f, height); } + public void SetSize(Vector3 size, float feetoffset) + { +// TODO: Merge the physics bits +// if (PhysicsActor != null && !IsChildAgent) +// PhysicsActor.setAvatarSize(size, feetoffset); + + } + private bool WaitForUpdateAgent(IClientAPI client) { // Before the source region executes UpdateAgent @@ -1426,7 +1618,8 @@ namespace OpenSim.Region.Framework.Scenes Vector3 look = Velocity; - if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) + // if ((look.X == 0) && (look.Y == 0) && (look.Z == 0)) + if ((Math.Abs(look.X) < 0.1) && (Math.Abs(look.Y) < 0.1) && (Math.Abs(look.Z) < 0.1)) { look = new Vector3(0.99f, 0.042f, 0); } @@ -1489,11 +1682,12 @@ namespace OpenSim.Region.Framework.Scenes { IEntityTransferModule m_agentTransfer = m_scene.RequestModuleInterface(); if (m_agentTransfer != null) - Util.FireAndForget(delegate { m_agentTransfer.EnableChildAgents(this); }); + m_agentTransfer.EnableChildAgents(this); IFriendsModule friendsModule = m_scene.RequestModuleInterface(); if (friendsModule != null) friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); + } // XXX: If we force an update here, then multiple attachments do appear correctly on a destination region @@ -1519,36 +1713,69 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// + /// + + private void UpdateCameraCollisionPlane(Vector4 plane) + { + if (m_lastCameraCollisionPlane != plane) + { + m_lastCameraCollisionPlane = plane; + ControllingClient.SendCameraConstraint(plane); + } + } + public void RayCastCameraCallback(bool hitYN, Vector3 collisionPoint, uint localid, float distance, Vector3 pNormal) { const float POSITION_TOLERANCE = 0.02f; - const float VELOCITY_TOLERANCE = 0.02f; const float ROTATION_TOLERANCE = 0.02f; - if (m_followCamAuto) + m_doingCamRayCast = false; + if (hitYN && localid != LocalId) { - if (hitYN) + SceneObjectGroup group = m_scene.GetGroupByPrim(localid); + bool IsPrim = group != null; + if (IsPrim) { - CameraConstraintActive = true; - //m_log.DebugFormat("[RAYCASTRESULT]: {0}, {1}, {2}, {3}", hitYN, collisionPoint, localid, distance); - - Vector3 normal = Vector3.Normalize(new Vector3(0f, 0f, collisionPoint.Z) - collisionPoint); - ControllingClient.SendCameraConstraint(new Vector4(normal.X, normal.Y, normal.Z, -1 * Vector3.Distance(new Vector3(0,0,collisionPoint.Z),collisionPoint))); + SceneObjectPart part = group.GetPart(localid); + if (part != null && !part.VolumeDetectActive) + { + CameraConstraintActive = true; + pNormal.X = (float) Math.Round(pNormal.X, 2); + pNormal.Y = (float) Math.Round(pNormal.Y, 2); + pNormal.Z = (float) Math.Round(pNormal.Z, 2); + pNormal.Normalize(); + collisionPoint.X = (float) Math.Round(collisionPoint.X, 1); + collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1); + collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1); + + Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z, + Vector3.Dot(collisionPoint, pNormal)); + UpdateCameraCollisionPlane(plane); + } } else { - if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || - !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || - !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) - { - if (CameraConstraintActive) - { - ControllingClient.SendCameraConstraint(new Vector4(0f, 0.5f, 0.9f, -3000f)); - CameraConstraintActive = false; - } - } + CameraConstraintActive = true; + pNormal.X = (float) Math.Round(pNormal.X, 2); + pNormal.Y = (float) Math.Round(pNormal.Y, 2); + pNormal.Z = (float) Math.Round(pNormal.Z, 2); + pNormal.Normalize(); + collisionPoint.X = (float) Math.Round(collisionPoint.X, 1); + collisionPoint.Y = (float) Math.Round(collisionPoint.Y, 1); + collisionPoint.Z = (float) Math.Round(collisionPoint.Z, 1); + + Vector4 plane = new Vector4(pNormal.X, pNormal.Y, pNormal.Z, + Vector3.Dot(collisionPoint, pNormal)); + UpdateCameraCollisionPlane(plane); } } + else if (!m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE) || + !Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE)) + { + Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -9000f); // not right... + UpdateCameraCollisionPlane(plane); + CameraConstraintActive = false; + } } /// @@ -1622,6 +1849,41 @@ namespace OpenSim.Region.Framework.Scenes StandUp(); } + // Raycast from the avatar's head to the camera to see if there's anything blocking the view + // this exclude checks may not be complete + + if (m_movementUpdateCount % NumMovementsBetweenRayCast == 0 && m_scene.PhysicsScene.SupportsRayCast()) + { + if (!m_doingCamRayCast && !m_mouseLook && ParentID == 0) + { + Vector3 posAdjusted = AbsolutePosition; +// posAdjusted.Z += 0.5f * Appearance.AvatarSize.Z - 0.5f; + posAdjusted.Z += 1.0f; // viewer current camera focus point + Vector3 tocam = CameraPosition - posAdjusted; + tocam.X = (float)Math.Round(tocam.X, 1); + tocam.Y = (float)Math.Round(tocam.Y, 1); + tocam.Z = (float)Math.Round(tocam.Z, 1); + + float distTocamlen = tocam.Length(); + if (distTocamlen > 0.3f) + { + tocam *= (1.0f / distTocamlen); + posAdjusted.X = (float)Math.Round(posAdjusted.X, 1); + posAdjusted.Y = (float)Math.Round(posAdjusted.Y, 1); + posAdjusted.Z = (float)Math.Round(posAdjusted.Z, 1); + + m_doingCamRayCast = true; + m_scene.PhysicsScene.RaycastWorld(posAdjusted, tocam, distTocamlen + 1.0f, RayCastCameraCallback); + } + } + else if (CameraConstraintActive && (m_mouseLook || ParentID != 0)) + { + Vector4 plane = new Vector4(0.9f, 0.0f, 0.361f, -10000f); // not right... + UpdateCameraCollisionPlane(plane); + CameraConstraintActive = false; + } + } + uint flagsForScripts = (uint)flags; flags = RemoveIgnoredControls(flags, IgnoredControls); @@ -2180,7 +2442,8 @@ namespace OpenSim.Region.Framework.Scenes // m_log.DebugFormat("[SCENE PRESENCE]: Resetting move to target for {0}", Name); MovingToTarget = false; - MoveToPositionTarget = Vector3.Zero; +// MoveToPositionTarget = Vector3.Zero; + m_forceToApply = null; // cancel possible last action // We need to reset the control flag as the ScenePresenceAnimator uses this to determine the correct // resting animation (e.g. hover or stand). NPCs don't have a client that will quickly reset this flag. @@ -2203,6 +2466,9 @@ namespace OpenSim.Region.Framework.Scenes if (satOnObject) { + PrevSitOffset = m_pos; // Save sit offset + UnRegisterSeatControls(part.ParentGroup.UUID); + TaskInventoryDictionary taskIDict = part.TaskInventory; if (taskIDict != null) { @@ -2218,6 +2484,7 @@ namespace OpenSim.Region.Framework.Scenes } } + part.ParentGroup.DeleteAvatar(UUID); Vector3 sitPartWorldPosition = part.GetWorldPosition(); ControllingClient.SendClearFollowCamProperties(part.ParentUUID); @@ -2278,6 +2545,9 @@ namespace OpenSim.Region.Framework.Scenes part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); } + else if (PhysicsActor == null) + AddToPhysicalScene(false); + Animator.TrySetMovementAnimation("STAND"); TriggerScenePresenceUpdated(); } @@ -2326,11 +2596,8 @@ namespace OpenSim.Region.Framework.Scenes if (part == null) return; - // TODO: determine position to sit at based on scene geometry; don't trust offset from client - // see http://wiki.secondlife.com/wiki/User:Andrew_Linden/Office_Hours/2007_11_06 for details on how LL does it - if (PhysicsActor != null) - m_sitAvatarHeight = PhysicsActor.Size.Z; + m_sitAvatarHeight = PhysicsActor.Size.Z * 0.5f; bool canSit = false; @@ -2357,33 +2624,32 @@ namespace OpenSim.Region.Framework.Scenes } else { + if (PhysicsSit(part,offset)) // physics engine + return; + Vector3 pos = part.AbsolutePosition + offset; if (Util.GetDistanceTo(AbsolutePosition, pos) <= 10) { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Sitting {0} on {1} {2} because sit target is unset and within 10m", -// Name, part.Name, part.LocalId); - AbsolutePosition = pos + new Vector3(0.0f, 0.0f, m_sitAvatarHeight); canSit = true; } -// else -// { -// m_log.DebugFormat( -// "[SCENE PRESENCE]: Ignoring sit request of {0} on {1} {2} because sit target is unset and outside 10m", -// Name, part.Name, part.LocalId); -// } } if (canSit) { + if (PhysicsActor != null) { // We can remove the physicsActor until they stand up. RemoveFromPhysicalScene(); } + if (MovingToTarget) + ResetMoveToTarget(); + + Velocity = Vector3.Zero; + part.AddSittingAvatar(UUID); cameraAtOffset = part.GetCameraAtOffset(); @@ -2427,14 +2693,6 @@ namespace OpenSim.Region.Framework.Scenes m_requestedSitTargetID = part.LocalId; m_requestedSitTargetUUID = part.UUID; -// m_log.DebugFormat("[SIT]: Client requested Sit Position: {0}", offset); - - if (m_scene.PhysicsScene.SupportsRayCast()) - { - //m_scene.PhysicsScene.RaycastWorld(Vector3.Zero,Vector3.Zero, 0.01f,new RaycastCallback()); - //SitRayCastAvatarPosition(part); - //return; - } } else { @@ -2444,197 +2702,115 @@ namespace OpenSim.Region.Framework.Scenes SendSitResponse(targetID, offset, Quaternion.Identity); } - /* - public void SitRayCastAvatarPosition(SceneObjectPart part) + // returns false if does not suport so older sit can be tried + public bool PhysicsSit(SceneObjectPart part, Vector3 offset) { - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = AbsolutePosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionResponse); - } - - public void SitRayCastAvatarPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) +// TODO: Pull in these bits + return false; +/* + if (part == null || part.ParentGroup.IsAttachment) { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Avatar Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayCastAvatarPositionCameraZ(part); - } - } + return true; + } + + if ( m_scene.PhysicsScene == null) + return false; + + if (part.PhysActor == null) + { + // none physcis shape + if (part.PhysicsShapeType == (byte)PhysicsShapeType.None) + ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); else - { - SitRayCastAvatarPositionCameraZ(part); + { // non physical phantom TODO + ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); + return false; } + return true; } + + + // not doing autopilot + m_requestedSitTargetID = 0; + + if (m_scene.PhysicsScene.SitAvatar(part.PhysActor, AbsolutePosition, CameraPosition, offset, new Vector3(0.35f, 0, 0.65f), PhysicsSitResponse) != 0) + return true; + + return false; +*/ + } + + + private bool CanEnterLandPosition(Vector3 testPos) + { + ILandObject land = m_scene.LandChannel.GetLandObject(testPos.X, testPos.Y); + + if (land == null || land.LandData.Name == "NO_LAND") + return true; + + return land.CanBeOnThisLand(UUID,testPos.Z); + } + + // status + // < 0 ignore + // 0 bad sit spot + public void PhysicsSitResponse(int status, uint partID, Vector3 offset, Quaternion Orientation) + { + if (status < 0) + return; + + if (status == 0) + { + ControllingClient.SendAlertMessage(" There is no suitable surface to sit on, try another spot."); + return; + } + + SceneObjectPart part = m_scene.GetSceneObjectPart(partID); + if (part == null) + return; + + Vector3 targetPos = part.GetWorldPosition() + offset * part.GetWorldRotation(); + if(!CanEnterLandPosition(targetPos)) + { + ControllingClient.SendAlertMessage(" Sit position on restricted land, try another spot"); + return; + } + + RemoveFromPhysicalScene(); + + if (MovingToTarget) + ResetMoveToTarget(); + + Velocity = Vector3.Zero; + + part.AddSittingAvatar(UUID); + + Vector3 cameraAtOffset = part.GetCameraAtOffset(); + Vector3 cameraEyeOffset = part.GetCameraEyeOffset(); + bool forceMouselook = part.GetForceMouselook(); + + ControllingClient.SendSitResponse( + part.UUID, offset, Orientation, false, cameraAtOffset, cameraEyeOffset, forceMouselook); + + // not using autopilot + + Rotation = Orientation; + m_pos = offset; + + m_requestedSitTargetID = 0; + part.ParentGroup.AddAvatar(UUID); + + ParentPart = part; + ParentID = part.LocalId; + if(status == 3) + Animator.TrySetMovementAnimation("SIT_GROUND"); else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } + Animator.TrySetMovementAnimation("SIT"); + SendAvatarDataToAllAgents(); + part.ParentGroup.TriggerScriptChangedEvent(Changed.LINK); } - public void SitRayCastAvatarPositionCameraZ(SceneObjectPart part) - { - // Next, try to raycast from the camera Z position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = AbsolutePosition; StartRayCastPosition.Z = CameraPosition.Z; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastAvatarPositionCameraZResponse); - } - - public void SitRayCastAvatarPositionCameraZResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Avatar Position + CameraZ succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayCastCameraPosition(part); - } - } - else - { - SitRayCastCameraPosition(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayCastCameraPosition(SceneObjectPart part) - { - // Next, try to raycast from the camera position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastCameraPositionResponse); - } - - public void SitRayCastCameraPositionResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Camera Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - } - else - { - SitRayHorizontal(part); - } - } - else - { - SitRayHorizontal(part); - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - public void SitRayHorizontal(SceneObjectPart part) - { - // Next, try to raycast from the avatar position to fwd - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastHorizontalResponse); - } - - public void SitRayCastHorizontalResponse(bool hitYN, Vector3 collisionPoint, uint localid, float pdistance, Vector3 normal) - { - SceneObjectPart part = FindNextAvailableSitTarget(m_requestedSitTargetUUID); - if (part != null) - { - if (hitYN) - { - if (collisionPoint.ApproxEquals(m_requestedSitOffset + part.AbsolutePosition, 0.2f)) - { - SitRaycastFindEdge(collisionPoint, normal); - m_log.DebugFormat("[SIT]: Raycast Horizontal Position succeeded at point: {0}, normal:{1}", collisionPoint, normal); - // Next, try to raycast from the camera position - Vector3 EndRayCastPosition = part.AbsolutePosition + m_requestedSitOffset; - Vector3 StartRayCastPosition = CameraPosition; - Vector3 direction = Vector3.Normalize(EndRayCastPosition - StartRayCastPosition); - float distance = Vector3.Distance(EndRayCastPosition, StartRayCastPosition); - //m_scene.PhysicsScene.RaycastWorld(StartRayCastPosition, direction, distance, SitRayCastResponseAvatarPosition); - } - else - { - ControllingClient.SendAlertMessage("Sit position not accessable."); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - } - else - { - ControllingClient.SendAlertMessage("Sit position not accessable."); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - } - else - { - ControllingClient.SendAlertMessage("Sit position no longer exists"); - m_requestedSitTargetUUID = UUID.Zero; - m_requestedSitTargetID = 0; - m_requestedSitOffset = Vector3.Zero; - } - - } - - private void SitRaycastFindEdge(Vector3 collisionPoint, Vector3 collisionNormal) - { - int i = 0; - //throw new NotImplementedException(); - //m_requestedSitTargetUUID = UUID.Zero; - //m_requestedSitTargetID = 0; - //m_requestedSitOffset = Vector3.Zero; - - SendSitResponse(ControllingClient, m_requestedSitTargetUUID, collisionPoint - m_requestedSitOffset, Quaternion.Identity); - } - */ public void HandleAgentSit(IClientAPI remoteClient, UUID agentID) { @@ -2654,6 +2830,7 @@ namespace OpenSim.Region.Framework.Scenes return; } + if (part.SitTargetAvatar == UUID) { Vector3 sitTargetPos = part.SitTargetPosition; @@ -2668,29 +2845,39 @@ namespace OpenSim.Region.Framework.Scenes //Quaternion result = (sitTargetOrient * vq) * nq; - Vector3 newPos = sitTargetPos + SIT_TARGET_ADJUSTMENT; - Quaternion newRot; + double x, y, z, m; - if (part.IsRoot) + Quaternion r = sitTargetOrient; + m = r.X * r.X + r.Y * r.Y + r.Z * r.Z + r.W * r.W; + + if (Math.Abs(1.0 - m) > 0.000001) { - newRot = sitTargetOrient; - } - else - { - newPos = newPos * part.RotationOffset; - newRot = part.RotationOffset * sitTargetOrient; + m = 1.0 / Math.Sqrt(m); + r.X *= (float)m; + r.Y *= (float)m; + r.Z *= (float)m; + r.W *= (float)m; } - newPos += part.OffsetPosition; + x = 2 * (r.X * r.Z + r.Y * r.W); + y = 2 * (-r.X * r.W + r.Y * r.Z); + z = -r.X * r.X - r.Y * r.Y + r.Z * r.Z + r.W * r.W; - m_pos = newPos; - Rotation = newRot; + Vector3 up = new Vector3((float)x, (float)y, (float)z); + Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; + + m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; + +// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset; + Rotation = sitTargetOrient; +// ParentPosition = part.AbsolutePosition; + part.ParentGroup.AddAvatar(UUID); } else { - // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is - // being sat upon. - m_pos -= part.GroupPosition; + m_pos -= part.AbsolutePosition; +// ParentPosition = part.AbsolutePosition; + part.ParentGroup.AddAvatar(UUID); // m_log.DebugFormat( // "[SCENE PRESENCE]: Sitting {0} at position {1} ({2} + {3}) on part {4} {5} without sit target", @@ -2807,8 +2994,8 @@ namespace OpenSim.Region.Framework.Scenes direc.Z *= 2.6f; // TODO: PreJump and jump happen too quickly. Many times prejump gets ignored. - Animator.TrySetMovementAnimation("PREJUMP"); - Animator.TrySetMovementAnimation("JUMP"); +// Animator.TrySetMovementAnimation("PREJUMP"); +// Animator.TrySetMovementAnimation("JUMP"); } } } @@ -2817,6 +3004,7 @@ namespace OpenSim.Region.Framework.Scenes // TODO: Add the force instead of only setting it to support multiple forces per frame? m_forceToApply = direc; + Animator.UpdateMovementAnimations(); } #endregion @@ -2834,16 +3022,12 @@ namespace OpenSim.Region.Framework.Scenes // NOTE: Velocity is not the same as m_velocity. Velocity will attempt to // grab the latest PhysicsActor velocity, whereas m_velocity is often // storing a requested force instead of an actual traveling velocity + if (Appearance.AvatarSize != m_lastSize && !IsLoggingIn) + SendAvatarDataToAllAgents(); - // Throw away duplicate or insignificant updates - if ( - // If the velocity has become zero, send it no matter what. - (Velocity != m_lastVelocity && Velocity == Vector3.Zero) - // otherwise, if things have changed reasonably, send the update - || (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) - || !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) - || !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE))) - + if (!Rotation.ApproxEquals(m_lastRotation, ROTATION_TOLERANCE) || + !Velocity.ApproxEquals(m_lastVelocity, VELOCITY_TOLERANCE) || + !m_pos.ApproxEquals(m_lastPosition, POSITION_TOLERANCE)) { SendTerseUpdateToAllClients(); @@ -3003,9 +3187,7 @@ namespace OpenSim.Region.Framework.Scenes // again here... this comes after the cached appearance check because the avatars // appearance goes into the avatar update packet SendAvatarDataToAllAgents(); - - // This invocation always shows up in the viewer logs as an error. - // SendAppearanceToAgent(this); + SendAppearanceToAgent(this); // If we are using the the cached appearance then send it out to everyone if (cachedappearance) @@ -3036,6 +3218,8 @@ namespace OpenSim.Region.Framework.Scenes return; } + m_lastSize = Appearance.AvatarSize; + int count = 0; m_scene.ForEachScenePresence(delegate(ScenePresence scenePresence) { @@ -3143,6 +3327,8 @@ namespace OpenSim.Region.Framework.Scenes avatar.ControllingClient.SendAppearance( UUID, Appearance.VisualParams, Appearance.Texture.GetBytes()); + + } #endregion @@ -3216,8 +3402,9 @@ namespace OpenSim.Region.Framework.Scenes // If we don't have a PhysActor, we can't cross anyway // Also don't do this while sat, sitting avatars cross with the - // object they sit on. - if (ParentID != 0 || PhysicsActor == null) + // object they sit on. ParentUUID denoted a pending sit, don't + // interfere with it. + if (ParentID != 0 || PhysicsActor == null || ParentUUID != UUID.Zero) return; if (!IsInTransit) @@ -3561,6 +3748,9 @@ namespace OpenSim.Region.Framework.Scenes cAgent.AlwaysRun = SetAlwaysRun; cAgent.Appearance = new AvatarAppearance(Appearance); + + cAgent.ParentPart = ParentUUID; + cAgent.SitOffset = PrevSitOffset; lock (scriptedcontrols) { @@ -3569,7 +3759,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (ScriptControllers c in scriptedcontrols.Values) { - controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); + controls[i++] = new ControllerData(c.objectID, c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); } cAgent.Controllers = controls; } @@ -3603,6 +3793,8 @@ namespace OpenSim.Region.Framework.Scenes CameraAtAxis = cAgent.AtAxis; CameraLeftAxis = cAgent.LeftAxis; CameraUpAxis = cAgent.UpAxis; + ParentUUID = cAgent.ParentPart; + PrevSitOffset = cAgent.SitOffset; // When we get to the point of re-computing neighbors everytime this // changes, then start using the agent's drawdistance rather than the @@ -3640,6 +3832,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (ControllerData c in cAgent.Controllers) { ScriptControllers sc = new ScriptControllers(); + sc.objectID = c.ObjectID; sc.itemID = c.ItemID; sc.ignoreControls = (ScriptControlled)c.IgnoreControls; sc.eventControls = (ScriptControlled)c.EventControls; @@ -3705,20 +3898,27 @@ namespace OpenSim.Region.Framework.Scenes } if (Appearance.AvatarHeight == 0) - Appearance.SetHeight(); +// Appearance.SetHeight(); + Appearance.SetSize(new Vector3(0.45f,0.6f,1.9f)); PhysicsScene scene = m_scene.PhysicsScene; Vector3 pVec = AbsolutePosition; +/* PhysicsActor = scene.AddAvatar( LocalId, Firstname + "." + Lastname, pVec, - new Vector3(0f, 0f, Appearance.AvatarHeight), isFlying); + new Vector3(0.45f, 0.6f, Appearance.AvatarHeight), isFlying); +*/ + + PhysicsActor = scene.AddAvatar( + LocalId, Firstname + "." + Lastname, pVec, + Appearance.AvatarBoxSize, isFlying); //PhysicsActor.OnRequestTerseUpdate += SendTerseUpdateToAllClients; PhysicsActor.OnCollisionUpdate += PhysicsCollisionUpdate; PhysicsActor.OnOutOfBounds += OutOfBoundsCall; // Called for PhysicsActors when there's something wrong - PhysicsActor.SubscribeEvents(500); + PhysicsActor.SubscribeEvents(100); PhysicsActor.LocalID = LocalId; } @@ -3732,6 +3932,7 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendAgentAlertMessage("Physics is having a problem with your avatar. You may not be able to move until you relog.", true); } + /// /// Event called by the physics plugin to tell the avatar about a collision. /// @@ -3745,7 +3946,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void PhysicsCollisionUpdate(EventArgs e) { - if (IsChildAgent) + if (IsChildAgent || Animator == null) return; //if ((Math.Abs(Velocity.X) > 0.1e-9f) || (Math.Abs(Velocity.Y) > 0.1e-9f)) @@ -3762,7 +3963,6 @@ namespace OpenSim.Region.Framework.Scenes CollisionEventUpdate collisionData = (CollisionEventUpdate)e; Dictionary coldata = collisionData.m_objCollisionList; - CollisionPlane = Vector4.UnitW; // // No collisions at all means we may be flying. Update always // // to make falling work @@ -3772,34 +3972,7 @@ namespace OpenSim.Region.Framework.Scenes // m_lastColCount = coldata.Count; // } - if (coldata.Count != 0) - { - switch (Animator.CurrentMovementAnimation) - { - case "STAND": - case "WALK": - case "RUN": - case "CROUCH": - case "CROUCHWALK": - { - ContactPoint lowest; - lowest.SurfaceNormal = Vector3.Zero; - lowest.Position = Vector3.Zero; - lowest.Position.Z = Single.NaN; - - foreach (ContactPoint contact in coldata.Values) - { - if (Single.IsNaN(lowest.Position.Z) || contact.Position.Z < lowest.Position.Z) - { - lowest = contact; - } - } - - CollisionPlane = new Vector4(-lowest.SurfaceNormal, -Vector3.Dot(lowest.Position, lowest.SurfaceNormal)); - } - break; - } - } + CollisionPlane = Vector4.UnitW; // Gods do not take damage and Invulnerable is set depending on parcel/region flags if (Invulnerable || GodLevel > 0) @@ -3898,6 +4071,12 @@ namespace OpenSim.Region.Framework.Scenes // m_reprioritizationTimer.Dispose(); RemoveFromPhysicalScene(); + + m_scene.EventManager.OnRegionHeartbeatEnd -= RegionHeartbeatEnd; + +// if (Animator != null) +// Animator.Close(); + Animator = null; LifecycleState = ScenePresenceState.Removed; } @@ -4133,10 +4312,18 @@ namespace OpenSim.Region.Framework.Scenes public void RegisterControlEventsToScript(int controls, int accept, int pass_on, uint Obj_localID, UUID Script_item_UUID) { + SceneObjectPart p = m_scene.GetSceneObjectPart(Obj_localID); + if (p == null) + return; + + ControllingClient.SendTakeControls(controls, false, false); + ControllingClient.SendTakeControls(controls, true, false); + ScriptControllers obj = new ScriptControllers(); obj.ignoreControls = ScriptControlled.CONTROL_ZERO; obj.eventControls = ScriptControlled.CONTROL_ZERO; + obj.objectID = p.ParentGroup.UUID; obj.itemID = Script_item_UUID; if (pass_on == 0 && accept == 0) { @@ -4185,6 +4372,21 @@ namespace OpenSim.Region.Framework.Scenes ControllingClient.SendTakeControls(int.MaxValue, false, false); } + private void UnRegisterSeatControls(UUID obj) + { + List takers = new List(); + + foreach (ScriptControllers c in scriptedcontrols.Values) + { + if (c.objectID == obj) + takers.Add(c.itemID); + } + foreach (UUID t in takers) + { + UnRegisterControlEventsToScript(0, t); + } + } + public void UnRegisterControlEventsToScript(uint Obj_localID, UUID Script_item_UUID) { ScriptControllers takecontrols; @@ -4514,6 +4716,12 @@ namespace OpenSim.Region.Framework.Scenes private void CheckAndAdjustLandingPoint(ref Vector3 pos) { + string reason; + + // Honor bans + if (!m_scene.TestLandRestrictions(UUID, out reason, ref pos.X, ref pos.Y)) + return; + SceneObjectGroup telehub = null; if (m_scene.RegionInfo.RegionSettings.TelehubObject != UUID.Zero && (telehub = m_scene.GetSceneObjectGroup(m_scene.RegionInfo.RegionSettings.TelehubObject)) != null) { @@ -4553,11 +4761,119 @@ namespace OpenSim.Region.Framework.Scenes pos = land.LandData.UserLocation; } } - + land.SendLandUpdateToClient(ControllingClient); } } + private DetectedObject CreateDetObject(SceneObjectPart obj) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = obj.UUID; + detobj.nameStr = obj.Name; + detobj.ownerUUID = obj.OwnerID; + detobj.posVector = obj.AbsolutePosition; + detobj.rotQuat = obj.GetWorldRotation(); + detobj.velVector = obj.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = obj.GroupID; + + return detobj; + } + + private DetectedObject CreateDetObject(ScenePresence av) + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = av.UUID; + detobj.nameStr = av.ControllingClient.Name; + detobj.ownerUUID = av.UUID; + detobj.posVector = av.AbsolutePosition; + detobj.rotQuat = av.Rotation; + detobj.velVector = av.Velocity; + detobj.colliderType = 0; + detobj.groupUUID = av.ControllingClient.ActiveGroupId; + + return detobj; + } + + private DetectedObject CreateDetObjectForGround() + { + DetectedObject detobj = new DetectedObject(); + detobj.keyUUID = UUID.Zero; + detobj.nameStr = ""; + detobj.ownerUUID = UUID.Zero; + detobj.posVector = AbsolutePosition; + detobj.rotQuat = Quaternion.Identity; + detobj.velVector = Vector3.Zero; + detobj.colliderType = 0; + detobj.groupUUID = UUID.Zero; + + return detobj; + } + + private ColliderArgs CreateColliderArgs(SceneObjectPart dest, List colliders) + { + ColliderArgs colliderArgs = new ColliderArgs(); + List colliding = new List(); + foreach (uint localId in colliders) + { + if (localId == 0) + continue; + + SceneObjectPart obj = m_scene.GetSceneObjectPart(localId); + if (obj != null) + { + if (!dest.CollisionFilteredOut(obj.UUID, obj.Name)) + colliding.Add(CreateDetObject(obj)); + } + else + { + ScenePresence av = m_scene.GetScenePresence(localId); + if (av != null && (!av.IsChildAgent)) + { + if (!dest.CollisionFilteredOut(av.UUID, av.Name)) + colliding.Add(CreateDetObject(av)); + } + } + } + + colliderArgs.Colliders = colliding; + + return colliderArgs; + } + + private delegate void ScriptCollidingNotification(uint localID, ColliderArgs message); + + private void SendCollisionEvent(SceneObjectGroup dest, scriptEvents ev, List colliders, ScriptCollidingNotification notify) + { + ColliderArgs CollidingMessage; + + if (colliders.Count > 0) + { + if ((dest.RootPart.ScriptEvents & ev) != 0) + { + CollidingMessage = CreateColliderArgs(dest.RootPart, colliders); + + if (CollidingMessage.Colliders.Count > 0) + notify(dest.RootPart.LocalId, CollidingMessage); + } + } + } + + private void SendLandCollisionEvent(SceneObjectGroup dest, scriptEvents ev, ScriptCollidingNotification notify) + { + if ((dest.RootPart.ScriptEvents & ev) != 0) + { + ColliderArgs LandCollidingMessage = new ColliderArgs(); + List colliding = new List(); + + colliding.Add(CreateDetObjectForGround()); + LandCollidingMessage.Colliders = colliding; + + notify(dest.RootPart.LocalId, LandCollidingMessage); + } + } + private void TeleportFlagsDebug() { // Some temporary debugging help to show all the TeleportFlags we have... @@ -4582,6 +4898,5 @@ namespace OpenSim.Region.Framework.Scenes m_log.InfoFormat("[SCENE PRESENCE]: TELEPORT ******************"); } - } } diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index a4fc4ae6c6..b3fdd22d18 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -908,7 +908,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server // Mimicking LLClientView which gets always set appearance from client. AvatarAppearance appearance; m_scene.GetAvatarAppearance(this, out appearance); - OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(), new List()); + OnSetAppearance(this, appearance.Texture, (byte[])appearance.VisualParams.Clone(),appearance.AvatarSize, new WearableCacheItem[0]); } public void SendRegionHandshake(RegionInfo regionInfo, RegionHandshakeArgs args) diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index f841d5c6b0..e1ef4d0cb3 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -110,6 +110,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests // ScenePresence.SendInitialData() to reset our entire appearance. m_scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); +/* m_afMod.SetAppearance(sp, originalTe, null); UUID npcId = m_npcMod.CreateNPC("John", "Smith", new Vector3(128, 128, 30), UUID.Zero, true, m_scene, sp.Appearance); @@ -125,6 +126,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests // Have to account for both SP and NPC. Assert.That(m_scene.AuthenticateHandler.GetAgentCircuits().Count, Is.EqualTo(2)); +*/ } [Test] diff --git a/OpenSim/Tests/Performance/NPCPerformanceTests.cs b/OpenSim/Tests/Performance/NPCPerformanceTests.cs index 2026a881f0..eb09061fab 100644 --- a/OpenSim/Tests/Performance/NPCPerformanceTests.cs +++ b/OpenSim/Tests/Performance/NPCPerformanceTests.cs @@ -144,6 +144,7 @@ namespace OpenSim.Tests.Performance // ScenePresence.SendInitialData() to reset our entire appearance. scene.AssetService.Store(AssetHelpers.CreateNotecardAsset(originalFace8TextureId)); +/* afm.SetAppearance(sp, originalTe, null); INPCModule npcModule = scene.RequestModuleInterface(); @@ -185,6 +186,7 @@ namespace OpenSim.Tests.Performance endGcMemory / 1024 / 1024, startGcMemory / 1024 / 1024, (endGcMemory - startGcMemory) / 1024 / 1024); +*/ } } -} \ No newline at end of file +} From 92aad6f1bb45974927fa43d6fd30f98337dee3f0 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 11 Dec 2013 01:44:03 +0000 Subject: [PATCH 08/24] Add missing files *blush* --- OpenSim/Framework/WearableCacheItem.cs | 157 ++++++++++++++++++ .../Interfaces/IBakedTextureModule.cs | 19 +++ 2 files changed, 176 insertions(+) create mode 100644 OpenSim/Framework/WearableCacheItem.cs create mode 100644 OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs diff --git a/OpenSim/Framework/WearableCacheItem.cs b/OpenSim/Framework/WearableCacheItem.cs new file mode 100644 index 0000000000..1aecf79695 --- /dev/null +++ b/OpenSim/Framework/WearableCacheItem.cs @@ -0,0 +1,157 @@ +/* + * 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 OpenMetaverse.StructuredData; + +namespace OpenSim.Framework +{ + [Serializable] + public class WearableCacheItem + { + public uint TextureIndex { get; set; } + public UUID CacheId { get; set; } + public UUID TextureID { get; set; } + public AssetBase TextureAsset { get; set; } + + + public static WearableCacheItem[] GetDefaultCacheItem() + { + int itemmax = 21; + WearableCacheItem[] retitems = new WearableCacheItem[itemmax]; + for (uint i=0;i ret = new List(); + if (pInput.Type == OSDType.Array) + { + OSDArray itemarray = (OSDArray) pInput; + foreach (OSDMap item in itemarray) + { + ret.Add(new WearableCacheItem() + { + TextureIndex = item["textureindex"].AsUInteger(), + CacheId = item["cacheid"].AsUUID(), + TextureID = item["textureid"].AsUUID() + }); + + if (dataCache != null && item.ContainsKey("assetdata")) + { + AssetBase asset = new AssetBase(item["textureid"].AsUUID(),"BakedTexture",(sbyte)AssetType.Texture,UUID.Zero.ToString()); + asset.Temporary = true; + asset.Data = item["assetdata"].AsBinary(); + dataCache.Cache(asset); + } + } + } + else if (pInput.Type == OSDType.Map) + { + OSDMap item = (OSDMap) pInput; + ret.Add(new WearableCacheItem(){ + TextureIndex = item["textureindex"].AsUInteger(), + CacheId = item["cacheid"].AsUUID(), + TextureID = item["textureid"].AsUUID() + }); + if (dataCache != null && item.ContainsKey("assetdata")) + { + string assetCreator = item["assetcreator"].AsString(); + string assetName = item["assetname"].AsString(); + AssetBase asset = new AssetBase(item["textureid"].AsUUID(), assetName, (sbyte)AssetType.Texture, assetCreator); + asset.Temporary = true; + asset.Data = item["assetdata"].AsBinary(); + dataCache.Cache(asset); + } + } + else + { + return new WearableCacheItem[0]; + } + return ret.ToArray(); + + } + public static OSD ToOSD(WearableCacheItem[] pcacheItems, IImprovedAssetCache dataCache) + { + OSDArray arr = new OSDArray(); + foreach (WearableCacheItem item in pcacheItems) + { + OSDMap itemmap = new OSDMap(); + itemmap.Add("textureindex", OSD.FromUInteger(item.TextureIndex)); + itemmap.Add("cacheid", OSD.FromUUID(item.CacheId)); + itemmap.Add("textureid", OSD.FromUUID(item.TextureID)); + if (dataCache != null) + { + if (dataCache.Check(item.TextureID.ToString())) + { + AssetBase assetItem = dataCache.Get(item.TextureID.ToString()); + if (assetItem != null) + { + itemmap.Add("assetdata", OSD.FromBinary(assetItem.Data)); + itemmap.Add("assetcreator", OSD.FromString(assetItem.CreatorID)); + itemmap.Add("assetname", OSD.FromString(assetItem.Name)); + } + } + } + arr.Add(itemmap); + } + return arr; + } + public static WearableCacheItem SearchTextureIndex(uint pTextureIndex,WearableCacheItem[] pcacheItems) + { + for (int i = 0; i < pcacheItems.Length; i++) + { + if (pcacheItems[i].TextureIndex == pTextureIndex) + return pcacheItems[i]; + } + return null; + } + public static WearableCacheItem SearchTextureCacheId(UUID pCacheId, WearableCacheItem[] pcacheItems) + { + for (int i = 0; i < pcacheItems.Length; i++) + { + if (pcacheItems[i].CacheId == pCacheId) + return pcacheItems[i]; + } + return null; + } + public static WearableCacheItem SearchTextureTextureId(UUID pTextureId, WearableCacheItem[] pcacheItems) + { + for (int i = 0; i < pcacheItems.Length; i++) + { + if (pcacheItems[i].TextureID == pTextureId) + return pcacheItems[i]; + } + return null; + } + } + + +} diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs new file mode 100644 index 0000000000..21ed44ffdb --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs @@ -0,0 +1,19 @@ +//////////////////////////////////////////////////////////////// +// +// (c) 2009, 2010 Careminster Limited and Melanie Thielker +// +// All rights reserved +// +using System; +using Nini.Config; +using OpenSim.Framework; +using OpenMetaverse; + +namespace OpenSim.Services.Interfaces +{ + public interface IBakedTextureModule + { + WearableCacheItem[] Get(UUID id); + void Store(UUID id, WearableCacheItem[] data); + } +} From 82ebb86d5808847fefcbe1affe24201ce4270ac2 Mon Sep 17 00:00:00 2001 From: Melanie Date: Wed, 11 Dec 2013 01:51:57 +0000 Subject: [PATCH 09/24] Replace proprietary file header with BSD one --- .../Interfaces/IBakedTextureModule.cs | 33 +++++++++++++++---- 1 file changed, 27 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs index 21ed44ffdb..b536a4984a 100644 --- a/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IBakedTextureModule.cs @@ -1,9 +1,30 @@ -//////////////////////////////////////////////////////////////// -// -// (c) 2009, 2010 Careminster Limited and Melanie Thielker -// -// All rights reserved -// +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + using System; using Nini.Config; using OpenSim.Framework; From 1d605642f78f46fed9e4cd38b117555717f87309 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 11 Dec 2013 23:59:52 +0000 Subject: [PATCH 10/24] Refix sitting on child prims by reinserting relevant code back into SP.HandleAgentSit() --- .../Region/Framework/Scenes/ScenePresence.cs | 25 ++++++++++++++++--- 1 file changed, 22 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index edb8ca8a2c..0282ad043e 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2868,14 +2868,33 @@ namespace OpenSim.Region.Framework.Scenes m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; -// m_pos = sitTargetPos + SIT_TARGET_ADJUSTMENT - sitOffset; - Rotation = sitTargetOrient; + Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; + Quaternion newRot; + + if (part.IsRoot) + { + newRot = sitTargetOrient; + } + else + { + newPos = newPos * part.RotationOffset; + newRot = part.RotationOffset * sitTargetOrient; + } + + newPos += part.OffsetPosition; + + m_pos = newPos; + Rotation = newRot; + // ParentPosition = part.AbsolutePosition; part.ParentGroup.AddAvatar(UUID); } else { - m_pos -= part.AbsolutePosition; + // An viewer expects to specify sit positions as offsets to the root prim, even if a child prim is + // being sat upon. + m_pos -= part.GroupPosition; + // ParentPosition = part.AbsolutePosition; part.ParentGroup.AddAvatar(UUID); From 11f177d6a88820c02547f916c39100a1c01e3bc1 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 13 Dec 2013 23:30:08 +0000 Subject: [PATCH 11/24] Eliminate unnecessary line from my previous commit 1d605642 --- OpenSim/Region/Framework/Scenes/ScenePresence.cs | 2 -- 1 file changed, 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 0282ad043e..cf98ef2f22 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -2866,8 +2866,6 @@ namespace OpenSim.Region.Framework.Scenes Vector3 up = new Vector3((float)x, (float)y, (float)z); Vector3 sitOffset = up * Appearance.AvatarHeight * 0.02638f; - m_pos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; - Vector3 newPos = sitTargetPos + sitOffset + SIT_TARGET_ADJUSTMENT; Quaternion newRot; From 54cc22976868dcdc0dd0143a0134fba7392af525 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 00:10:32 +0000 Subject: [PATCH 12/24] Fix TestSitAndStandWithNoSitTarget NPC and SP tests. These stopped working because current code calculates sit heights based on avatar physics rather than appearance data. Also changed BasicPhysics to not divide Z param of all set sizes by 2 - there's no obvious good reason for this and basicphysics is only used in tests --- .../Framework/Scenes/Tests/ScenePresenceSitTests.cs | 2 +- .../OptionalModules/World/NPC/Tests/NPCModuleTests.cs | 8 ++------ .../Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs | 9 +-------- 3 files changed, 4 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs index acaeb90fc4..c097a798c6 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs @@ -119,7 +119,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337> Assert.That( m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); + Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2))); m_sp.StandUp(); diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index e1ef4d0cb3..d552229141 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -337,7 +337,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests public void TestSitAndStandWithNoSitTarget() { TestHelpers.InMethod(); -// log4net.Config.XmlConfigurator.Configure(); +// TestHelpers.EnableLogging(); ScenePresence sp = SceneHelpers.AddScenePresence(m_scene, TestHelpers.ParseTail(0x1)); @@ -355,13 +355,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); - // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the - // default avatar. - // Curiously, Vector3.ToString() will not display the last two places of the float. For example, - // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337> Assert.That( npc.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, 0.845499337f))); + Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2))); m_npcMod.Stand(npc.UUID, m_scene); diff --git a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs index e43136a258..0d17e0e357 100644 --- a/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs +++ b/OpenSim/Region/Physics/BasicPhysicsPlugin/BasicPhysicsActor.cs @@ -118,14 +118,7 @@ namespace OpenSim.Region.Physics.BasicPhysicsPlugin public override Vector3 Position { get; set; } - public override Vector3 Size - { - get { return _size; } - set { - _size = value; - _size.Z = _size.Z / 2.0f; - } - } + public override Vector3 Size { get; set; } public override PrimitiveBaseShape Shape { From d2d4ae541b9e9e51225b7a9699346efdfc0b9b1a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 00:19:04 +0000 Subject: [PATCH 13/24] Fix build break in test from previous commit 54cc229 - hadn't realized ScenePresence inst var name was slightly different --- OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs index c097a798c6..eff8c7ab95 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs @@ -119,7 +119,7 @@ namespace OpenSim.Region.Framework.Scenes.Tests // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337> Assert.That( m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2))); + Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, m_sp.PhysicsActor.Size.Z / 2))); m_sp.StandUp(); From bcb8c4068e4d9ddbd1d4f29c7528f089d11f1d02 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 00:36:25 +0000 Subject: [PATCH 14/24] Comment out sit position checks in TestSitAndStandWithSitTarget() in SP and NPC tests until positions are known to be stable. Also resolve issues with NoSitTarget() tests where I was trying to use a destroyed PhysActor --- .../Scenes/Tests/ScenePresenceSitTests.cs | 14 ++++++-------- .../World/NPC/Tests/NPCModuleTests.cs | 8 +++++--- 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs index eff8c7ab95..0911f00cf9 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/ScenePresenceSitTests.cs @@ -111,15 +111,13 @@ namespace OpenSim.Region.Framework.Scenes.Tests SceneObjectPart part = SceneHelpers.AddSceneObject(m_scene).RootPart; + // We need to preserve this here because phys actor is removed by the sit. + Vector3 spPhysActorSize = m_sp.PhysicsActor.Size; m_sp.HandleAgentRequestSit(m_sp.ControllingClient, m_sp.UUID, part.UUID, Vector3.Zero); - // FIXME: This is different for live avatars - z position is adjusted. This is half the height of the - // default avatar. - // Curiously, Vector3.ToString() will not display the last two places of the float. For example, - // printing out npc.AbsolutePosition will give <0, 0, 0.8454993> not <0, 0, 0.845499337> Assert.That( m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, m_sp.PhysicsActor.Size.Z / 2))); + Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, spPhysActorSize.Z / 2))); m_sp.StandUp(); @@ -147,9 +145,9 @@ namespace OpenSim.Region.Framework.Scenes.Tests Assert.That(part.SitTargetAvatar, Is.EqualTo(m_sp.UUID)); Assert.That(m_sp.ParentID, Is.EqualTo(part.LocalId)); - Assert.That( - m_sp.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); +// Assert.That( +// m_sp.AbsolutePosition, +// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); Assert.That(m_sp.PhysicsActor, Is.Null); Assert.That(part.GetSittingAvatarsCount(), Is.EqualTo(1)); diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs index d552229141..7f9e440732 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs @@ -323,9 +323,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(part.SitTargetAvatar, Is.EqualTo(npcId)); Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); - Assert.That( - npc.AbsolutePosition, - Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); +// Assert.That( +// npc.AbsolutePosition, +// Is.EqualTo(part.AbsolutePosition + part.SitTargetPosition + ScenePresence.SIT_TARGET_ADJUSTMENT)); m_npcMod.Stand(npc.UUID, m_scene); @@ -355,6 +355,8 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests Assert.That(part.SitTargetAvatar, Is.EqualTo(UUID.Zero)); Assert.That(npc.ParentID, Is.EqualTo(part.LocalId)); + // We should really be using the NPC size but this would mean preserving the physics actor since it is + // removed on sit. Assert.That( npc.AbsolutePosition, Is.EqualTo(part.AbsolutePosition + new Vector3(0, 0, sp.PhysicsActor.Size.Z / 2))); From 5ddd8182385585f06c0f784cee27c7aa61b3da54 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 00:43:10 +0000 Subject: [PATCH 15/24] minor: Make wind console commands print out to console rather than log --- .../CoreModules/World/Wind/WindModule.cs | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs index 9de588ccdb..dad8bcb20e 100644 --- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs +++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs @@ -216,13 +216,13 @@ namespace OpenSim.Region.CoreModules // FIXME: If console region is root then this will be printed by every module. Currently, there is no // way to prevent this, short of making the entire module shared (which is complete overkill). // One possibility is to return a bool to signal whether the module has completely handled the command - m_log.InfoFormat("[WIND]: Please change to a specific region in order to set Sun parameters."); + MainConsole.Instance.Output("Please change to a specific region in order to set Sun parameters."); return; } if (m_scene.ConsoleScene() != m_scene) { - m_log.InfoFormat("[WIND]: Console Scene is not my scene."); + MainConsole.Instance.Output("Console Scene is not my scene."); return; } } @@ -233,7 +233,9 @@ namespace OpenSim.Region.CoreModules private void HandleConsoleCommand(string module, string[] cmdparams) { ValidateConsole(); - m_log.Info("[WIND] The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins."); + + MainConsole.Instance.Output( + "The wind command can be used to change the currently active wind model plugin and update the parameters for wind plugins."); } /// @@ -246,7 +248,9 @@ namespace OpenSim.Region.CoreModules if ((cmdparams.Length != 4) || !cmdparams[1].Equals("base")) { - m_log.Info("[WIND] Invalid parameters to change parameters for Wind module base, usage: wind base "); + MainConsole.Instance.Output( + "Invalid parameters to change parameters for Wind module base, usage: wind base "); + return; } @@ -261,7 +265,9 @@ namespace OpenSim.Region.CoreModules } else { - m_log.InfoFormat("[WIND] Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]); + MainConsole.Instance.OutputFormat( + "Invalid value {0} specified for {1}", cmdparams[3], cmdparams[2]); + return; } @@ -271,22 +277,23 @@ namespace OpenSim.Region.CoreModules if (desiredPlugin.Equals(m_activeWindPlugin.Name)) { - m_log.InfoFormat("[WIND] Wind model plugin {0} is already active", cmdparams[3]); + MainConsole.Instance.OutputFormat("Wind model plugin {0} is already active", cmdparams[3]); + return; } if (m_availableWindPlugins.ContainsKey(desiredPlugin)) { m_activeWindPlugin = m_availableWindPlugins[cmdparams[3]]; - m_log.InfoFormat("[WIND] {0} wind model plugin now active", m_activeWindPlugin.Name); + + MainConsole.Instance.OutputFormat("{0} wind model plugin now active", m_activeWindPlugin.Name); } else { - m_log.InfoFormat("[WIND] Could not find wind model plugin {0}", desiredPlugin); + MainConsole.Instance.OutputFormat("Could not find wind model plugin {0}", desiredPlugin); } break; } - } /// @@ -300,7 +307,7 @@ namespace OpenSim.Region.CoreModules if ((cmdparams.Length != 4) && (cmdparams.Length != 3)) { - m_log.Info("[WIND] Usage: wind [value]"); + MainConsole.Instance.Output("Usage: wind [value]"); return; } @@ -311,7 +318,7 @@ namespace OpenSim.Region.CoreModules { if (!float.TryParse(cmdparams[3], out value)) { - m_log.InfoFormat("[WIND] Invalid value {0}", cmdparams[3]); + MainConsole.Instance.OutputFormat("Invalid value {0}", cmdparams[3]); } try @@ -320,7 +327,7 @@ namespace OpenSim.Region.CoreModules } catch (Exception e) { - m_log.InfoFormat("[WIND] {0}", e.Message); + MainConsole.Instance.OutputFormat("{0}", e.Message); } } else @@ -328,11 +335,11 @@ namespace OpenSim.Region.CoreModules try { value = WindParamGet(plugin, param); - m_log.InfoFormat("[WIND] {0} : {1}", param, value); + MainConsole.Instance.OutputFormat("{0} : {1}", param, value); } catch (Exception e) { - m_log.InfoFormat("[WIND] {0}", e.Message); + MainConsole.Instance.OutputFormat("{0}", e.Message); } } From d656ec2a0766cf2a6ff6ad9cd8e2d42ada547d6c Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 01:07:37 +0000 Subject: [PATCH 16/24] Make WindParamSet success a console message rather than a log message. This effectively disables the log message as requested by http://opensimulator.org/mantis/view.php?id=6890 --- OpenSim/Region/CoreModules/World/Wind/WindModule.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs index dad8bcb20e..35014f531b 100644 --- a/OpenSim/Region/CoreModules/World/Wind/WindModule.cs +++ b/OpenSim/Region/CoreModules/World/Wind/WindModule.cs @@ -324,6 +324,7 @@ namespace OpenSim.Region.CoreModules try { WindParamSet(plugin, param, value); + MainConsole.Instance.OutputFormat("{0} set to {1}", param, value); } catch (Exception e) { @@ -373,13 +374,11 @@ namespace OpenSim.Region.CoreModules { IWindModelPlugin windPlugin = m_availableWindPlugins[plugin]; windPlugin.WindParamSet(param, value); - m_log.InfoFormat("[WIND] {0} set to {1}", param, value); } else { throw new Exception(String.Format("Could not find plugin {0}", plugin)); } - } public float WindParamGet(string plugin, string param) From 63ccc3dbf595d56fb9f08ee9575b81f3b39ca290 Mon Sep 17 00:00:00 2001 From: Eva Comaroski Date: Fri, 6 Dec 2013 13:12:35 +0000 Subject: [PATCH 17/24] Convert if-blocks to return statements in small functions such as GetStartParameter(). --- .../Region/ScriptEngine/XEngine/XEngine.cs | 20 +++++-------------- 1 file changed, 5 insertions(+), 15 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 5804aa87f2..b261b9fb32 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -1709,9 +1709,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine public bool GetScriptState(UUID itemID) { IScriptInstance instance = GetInstance(itemID); - if (instance != null) - return instance.Running; - return false; + return instance != null && instance.Running; } public void ApiResetScript(UUID itemID) @@ -1755,9 +1753,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine public DetectParams GetDetectParams(UUID itemID, int idx) { IScriptInstance instance = GetInstance(itemID); - if (instance != null) - return instance.GetDetectParams(idx); - return null; + return instance != null ? instance.GetDetectParams(idx) : null; } public void SetMinEventDelay(UUID itemID, double delay) @@ -1770,9 +1766,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine public UUID GetDetectID(UUID itemID, int idx) { IScriptInstance instance = GetInstance(itemID); - if (instance != null) - return instance.GetDetectID(idx); - return UUID.Zero; + return instance != null ? instance.GetDetectID(idx) : UUID.Zero; } public void SetState(UUID itemID, string newState) @@ -1786,9 +1780,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine public int GetStartParameter(UUID itemID) { IScriptInstance instance = GetInstance(itemID); - if (instance == null) - return 0; - return instance.StartParam; + return instance == null ? 0 : instance.StartParam; } public void OnShutdown() @@ -1822,9 +1814,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine public IScriptApi GetApi(UUID itemID, string name) { IScriptInstance instance = GetInstance(itemID); - if (instance == null) - return null; - return instance.GetApi(name); + return instance == null ? null : instance.GetApi(name); } public void OnGetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID) From 996a6c2eeacf25456d2ffc12e59c34240cf8a578 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 01:34:28 +0000 Subject: [PATCH 18/24] After previous discussion, put eye-catcher 'SCRIPT READY' messages to console rather than log as warning The problem with logging at warn is that these aren't actually warnings, and so are false positives to scripts that monitor for problems. Ideally, log4net would have a separate "status" logging level, but currently we will compromise by putting them to console, as they are user-oriented --- OpenSim/Framework/Servers/BaseOpenSimServer.cs | 4 ++-- .../Scripting/RegionReadyModule/RegionReadyModule.cs | 8 +++++--- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/OpenSim/Framework/Servers/BaseOpenSimServer.cs b/OpenSim/Framework/Servers/BaseOpenSimServer.cs index 4ab6908e90..566772d869 100644 --- a/OpenSim/Framework/Servers/BaseOpenSimServer.cs +++ b/OpenSim/Framework/Servers/BaseOpenSimServer.cs @@ -135,8 +135,8 @@ namespace OpenSim.Framework.Servers TimeSpan timeTaken = DateTime.Now - m_startuptime; - m_log.InfoFormat( - "[STARTUP]: Non-script portion of startup took {0}m {1}s. PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED.", + MainConsole.Instance.OutputFormat( + "PLEASE WAIT FOR LOGINS TO BE ENABLED ON REGIONS ONCE SCRIPTS HAVE STARTED. Non-script portion of startup took {0}m {1}s.", timeTaken.Minutes, timeTaken.Seconds); } diff --git a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs index c717128363..eb386fe423 100644 --- a/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs +++ b/OpenSim/Region/OptionalModules/Scripting/RegionReadyModule/RegionReadyModule.cs @@ -216,9 +216,11 @@ namespace OpenSim.Region.OptionalModules.Scripting.RegionReady // m_log.InfoFormat("[RegionReady]: Logins enabled for {0}, Oar {1}", // m_scene.RegionInfo.RegionName, m_oarFileLoading.ToString()); - // Warn level because the region cannot be used while logins are disabled - m_log.WarnFormat( - "[RegionReady]: INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); + // Putting this out to console to make it eye-catching for people who are running OpenSimulator + // without info log messages enabled. Making this a warning is arguably misleading since it isn't a + // warning, and monitor scripts looking for warn/error/fatal messages will received false positives. + // Arguably, log4net needs a status log level (like Apache). + MainConsole.Instance.OutputFormat("INITIALIZATION COMPLETE FOR {0} - LOGINS ENABLED", m_scene.Name); } m_scene.SceneGridService.InformNeighborsThatRegionisUp( From e7a294e739abc1e255d205a83aeadb679f098569 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 01:48:03 +0000 Subject: [PATCH 19/24] Wrap analysis of the particle system in the UUID Gatherer in a separate try/catch as sometimes it appears that this can be corrupt. As per Oren's suggestion. --- OpenSim/Region/Framework/Scenes/UuidGatherer.cs | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs index 502c7485ad..3e074b9cfc 100644 --- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs +++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs @@ -181,9 +181,18 @@ namespace OpenSim.Region.Framework.Scenes if (part.ParticleSystem.Length > 0) { - Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); - if (ps.Texture != UUID.Zero) - assetUuids[ps.Texture] = AssetType.Texture; + try + { + Primitive.ParticleSystem ps = new Primitive.ParticleSystem(part.ParticleSystem, 0); + if (ps.Texture != UUID.Zero) + assetUuids[ps.Texture] = AssetType.Texture; + } + catch (Exception e) + { + m_log.WarnFormat( + "[UUID GATHERER]: Could not check particle system for part {0} {1} in object {2} {3} since it is corrupt. Continuing.", + part.Name, part.UUID, sceneObject.Name, sceneObject.UUID); + } } TaskInventoryDictionary taskDictionary = (TaskInventoryDictionary)part.TaskInventory.Clone(); From 957449e62cda67a641162043e21cd102f6f99080 Mon Sep 17 00:00:00 2001 From: Kevin Cozens Date: Mon, 9 Dec 2013 03:15:40 -0500 Subject: [PATCH 20/24] ParseNotecardToList() returned data past end of notecard text (mantis #6881). --- OpenSim/Framework/SLUtil.cs | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) diff --git a/OpenSim/Framework/SLUtil.cs b/OpenSim/Framework/SLUtil.cs index 537de7ab15..cb73e8f762 100644 --- a/OpenSim/Framework/SLUtil.cs +++ b/OpenSim/Framework/SLUtil.cs @@ -247,12 +247,18 @@ namespace OpenSim.Framework /// public static List ParseNotecardToList(string rawInput) { - string[] input = rawInput.Replace("\r", "").Split('\n'); + string[] input; int idx = 0; int level = 0; List output = new List(); string[] words; + //The Linden format always ends with a } after the input data. + //Strip off trailing } so there is nothing after the input data. + int i = rawInput.LastIndexOf("}"); + rawInput = rawInput.Remove(i, rawInput.Length-i); + input = rawInput.Replace("\r", "").Split('\n'); + while (idx < input.Length) { if (input[idx] == "{") @@ -287,24 +293,18 @@ namespace OpenSim.Framework break; if (words[0] == "Text") { - int len = int.Parse(words[2]); - idx++; + idx++; //Now points to first line of notecard text - int count = -1; + //Number of lines in notecard. + int lines = input.Length - idx; + int line = 0; - while (count < len && idx < input.Length) + while (line < lines) { - // int l = input[idx].Length; - string ln = input[idx]; - - int need = len-count-1; - if (ln.Length > need) - ln = ln.Substring(0, need); - -// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", ln); - output.Add(ln); - count += ln.Length + 1; +// m_log.DebugFormat("[PARSE NOTECARD]: Adding line {0}", input[idx]); + output.Add(input[idx]); idx++; + line++; } return output; From 51da52f904965425eda4dee3832525bee23bc303 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Sat, 14 Dec 2013 02:48:29 +0000 Subject: [PATCH 21/24] Extend TestLlGetNotecardLine() regression test to contain chars that are two bytes in utf8 --- .../Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs index c92bcdbc5b..42d1b3b07b 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiNotecardTests.cs @@ -75,7 +75,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests { TestHelpers.InMethod(); - string[] ncLines = { "One", "Two", "Three" }; + string[] ncLines = { "One", "Twoè", "Three" }; TaskInventoryItem ncItem = TaskInventoryHelpers.AddNotecard(m_scene, m_so.RootPart, "nc", "1", "10", string.Join("\n", ncLines)); From f69e91dc2dfe4de573093199e02e78bcdcff0e9b Mon Sep 17 00:00:00 2001 From: Melanie Date: Mon, 16 Dec 2013 22:08:02 +0000 Subject: [PATCH 22/24] This is the acutal sitting avatar crossing code. This commit implements the actual crossing mechanics for seated avatars, using the supporting code from the previous commits. Physics is not supported yet, although some few bits for them are already in place due to the earlier code drops. With this commit, crossing sitting avatar by "editing" the prim across the border, by using llSetPos or keyframe motion may already be possible. Vehicles will come next. --- .../Framework/Scenes/SceneObjectGroup.cs | 154 +++++++++++++++++- 1 file changed, 152 insertions(+), 2 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index f16a8e6e2f..a2e4417df1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -429,6 +429,12 @@ namespace OpenSim.Region.Framework.Scenes return (IsAttachment || (m_rootPart.Shape.PCode == 9 && m_rootPart.Shape.State != 0)); } + private struct avtocrossInfo + { + public ScenePresence av; + public uint ParentID; + } + /// /// The absolute position of this scene object in the scene /// @@ -456,13 +462,124 @@ namespace OpenSim.Region.Framework.Scenes || Scene.TestBorderCross(val, Cardinals.S)) && !IsAttachmentCheckFull() && (!Scene.LoadingPrims)) { + IEntityTransferModule entityTransfer = m_scene.RequestModuleInterface(); + uint x = 0; + uint y = 0; + string version = String.Empty; + Vector3 newpos = Vector3.Zero; + OpenSim.Services.Interfaces.GridRegion destination = null; + if (m_rootPart.KeyframeMotion != null) m_rootPart.KeyframeMotion.StartCrossingCheck(); - m_scene.CrossPrimGroupIntoNewRegion(val, this, true); + bool canCross = true; + foreach (ScenePresence av in m_linkedAvatars) + { + // We need to cross these agents. First, let's find + // out if any of them can't cross for some reason. + // We have to deny the crossing entirely if any + // of them are banned. Alternatively, we could + // unsit banned agents.... + + + // We set the avatar position as being the object + // position to get the region to send to + if ((destination = entityTransfer.GetDestination(m_scene, av.UUID, val, out x, out y, out version, out newpos)) == null) + { + canCross = false; + break; + } + + m_log.DebugFormat("[SCENE OBJECT]: Avatar {0} needs to be crossed to {1}", av.Name, destination.RegionName); + } + + if (canCross) + { + // We unparent the SP quietly so that it won't + // be made to stand up + + List avsToCross = new List(); + + foreach (ScenePresence av in m_linkedAvatars) + { + avtocrossInfo avinfo = new avtocrossInfo(); + SceneObjectPart parentPart = m_scene.GetSceneObjectPart(av.ParentID); + if (parentPart != null) + av.ParentUUID = parentPart.UUID; + + avinfo.av = av; + avinfo.ParentID = av.ParentID; + avsToCross.Add(avinfo); + + av.PrevSitOffset = av.OffsetPosition; + av.ParentID = 0; + } + + // m_linkedAvatars.Clear(); + m_scene.CrossPrimGroupIntoNewRegion(val, this, true); + + // Normalize + if (val.X >= Constants.RegionSize) + val.X -= Constants.RegionSize; + if (val.Y >= Constants.RegionSize) + val.Y -= Constants.RegionSize; + if (val.X < 0) + val.X += Constants.RegionSize; + if (val.Y < 0) + val.Y += Constants.RegionSize; + + // If it's deleted, crossing was successful + if (IsDeleted) + { + // foreach (ScenePresence av in m_linkedAvatars) + foreach (avtocrossInfo avinfo in avsToCross) + { + ScenePresence av = avinfo.av; + if (!av.IsInTransit) // just in case... + { + 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); + } + else + m_log.DebugFormat("[SCENE OBJECT]: Crossing avatar alreasy in transit {0} to {1}", av.Name, val); + } + avsToCross.Clear(); + return; + } + else // cross failed, put avas back ?? + { + foreach (avtocrossInfo avinfo in avsToCross) + { + ScenePresence av = avinfo.av; + av.ParentUUID = UUID.Zero; + av.ParentID = avinfo.ParentID; +// m_linkedAvatars.Add(av); + } + } + avsToCross.Clear(); + + } + else + { + if (m_rootPart.KeyframeMotion != null) + m_rootPart.KeyframeMotion.CrossingFailure(); + + if (RootPart.PhysActor != null) + { + RootPart.PhysActor.CrossingFailure(); + } + } + Vector3 oldp = AbsolutePosition; + val.X = Util.Clamp(oldp.X, 0.5f, (float)Constants.RegionSize - 0.5f); + val.Y = Util.Clamp(oldp.Y, 0.5f, (float)Constants.RegionSize - 0.5f); + val.Z = Util.Clamp(oldp.Z, 0.5f, 4096.0f); } } - + if (RootPart.GetStatusSandbox()) { if (Util.GetDistanceTo(RootPart.StatusSandboxPos, value) > 10) @@ -496,6 +613,39 @@ namespace OpenSim.Region.Framework.Scenes } } + public override Vector3 Velocity + { + get { return RootPart.Velocity; } + set { RootPart.Velocity = value; } + } + + private void CrossAgentToNewRegionCompleted(IAsyncResult iar) + { + CrossAgentToNewRegionDelegate icon = (CrossAgentToNewRegionDelegate)iar.AsyncState; + ScenePresence agent = icon.EndInvoke(iar); + + //// If the cross was successful, this agent is a child agent + if (agent.IsChildAgent) + { + if (agent.ParentUUID != UUID.Zero) + { + agent.ParentPart = null; +// agent.ParentPosition = Vector3.Zero; +// agent.ParentUUID = UUID.Zero; + } + } + + agent.ParentUUID = UUID.Zero; +// agent.Reset(); +// else // Not successful +// agent.RestoreInCurrentScene(); + + // In any case + agent.IsInTransit = false; + + m_log.DebugFormat("[SCENE OBJECT]: Crossing agent {0} {1} completed.", agent.Firstname, agent.Lastname); + } + public override uint LocalId { get { return m_rootPart.LocalId; } From b03ec6137f462486a3469f6ba4bbd363dc85295f Mon Sep 17 00:00:00 2001 From: BlueWall Date: Mon, 16 Dec 2013 15:10:09 -0500 Subject: [PATCH 23/24] Populate user preferences with UserAccount email if it is present, else return an error indicating no email is on record for the user. --- OpenSim/Data/MySQL/MySQLUserProfilesData.cs | 16 +++-- OpenSim/Data/SQLite/SQLiteUserProfilesData.cs | 3 +- .../UserProfilesService.cs | 61 +++++++++++++++++++ 3 files changed, 73 insertions(+), 7 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs index 63492c2f10..0bf959543c 100644 --- a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs +++ b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs @@ -925,15 +925,19 @@ namespace OpenSim.Data.MySQL } else { + dbcon.Close(); + dbcon.Open(); + + query = "INSERT INTO usersettings VALUES "; + query += "(?uuid,'false','false', ?Email)"; + using (MySqlCommand put = new MySqlCommand(query, dbcon)) { - query = "INSERT INTO usersettings VALUES "; - query += "(?Id,'false','false', '')"; - lock(Lock) - { - put.ExecuteNonQuery(); - } + put.Parameters.AddWithValue("?Email", pref.EMail); + put.Parameters.AddWithValue("?uuid", pref.UserId.ToString()); + + put.ExecuteNonQuery(); } } } diff --git a/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs index 916a226d6b..90d45e9c0e 100644 --- a/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs +++ b/OpenSim/Data/SQLite/SQLiteUserProfilesData.cs @@ -808,11 +808,12 @@ namespace OpenSim.Data.SQLite else { query = "INSERT INTO usersettings VALUES "; - query += "(:Id,'false','false', '')"; + query += "(:Id,'false','false', :Email)"; using (SqliteCommand put = (SqliteCommand)m_connection.CreateCommand()) { put.Parameters.AddWithValue(":Id", pref.UserId.ToString()); + put.Parameters.AddWithValue(":Email", pref.EMail); put.ExecuteNonQuery(); } diff --git a/OpenSim/Services/UserProfilesService/UserProfilesService.cs b/OpenSim/Services/UserProfilesService/UserProfilesService.cs index 69c7b91957..dd26cdcb13 100644 --- a/OpenSim/Services/UserProfilesService/UserProfilesService.cs +++ b/OpenSim/Services/UserProfilesService/UserProfilesService.cs @@ -37,6 +37,7 @@ using OpenSim.Data; using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework; +using OpenSim.Services.UserAccountService; namespace OpenSim.Services.ProfilesService { @@ -166,11 +167,71 @@ namespace OpenSim.Services.ProfilesService #region User Preferences public bool UserPreferencesUpdate(ref UserPreferences pref, ref string result) { + if(string.IsNullOrEmpty(pref.EMail)) + { + UserAccount account = new UserAccount(); + if(userAccounts is UserAccountService.UserAccountService) + { + try + { + account = userAccounts.GetUserAccount(UUID.Zero, pref.UserId); + if(string.IsNullOrEmpty(account.Email)) + { + result = "No Email address on record!"; + return false; + } + else + pref.EMail = account.Email; + } + catch + { + m_log.Info ("[PROFILES]: UserAccountService Exception: Could not get user account"); + result = "Missing Email address!"; + return false; + } + } + else + { + m_log.Info ("[PROFILES]: UserAccountService: Could not get user account"); + result = "Missing Email address!"; + return false; + } + } return ProfilesData.UpdateUserPreferences(ref pref, ref result); } public bool UserPreferencesRequest(ref UserPreferences pref, ref string result) { + if(string.IsNullOrEmpty(pref.EMail)) + { + UserAccount account = new UserAccount(); + if(userAccounts is UserAccountService.UserAccountService) + { + try + { + account = userAccounts.GetUserAccount(UUID.Zero, pref.UserId); + if(string.IsNullOrEmpty(account.Email)) + { + result = "No Email address on record!"; + return false; + } + else + pref.EMail = account.Email; + } + catch + { + m_log.Info ("[PROFILES]: UserAccountService Exception: Could not get user account"); + result = "Missing Email address!"; + return false; + } + } + else + { + m_log.Info ("[PROFILES]: UserAccountService: Could not get user account"); + result = "Missing Email address!"; + return false; + } + } return ProfilesData.GetUserPreferences(ref pref, ref result); } #endregion User Preferences From 141d771a931140402cfa0575cf31e7116540f7d0 Mon Sep 17 00:00:00 2001 From: BlueWall Date: Mon, 16 Dec 2013 15:43:34 -0500 Subject: [PATCH 24/24] Fix issue with editing notes for other avatars --- OpenSim/Data/MySQL/MySQLUserProfilesData.cs | 4 ++++ .../CoreModules/Avatar/UserProfiles/UserProfileModule.cs | 4 ++-- 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs index 0bf959543c..6ed3b06a2a 100644 --- a/OpenSim/Data/MySQL/MySQLUserProfilesData.cs +++ b/OpenSim/Data/MySQL/MySQLUserProfilesData.cs @@ -546,6 +546,10 @@ namespace OpenSim.Data.MySQL reader.Read(); notes.Notes = OSD.FromString((string)reader["notes"]); } + else + { + notes.Notes = OSD.FromString(""); + } } } } diff --git a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs index b21082fd74..bfa30e6ed7 100644 --- a/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/UserProfiles/UserProfileModule.cs @@ -758,8 +758,8 @@ namespace OpenSim.Region.OptionalModules.Avatar.UserProfiles IClientAPI remoteClient = (IClientAPI)sender; string serverURI = string.Empty; GetUserProfileServerURI(remoteClient.AgentId, out serverURI); - note.TargetId = remoteClient.AgentId; - UUID.TryParse(args[0], out note.UserId); + note.UserId = remoteClient.AgentId; + UUID.TryParse(args[0], out note.TargetId); object Note = (object)note; if(!JsonRpcRequest(ref Note, "avatarnotesrequest", serverURI, UUID.Random().ToString()))