diff --git a/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs new file mode 100644 index 0000000000..4dca59231e --- /dev/null +++ b/OpenSim/Capabilities/Handlers/AvatarPickerSearch/AvatarPickerSearchHandler.cs @@ -0,0 +1,116 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Collections.Specialized; +using System.IO; +using System.Reflection; +using System.Web; +using log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Capabilities; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +//using OpenSim.Region.Framework.Interfaces; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; + +namespace OpenSim.Capabilities.Handlers +{ + public class AvatarPickerSearchHandler : BaseStreamHandler + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private IPeople m_PeopleService; + + public AvatarPickerSearchHandler(string path, IPeople peopleService, string name, string description) + : base("GET", path, name, description) + { + m_PeopleService = peopleService; + } + + public override byte[] Handle(string path, Stream request, IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + // Try to parse the texture ID from the request URL + NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); + string names = query.GetOne("names"); + string psize = query.GetOne("page_size"); + string pnumber = query.GetOne("page"); + + if (m_PeopleService == null) + return FailureResponse(names, (int)System.Net.HttpStatusCode.InternalServerError, httpResponse); + + if (string.IsNullOrEmpty(names) || names.Length < 3) + return FailureResponse(names, (int)System.Net.HttpStatusCode.BadRequest, httpResponse); + + m_log.DebugFormat("[AVATAR PICKER SEARCH]: search for {0}", names); + + int page_size = (string.IsNullOrEmpty(psize) ? 500 : Int32.Parse(psize)); + int page_number = (string.IsNullOrEmpty(pnumber) ? 1 : Int32.Parse(pnumber)); + + // Full content request + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.OK; + //httpResponse.ContentLength = ??; + httpResponse.ContentType = "application/llsd+xml"; + + List users = m_PeopleService.GetUserData(names, page_size, page_number); + + LLSDAvatarPicker osdReply = new LLSDAvatarPicker(); + osdReply.next_page_url = httpRequest.RawUrl; + foreach (UserData u in users) + osdReply.agents.Array.Add(ConvertUserData(u)); + + string reply = LLSDHelpers.SerialiseLLSDReply(osdReply); + return System.Text.Encoding.UTF8.GetBytes(reply); + } + + private LLSDPerson ConvertUserData(UserData user) + { + LLSDPerson p = new LLSDPerson(); + p.legacy_first_name = user.FirstName; + p.legacy_last_name = user.LastName; + p.display_name = user.FirstName + " " + user.LastName; + if (user.LastName.StartsWith("@")) + p.username = user.FirstName.ToLower() + user.LastName.ToLower(); + else + p.username = user.FirstName.ToLower() + "." + user.LastName.ToLower(); + p.id = user.Id; + p.is_display_name_default = false; + return p; + } + + private byte[] FailureResponse(string names, int statuscode, IOSHttpResponse httpResponse) + { + m_log.Error("[AVATAR PICKER SEARCH]: Error searching for " + names); + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + return System.Text.Encoding.UTF8.GetBytes(string.Empty); + } + } +} \ No newline at end of file diff --git a/OpenSim/Capabilities/LLSDAvatarPicker.cs b/OpenSim/Capabilities/LLSDAvatarPicker.cs new file mode 100644 index 0000000000..d0b3f3a5ec --- /dev/null +++ b/OpenSim/Capabilities/LLSDAvatarPicker.cs @@ -0,0 +1,51 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using OpenMetaverse; + +namespace OpenSim.Framework.Capabilities +{ + [OSDMap] + public class LLSDAvatarPicker + { + public string next_page_url; + // an array of LLSDPerson + public OSDArray agents = new OSDArray(); + } + + [OSDMap] + public class LLSDPerson + { + public string username; + public string display_name; + //'display_name_next_update':d"1970-01-01T00:00:00Z" + public string legacy_first_name; + public string legacy_last_name; + public UUID id; + public bool is_display_name_default; + } +} \ No newline at end of file diff --git a/OpenSim/Framework/IPeople.cs b/OpenSim/Framework/IPeople.cs new file mode 100644 index 0000000000..b88e1039e6 --- /dev/null +++ b/OpenSim/Framework/IPeople.cs @@ -0,0 +1,47 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using OpenMetaverse; + +namespace OpenSim.Framework +{ + public class UserData + { + public UUID Id { get; set; } + public string FirstName { get; set; } + public string LastName { get; set; } + public string HomeURL { get; set; } + public Dictionary ServerURLs { get; set; } + } + + public interface IPeople + { + List GetUserData(string query, int page_size, int page_number); + } +} \ No newline at end of file diff --git a/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs new file mode 100644 index 0000000000..d7af1f29a0 --- /dev/null +++ b/OpenSim/Region/ClientStack/Linden/Caps/AvatarPickerSearchModule.cs @@ -0,0 +1,140 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Specialized; +using System.Drawing; +using System.Drawing.Imaging; +using System.Reflection; +using System.IO; +using System.Web; +using log4net; +using Nini.Config; +using Mono.Addins; +using OpenMetaverse; +using OpenMetaverse.StructuredData; +using OpenSim.Framework; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Caps = OpenSim.Framework.Capabilities.Caps; +using OpenSim.Capabilities.Handlers; + +namespace OpenSim.Region.ClientStack.Linden +{ + + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "AvatarPickerSearchModule")] + public class AvatarPickerSearchModule : INonSharedRegionModule + { + private static readonly ILog m_log = + LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private IPeople m_People; + private bool m_Enabled = false; + + private string m_URL; + + #region ISharedRegionModule Members + + public void Initialise(IConfigSource source) + { + IConfig config = source.Configs["ClientStack.LindenCaps"]; + if (config == null) + return; + + m_URL = config.GetString("Cap_AvatarPickerSearch", string.Empty); + m_log.DebugFormat("[XXX]: Cap_AvatarPickerSearch = {0}", m_URL); + // Cap doesn't exist + if (m_URL != string.Empty) + m_Enabled = true; + } + + public void AddRegion(Scene s) + { + if (!m_Enabled) + return; + + m_scene = s; + } + + public void RemoveRegion(Scene s) + { + if (!m_Enabled) + return; + + m_scene.EventManager.OnRegisterCaps -= RegisterCaps; + m_scene = null; + } + + public void RegionLoaded(Scene s) + { + if (!m_Enabled) + return; + + m_People = m_scene.RequestModuleInterface(); + m_scene.EventManager.OnRegisterCaps += RegisterCaps; + } + + public void PostInitialise() + { + } + + public void Close() { } + + public string Name { get { return "AvatarPickerSearchModule"; } } + + public Type ReplaceableInterface + { + get { return null; } + } + + #endregion + + public void RegisterCaps(UUID agentID, Caps caps) + { + UUID capID = UUID.Random(); + + if (m_URL == "localhost") + { + m_log.DebugFormat("[AVATAR PICKER SEARCH]: /CAPS/{0} in region {1}", capID, m_scene.RegionInfo.RegionName); + caps.RegisterHandler( + "AvatarPickerSearch", + new AvatarPickerSearchHandler("/CAPS/" + capID + "/", m_People, "AvatarPickerSearch", "Search for avatars by name")); + } + else + { + // m_log.DebugFormat("[AVATAR PICKER SEARCH]: {0} in region {1}", m_URL, m_scene.RegionInfo.RegionName); + caps.RegisterHandler("AvatarPickerSearch", m_URL); + } + } + + } +} diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs index 8ce20e9950..fac93e63bb 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/HGUserManagementModule.cs @@ -70,7 +70,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement #endregion ISharedRegionModule - protected override void AddAdditionalUsers(UUID avatarID, string query, List users) + protected override void AddAdditionalUsers(string query, List users) { if (query.Contains("@")) // First.Last@foo.com, maybe? { diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index 7b823ba8f0..6847e572fb 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs @@ -46,17 +46,8 @@ using Mono.Addins; namespace OpenSim.Region.CoreModules.Framework.UserManagement { - public class UserData - { - public UUID Id { get; set; } - public string FirstName { get; set; } - public string LastName { get; set; } - public string HomeURL { get; set; } - public Dictionary ServerURLs { get; set; } - } - [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "UserManagementModule")] - public class UserManagementModule : ISharedRegionModule, IUserManagement + public class UserManagementModule : ISharedRegionModule, IUserManagement, IPeople { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -101,6 +92,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_Scenes.Add(scene); scene.RegisterModuleInterface(this); + scene.RegisterModuleInterface(this); scene.EventManager.OnNewClient += new EventManager.OnNewClientDelegate(EventManager_OnNewClient); scene.EventManager.OnPrimsLoaded += new EventManager.PrimsLoaded(EventManager_OnPrimsLoaded); } @@ -181,29 +173,7 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement m_log.DebugFormat("[USER MANAGEMENT MODULE]: HandleAvatarPickerRequest for {0}", query); - // searhc the user accounts service - List accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); - - List users = new List(); - if (accs != null) - { - foreach (UserAccount acc in accs) - { - UserData ud = new UserData(); - ud.FirstName = acc.FirstName; - ud.LastName = acc.LastName; - ud.Id = acc.PrincipalID; - users.Add(ud); - } - } - - // search the local cache - foreach (UserData data in m_UserCache.Values) - if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && - (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) - users.Add(data); - - AddAdditionalUsers(avatarID, query, users); + List users = GetUserData(query, 500, 1); AvatarPickerReplyPacket replyPacket = (AvatarPickerReplyPacket)PacketPool.Instance.GetPacket(PacketType.AvatarPickerReply); // TODO: don't create new blocks if recycling an old packet @@ -249,12 +219,46 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement client.SendAvatarPickerReply(agent_data, data_args); } - protected virtual void AddAdditionalUsers(UUID avatarID, string query, List users) + protected virtual void AddAdditionalUsers(string query, List users) { } #endregion Event Handlers + #region IPeople + + public List GetUserData(string query, int page_size, int page_number) + { + // search the user accounts service + List accs = m_Scenes[0].UserAccountService.GetUserAccounts(m_Scenes[0].RegionInfo.ScopeID, query); + + List users = new List(); + if (accs != null) + { + foreach (UserAccount acc in accs) + { + UserData ud = new UserData(); + ud.FirstName = acc.FirstName; + ud.LastName = acc.LastName; + ud.Id = acc.PrincipalID; + users.Add(ud); + } + } + + // search the local cache + foreach (UserData data in m_UserCache.Values) + if (users.Find(delegate(UserData d) { return d.Id == data.Id; }) == null && + (data.FirstName.ToLower().StartsWith(query.ToLower()) || data.LastName.ToLower().StartsWith(query.ToLower()))) + users.Add(data); + + AddAdditionalUsers(query, users); + + return users; + + } + + #endregion IPeople + private void CacheCreators(SceneObjectGroup sog) { //m_log.DebugFormat("[USER MANAGEMENT MODULE]: processing {0} {1}; {2}", sog.RootPart.Name, sog.RootPart.CreatorData, sog.RootPart.CreatorIdentification); diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs new file mode 100644 index 0000000000..948c8934a9 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/XEstateConnector.cs @@ -0,0 +1,215 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Reflection; + +using OpenSim.Services.Interfaces; +using GridRegion = OpenSim.Services.Interfaces.GridRegion; +using OpenSim.Server.Base; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Framework; +using OpenSim.Region.Framework.Scenes; + +using OpenMetaverse; +using log4net; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + public class EstateConnector + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected XEstateModule m_EstateModule; + + public EstateConnector(XEstateModule module) + { + m_EstateModule = module; + } + + public void SendTeleportHomeOneUser(uint EstateID, UUID PreyID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "teleport_home_one_user"; + + sendData["EstateID"] = EstateID.ToString(); + sendData["PreyID"] = PreyID.ToString(); + + SendToEstate(EstateID, sendData); + } + + public void SendTeleportHomeAllUsers(uint EstateID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "teleport_home_all_users"; + + sendData["EstateID"] = EstateID.ToString(); + + SendToEstate(EstateID, sendData); + } + + public bool SendUpdateCovenant(uint EstateID, UUID CovenantID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "update_covenant"; + + sendData["CovenantID"] = CovenantID.ToString(); + sendData["EstateID"] = EstateID.ToString(); + + // Handle local regions locally + // + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + s.RegionInfo.RegionSettings.Covenant = CovenantID; +// s.ReloadEstateData(); + } + + SendToEstate(EstateID, sendData); + + return true; + } + + public bool SendUpdateEstate(uint EstateID) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "update_estate"; + + sendData["EstateID"] = EstateID.ToString(); + + // Handle local regions locally + // + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + s.ReloadEstateData(); + } + + SendToEstate(EstateID, sendData); + + return true; + } + + public void SendEstateMessage(uint EstateID, UUID FromID, string FromName, string Message) + { + Dictionary sendData = new Dictionary(); + sendData["METHOD"] = "estate_message"; + + sendData["EstateID"] = EstateID.ToString(); + sendData["FromID"] = FromID.ToString(); + sendData["FromName"] = FromName; + sendData["Message"] = Message; + + SendToEstate(EstateID, sendData); + } + + private void SendToEstate(uint EstateID, Dictionary sendData) + { + List regions = m_EstateModule.Scenes[0].GetEstateRegions((int)EstateID); + + UUID ScopeID = UUID.Zero; + + // Handle local regions locally + // + foreach (Scene s in m_EstateModule.Scenes) + { + if (regions.Contains(s.RegionInfo.RegionID)) + { + // All regions in one estate are in the same scope. + // Use that scope. + // + ScopeID = s.RegionInfo.ScopeID; + regions.Remove(s.RegionInfo.RegionID); + } + } + + // Our own region should always be in the above list. + // In a standalone this would not be true. But then, + // Scope ID is not relevat there. Use first scope. + // + if (ScopeID == UUID.Zero) + ScopeID = m_EstateModule.Scenes[0].RegionInfo.ScopeID; + + // Don't send to the same instance twice + // + List done = new List(); + + // Send to remote regions + // + foreach (UUID regionID in regions) + { + GridRegion region = m_EstateModule.Scenes[0].GridService.GetRegionByUUID(ScopeID, regionID); + if (region != null) + { + string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; + if (done.Contains(url)) + continue; + + Call(region, sendData); + done.Add(url); + } + } + } + + private bool Call(GridRegion region, Dictionary sendData) + { + string reqString = ServerUtils.BuildQueryString(sendData); + // m_log.DebugFormat("[XESTATE CONNECTOR]: queryString = {0}", reqString); + try + { + string url = "http://" + region.ExternalHostName + ":" + region.HttpPort; + string reply = SynchronousRestFormsRequester.MakeRequest("POST", + url + "/estate", + reqString); + if (reply != string.Empty) + { + Dictionary replyData = ServerUtils.ParseXmlResponse(reply); + + if (replyData.ContainsKey("RESULT")) + { + if (replyData["RESULT"].ToString().ToLower() == "true") + return true; + else + return false; + } + else + m_log.DebugFormat("[XESTATE CONNECTOR]: reply data does not contain result field"); + + } + else + m_log.DebugFormat("[XESTATE CONNECTOR]: received empty reply"); + } + catch (Exception e) + { + m_log.DebugFormat("[XESTATE CONNECTOR]: Exception when contacting remote sim: {0}", e.Message); + } + + return false; + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs new file mode 100644 index 0000000000..1f099c61ad --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/XEstateModule.cs @@ -0,0 +1,254 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections; +using System.Collections.Generic; +using System.Reflection; +using log4net; +using Nini.Config; +using Nwc.XmlRpc; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Communications; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using OpenSim.Server.Base; +using OpenSim.Framework.Servers; +using OpenSim.Framework.Servers.HttpServer; +using Mono.Addins; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XEstate")] + public class XEstateModule : ISharedRegionModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected List m_Scenes = new List(); + protected bool m_InInfoUpdate = false; + + public bool InInfoUpdate + { + get { return m_InInfoUpdate; } + set { m_InInfoUpdate = value; } + } + + public List Scenes + { + get { return m_Scenes; } + } + + protected EstateConnector m_EstateConnector; + + public void Initialise(IConfigSource config) + { + int port = 0; + + IConfig estateConfig = config.Configs["Estate"]; + if (estateConfig != null) + { + port = estateConfig.GetInt("Port", 0); + } + + m_EstateConnector = new EstateConnector(this); + + // Instantiate the request handler + IHttpServer server = MainServer.GetHttpServer((uint)port); + server.AddStreamHandler(new EstateRequestHandler(this)); + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public void AddRegion(Scene scene) + { + m_Scenes.Add(scene); + + scene.EventManager.OnNewClient += OnNewClient; + } + + public void RegionLoaded(Scene scene) + { + IEstateModule em = scene.RequestModuleInterface(); + + em.OnRegionInfoChange += OnRegionInfoChange; + em.OnEstateInfoChange += OnEstateInfoChange; + em.OnEstateMessage += OnEstateMessage; + } + + public void RemoveRegion(Scene scene) + { + scene.EventManager.OnNewClient -= OnNewClient; + + m_Scenes.Remove(scene); + } + + public string Name + { + get { return "EstateModule"; } + } + + public Type ReplaceableInterface + { + get { return null; } + } + + private Scene FindScene(UUID RegionID) + { + foreach (Scene s in Scenes) + { + if (s.RegionInfo.RegionID == RegionID) + return s; + } + + return null; + } + + private void OnRegionInfoChange(UUID RegionID) + { + Scene s = FindScene(RegionID); + if (s == null) + return; + + if (!m_InInfoUpdate) + m_EstateConnector.SendUpdateCovenant(s.RegionInfo.EstateSettings.EstateID, s.RegionInfo.RegionSettings.Covenant); + } + + private void OnEstateInfoChange(UUID RegionID) + { + Scene s = FindScene(RegionID); + if (s == null) + return; + + if (!m_InInfoUpdate) + m_EstateConnector.SendUpdateEstate(s.RegionInfo.EstateSettings.EstateID); + } + + private void OnEstateMessage(UUID RegionID, UUID FromID, string FromName, string Message) + { + Scene senderScenes = FindScene(RegionID); + if (senderScenes == null) + return; + + uint estateID = senderScenes.RegionInfo.EstateSettings.EstateID; + + foreach (Scene s in Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == estateID) + { + IDialogModule dm = s.RequestModuleInterface(); + + if (dm != null) + { + dm.SendNotificationToUsersInRegion(FromID, FromName, + Message); + } + } + } + if (!m_InInfoUpdate) + m_EstateConnector.SendEstateMessage(estateID, FromID, FromName, Message); + } + + private void OnNewClient(IClientAPI client) + { + client.OnEstateTeleportOneUserHomeRequest += OnEstateTeleportOneUserHomeRequest; + client.OnEstateTeleportAllUsersHomeRequest += OnEstateTeleportAllUsersHomeRequest; + + } + + private void OnEstateTeleportOneUserHomeRequest(IClientAPI client, UUID invoice, UUID senderID, UUID prey) + { + if (prey == UUID.Zero) + return; + + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)client.Scene; + + uint estateID = scene.RegionInfo.EstateSettings.EstateID; + + if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false)) + return; + + foreach (Scene s in Scenes) + { + if (s == scene) + continue; // Already handles by estate module + if (s.RegionInfo.EstateSettings.EstateID != estateID) + continue; + + ScenePresence p = scene.GetScenePresence(prey); + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + scene.TeleportClientHome(prey, p.ControllingClient); + } + } + + m_EstateConnector.SendTeleportHomeOneUser(estateID, prey); + } + + private void OnEstateTeleportAllUsersHomeRequest(IClientAPI client, UUID invoice, UUID senderID) + { + if (!(client.Scene is Scene)) + return; + + Scene scene = (Scene)client.Scene; + + uint estateID = scene.RegionInfo.EstateSettings.EstateID; + + if (!scene.Permissions.CanIssueEstateCommand(client.AgentId, false)) + return; + + foreach (Scene s in Scenes) + { + if (s == scene) + continue; // Already handles by estate module + if (s.RegionInfo.EstateSettings.EstateID != estateID) + continue; + + scene.ForEachScenePresence(delegate(ScenePresence p) { + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + scene.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient); + } + }); + } + + m_EstateConnector.SendTeleportHomeAllUsers(estateID); + } + } +} diff --git a/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs new file mode 100644 index 0000000000..eb74cdab76 --- /dev/null +++ b/OpenSim/Region/CoreModules/World/Estate/XEstateRequestHandler.cs @@ -0,0 +1,298 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.IO; +using System.Reflection; +using System.Xml; + +using OpenSim.Framework; +using OpenSim.Server.Base; +using OpenSim.Framework.Servers.HttpServer; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Region.Framework.Interfaces; + +using OpenMetaverse; +using log4net; + +namespace OpenSim.Region.CoreModules.World.Estate +{ + public class EstateRequestHandler : BaseStreamHandler + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + protected XEstateModule m_EstateModule; + protected Object m_RequestLock = new Object(); + + public EstateRequestHandler(XEstateModule fmodule) + : base("POST", "/estate") + { + m_EstateModule = fmodule; + } + + public override byte[] Handle(string path, Stream requestData, + IOSHttpRequest httpRequest, IOSHttpResponse httpResponse) + { + StreamReader sr = new StreamReader(requestData); + string body = sr.ReadToEnd(); + sr.Close(); + body = body.Trim(); + + m_log.DebugFormat("[XESTATE HANDLER]: query String: {0}", body); + + try + { + lock (m_RequestLock) + { + Dictionary request = + ServerUtils.ParseQueryString(body); + + if (!request.ContainsKey("METHOD")) + return FailureResult(); + + string method = request["METHOD"].ToString(); + request.Remove("METHOD"); + + try + { + m_EstateModule.InInfoUpdate = false; + + switch (method) + { + case "update_covenant": + return UpdateCovenant(request); + case "update_estate": + return UpdateEstate(request); + case "estate_message": + return EstateMessage(request); + case "teleport_home_one_user": + return TeleportHomeOneUser(request); + case "teleport_home_all_users": + return TeleportHomeAllUsers(request); + } + } + finally + { + m_EstateModule.InInfoUpdate = false; + } + } + } + catch (Exception e) + { + m_log.Debug("[XESTATE]: Exception {0}" + e.ToString()); + } + + return FailureResult(); + } + + byte[] TeleportHomeAllUsers(Dictionary request) + { + UUID PreyID = UUID.Zero; + int EstateID = 0; + + if (!request.ContainsKey("EstateID")) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + { + s.ForEachScenePresence(delegate(ScenePresence p) { + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + s.TeleportClientHome(p.ControllingClient.AgentId, p.ControllingClient); + } + }); + } + } + + return SuccessResult(); + } + + byte[] TeleportHomeOneUser(Dictionary request) + { + UUID PreyID = UUID.Zero; + int EstateID = 0; + + if (!request.ContainsKey("PreyID") || + !request.ContainsKey("EstateID")) + { + return FailureResult(); + } + + if (!UUID.TryParse(request["PreyID"].ToString(), out PreyID)) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + { + ScenePresence p = s.GetScenePresence(PreyID); + if (p != null && !p.IsChildAgent) + { + p.ControllingClient.SendTeleportStart(16); + s.TeleportClientHome(PreyID, p.ControllingClient); + } + } + } + + return SuccessResult(); + } + + byte[] EstateMessage(Dictionary request) + { + UUID FromID = UUID.Zero; + string FromName = String.Empty; + string Message = String.Empty; + int EstateID = 0; + + if (!request.ContainsKey("FromID") || + !request.ContainsKey("FromName") || + !request.ContainsKey("Message") || + !request.ContainsKey("EstateID")) + { + return FailureResult(); + } + + if (!UUID.TryParse(request["FromID"].ToString(), out FromID)) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + FromName = request["FromName"].ToString(); + Message = request["Message"].ToString(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == EstateID) + { + IDialogModule dm = s.RequestModuleInterface(); + + if (dm != null) + { + dm.SendNotificationToUsersInRegion(FromID, FromName, + Message); + } + } + } + + return SuccessResult(); + } + + byte[] UpdateCovenant(Dictionary request) + { + UUID CovenantID = UUID.Zero; + int EstateID = 0; + + if (!request.ContainsKey("CovenantID") || !request.ContainsKey("EstateID")) + return FailureResult(); + + if (!UUID.TryParse(request["CovenantID"].ToString(), out CovenantID)) + return FailureResult(); + + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID) + s.RegionInfo.RegionSettings.Covenant = CovenantID; + } + + return SuccessResult(); + } + + byte[] UpdateEstate(Dictionary request) + { + int EstateID = 0; + + if (!request.ContainsKey("EstateID")) + return FailureResult(); + if (!Int32.TryParse(request["EstateID"].ToString(), out EstateID)) + return FailureResult(); + + foreach (Scene s in m_EstateModule.Scenes) + { + if (s.RegionInfo.EstateSettings.EstateID == (uint)EstateID) + s.ReloadEstateData(); + } + return SuccessResult(); + } + + private byte[] FailureResult() + { + return BoolResult(false); + } + + private byte[] SuccessResult() + { + return BoolResult(true); + } + + private byte[] BoolResult(bool value) + { + XmlDocument doc = new XmlDocument(); + + XmlNode xmlnode = doc.CreateNode(XmlNodeType.XmlDeclaration, + "", ""); + + doc.AppendChild(xmlnode); + + XmlElement rootElement = doc.CreateElement("", "ServerResponse", + ""); + + doc.AppendChild(rootElement); + + XmlElement result = doc.CreateElement("", "RESULT", ""); + result.AppendChild(doc.CreateTextNode(value.ToString())); + + rootElement.AppendChild(result); + + return DocToBytes(doc); + } + + private byte[] DocToBytes(XmlDocument doc) + { + MemoryStream ms = new MemoryStream(); + XmlTextWriter xw = new XmlTextWriter(ms, null); + xw.Formatting = Formatting.Indented; + doc.WriteTo(xw); + xw.Flush(); + + return ms.ToArray(); + } + } +} diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 292efa4b7e..d49b24ec0d 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -40,7 +40,7 @@ namespace OpenSim.Region.Framework.Interfaces uint GetRegionFlags(); bool IsManager(UUID avatarID); - + /// /// Tell all clients about the current state of the region (terrain textures, water height, etc.). /// diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index caeb980cef..5860c9ae33 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -3392,7 +3392,7 @@ namespace OpenSim.Region.Framework.Scenes { if (EntityTransferModule != null) { - EntityTransferModule.TeleportHome(agentId, client); + return EntityTransferModule.TeleportHome(agentId, client); } else { diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs index 04ea289bd1..c16b7d3e6a 100644 --- a/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSDynamics.cs @@ -1028,6 +1028,10 @@ namespace OpenSim.Region.Physics.BulletSPlugin Vector3 currentVelV = VehicleVelocity * Quaternion.Inverse(VehicleOrientation); Vector3 linearMotorCorrectionV = m_linearMotor.Step(pTimestep, currentVelV); + // Friction reduces vehicle motion + Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep); + linearMotorCorrectionV -= (currentVelV * frictionFactorW); + // Motor is vehicle coordinates. Rotate it to world coordinates Vector3 linearMotorVelocityW = linearMotorCorrectionV * VehicleOrientation; @@ -1041,9 +1045,7 @@ namespace OpenSim.Region.Physics.BulletSPlugin // Add this correction to the velocity to make it faster/slower. VehicleVelocity += linearMotorVelocityW; - // Friction reduces vehicle motion - Vector3 frictionFactorW = ComputeFrictionFactor(m_linearFrictionTimescale, pTimestep) * VehicleOrientation; - VehicleVelocity -= (VehicleVelocity * frictionFactorW); + VDetailLog("{0}, MoveLinear,velocity,origVelW={1},velV={2},correctV={3},correctW={4},newVelW={5},fricFact={6}", ControllingPrim.LocalID, origVelW, currentVelV, linearMotorCorrectionV, @@ -1337,11 +1339,13 @@ namespace OpenSim.Region.Physics.BulletSPlugin // angularMotorContributionV.Y = 0f; // } + // Reduce any velocity by friction. + Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep); + angularMotorContributionV -= (currentAngularV * frictionFactorW); + VehicleRotationalVelocity += angularMotorContributionV * VehicleOrientation; - // Reduce any velocity by friction. - Vector3 frictionFactorW = ComputeFrictionFactor(m_angularFrictionTimescale, pTimestep) * VehicleOrientation; - VehicleRotationalVelocity -= (VehicleRotationalVelocity * frictionFactorW); + VDetailLog("{0}, MoveAngular,angularTurning,angContribV={1}", ControllingPrim.LocalID, angularMotorContributionV); } diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs index 1f16cc8db9..350a5d1761 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSLinksetCompound.cs @@ -347,21 +347,21 @@ public sealed class BSLinksetCompound : BSLinkset // Bullet presumes an object's origin (relative <0,0,0>) is its center-of-mass OMV.Vector3 centerOfMassW = ComputeLinksetCenterOfMass(); - OMV.Quaternion invRootOrientation = OMV.Quaternion.Inverse(LinksetRoot.RawOrientation); + OMV.Quaternion invRootOrientation = OMV.Quaternion.Normalize(OMV.Quaternion.Inverse(LinksetRoot.RawOrientation)); // 'centerDisplacement' is the value to subtract from children to give physical offset position - OMV.Vector3 centerDisplacement = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; + OMV.Vector3 centerDisplacementV = (centerOfMassW - LinksetRoot.RawPosition) * invRootOrientation; if (UseBulletSimRootOffsetHack || disableCOM) { - centerDisplacement = OMV.Vector3.Zero; + centerDisplacementV = OMV.Vector3.Zero; LinksetRoot.ClearDisplacement(); } else { - LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacement); + LinksetRoot.SetEffectiveCenterOfMassDisplacement(centerDisplacementV); } DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,COM,rootPos={1},com={2},comDisp={3}", - LinksetRoot.LocalID, LinksetRoot.RawPosition, centerOfMassW, centerDisplacement); + LinksetRoot.LocalID, LinksetRoot.RawPosition, centerOfMassW, centerDisplacementV); // Add the shapes of all the components of the linkset int memberIndex = 1; @@ -372,8 +372,8 @@ public sealed class BSLinksetCompound : BSLinkset // Get a reference to the shape of the child and add that shape to the linkset compound shape BSShape childShape = cPrim.PhysShape.GetReference(m_physicsScene, cPrim); - OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacement; - OMV.Quaternion offsetRot = cPrim.RawOrientation * invRootOrientation; + OMV.Vector3 offsetPos = (cPrim.RawPosition - LinksetRoot.RawPosition) * invRootOrientation - centerDisplacementV; + OMV.Quaternion offsetRot = OMV.Quaternion.Normalize(cPrim.RawOrientation) * invRootOrientation; m_physicsScene.PE.AddChildShapeToCompoundShape(linksetShape.physShapeInfo, childShape.physShapeInfo, offsetPos, offsetRot); DetailLog("{0},BSLinksetCompound.RecomputeLinksetCompound,addChild,indx={1},cShape={2},offPos={3},offRot={4}", LinksetRoot.LocalID, memberIndex, childShape, offsetPos, offsetRot); diff --git a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs index 10081840eb..f89c52f787 100755 --- a/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs +++ b/OpenSim/Region/Physics/BulletSPlugin/BSShapes.cs @@ -117,11 +117,11 @@ public abstract class BSShape StringBuilder buff = new StringBuilder(); if (physShapeInfo == null) { - buff.Append(",noPhys"); + buff.Append("" -- capability enabled and served by some other server ;; ; These are enabled by default to localhost. Change if you see fit. - Cap_GetTexture = "localhost" + Cap_GetTexture = "localhost" Cap_GetMesh = "localhost" + Cap_AvatarPickerSearch = "localhost" + ; This is disabled by default. Change if you see fit. Note that ; serving this cap from the simulators may lead to poor performace. Cap_WebFetchInventoryDescendents = "" diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index ca8822c62a..60e4be2743 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -541,7 +541,6 @@ ;; in OpenSim.ini ;; Cap_AttachmentResources = "" - Cap_AvatarPickerSearch = "" Cap_ChatSessionRequest = "" Cap_CopyInventoryFromNotecard = "localhost" Cap_DispatchRegionInfo = "" @@ -605,6 +604,10 @@ Cap_WebFetchInventoryDescendents = "" Cap_FetchInventoryDescendents2 = "localhost" Cap_FetchInventory2 = "localhost" + + ; Capability for searching for people + Cap_AvatarPickerSearch = "localhost" + [Chat]