diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 089d2f544c..287073bbf8 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -71,6 +71,7 @@ what it is today. * CharlieO * ChrisDown * Chris Yeoh (IBM) +* controlbreak * coyled * Daedius * Dong Jun Lan (IBM) diff --git a/OpenSim/Data/MSSQL/MSSQLManager.cs b/OpenSim/Data/MSSQL/MSSQLManager.cs index 575fd210c1..62c38d3568 100644 --- a/OpenSim/Data/MSSQL/MSSQLManager.cs +++ b/OpenSim/Data/MSSQL/MSSQLManager.cs @@ -104,6 +104,11 @@ namespace OpenSim.Data.MSSQL { return SqlDbType.BigInt; } + if (type == typeof(DateTime)) + { + return SqlDbType.DateTime; + } + return SqlDbType.VarChar; } diff --git a/OpenSim/Data/Null/NullFriendsData.cs b/OpenSim/Data/Null/NullFriendsData.cs index 0a4b2426a8..473999fdb2 100644 --- a/OpenSim/Data/Null/NullFriendsData.cs +++ b/OpenSim/Data/Null/NullFriendsData.cs @@ -28,6 +28,9 @@ using System; using System.Collections; using System.Collections.Generic; +using System.Reflection; +using System.Threading; +using log4net; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Data; @@ -36,12 +39,26 @@ namespace OpenSim.Data.Null { public class NullFriendsData : IFriendsData { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static List m_Data = new List(); public NullFriendsData(string connectionString, string realm) { } + /// + /// Clear all friends data + /// + /// + /// This is required by unit tests to clear the static data between test runs. + /// + public static void Clear() + { + lock (m_Data) + m_Data.Clear(); + } + public FriendsData[] GetFriends(UUID principalID) { return GetFriends(principalID.ToString()); @@ -56,20 +73,30 @@ namespace OpenSim.Data.Null /// public FriendsData[] GetFriends(string userID) { - List lst = m_Data.FindAll(fdata => + lock (m_Data) { - return fdata.PrincipalID == userID.ToString(); - }); - - if (lst != null) - { - lst.ForEach(f => + List lst = m_Data.FindAll(fdata => { - FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID); - if (f2 != null) { f.Data["TheirFlags"] = f2.Data["Flags"]; } + return fdata.PrincipalID == userID.ToString(); }); - - return lst.ToArray(); + + if (lst != null) + { + lst.ForEach(f => + { + FriendsData f2 = m_Data.Find(candidateF2 => f.Friend == candidateF2.PrincipalID); + if (f2 != null) + f.Data["TheirFlags"] = f2.Data["Flags"]; + + // m_log.DebugFormat( + // "[NULL FRIENDS DATA]: Got {0} {1} {2} for {3}", + // f.Friend, f.Data["Flags"], f2 != null ? f.Data["TheirFlags"] : "not found!", f.PrincipalID); + }); + + // m_log.DebugFormat("[NULL FRIENDS DATA]: Got {0} friends for {1}", lst.Count, userID); + + return lst.ToArray(); + } } return new FriendsData[0]; @@ -80,7 +107,11 @@ namespace OpenSim.Data.Null if (data == null) return false; - m_Data.Add(data); +// m_log.DebugFormat( +// "[NULL FRIENDS DATA]: Storing {0} {1} {2}", data.PrincipalID, data.Friend, data.Data["Flags"]); + + lock (m_Data) + m_Data.Add(data); return true; } @@ -92,14 +123,21 @@ namespace OpenSim.Data.Null public bool Delete(string userID, string friendID) { - List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); - if (lst != null) + lock (m_Data) { - FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); - if (friendID != null) + List lst = m_Data.FindAll(delegate(FriendsData fdata) { return fdata.PrincipalID == userID.ToString(); }); + if (lst != null) { - m_Data.Remove(friend); - return true; + FriendsData friend = lst.Find(delegate(FriendsData fdata) { return fdata.Friend == friendID; }); + if (friendID != null) + { + // m_log.DebugFormat( + // "[NULL FRIENDS DATA]: Deleting friend {0} {1} for {2}", + // friend.Friend, friend.Data["Flags"], friend.PrincipalID); + + m_Data.Remove(friend); + return true; + } } } diff --git a/OpenSim/Data/Null/NullPresenceData.cs b/OpenSim/Data/Null/NullPresenceData.cs index 91f1cc561e..c06c223a81 100644 --- a/OpenSim/Data/Null/NullPresenceData.cs +++ b/OpenSim/Data/Null/NullPresenceData.cs @@ -110,7 +110,6 @@ namespace OpenSim.Data.Null return false; } - public PresenceData[] Get(string field, string data) { if (Instance != this) diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 1d806fc5eb..1f03ec5c20 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -244,10 +244,10 @@ namespace OpenSim.Data.Tests SceneObjectPart[] newparts = newsog.Parts; Assert.That(newparts.Length,Is.EqualTo(4), "Assert.That(newparts.Length,Is.EqualTo(4))"); - Assert.That(newsog.HasChildPrim(tmp0), "Assert.That(newsog.HasChildPrim(tmp0))"); - Assert.That(newsog.HasChildPrim(tmp1), "Assert.That(newsog.HasChildPrim(tmp1))"); - Assert.That(newsog.HasChildPrim(tmp2), "Assert.That(newsog.HasChildPrim(tmp2))"); - Assert.That(newsog.HasChildPrim(tmp3), "Assert.That(newsog.HasChildPrim(tmp3))"); + Assert.That(newsog.ContainsPart(tmp0), "Assert.That(newsog.ContainsPart(tmp0))"); + Assert.That(newsog.ContainsPart(tmp1), "Assert.That(newsog.ContainsPart(tmp1))"); + Assert.That(newsog.ContainsPart(tmp2), "Assert.That(newsog.ContainsPart(tmp2))"); + Assert.That(newsog.ContainsPart(tmp3), "Assert.That(newsog.ContainsPart(tmp3))"); } [Test] diff --git a/OpenSim/Framework/ICallingCardModule.cs b/OpenSim/Framework/ICallingCardModule.cs deleted file mode 100644 index 17e6de35b6..0000000000 --- a/OpenSim/Framework/ICallingCardModule.cs +++ /dev/null @@ -1,13 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Text; -using OpenMetaverse; -using OpenSim.Framework; - -namespace OpenSim.Framework -{ - public interface ICallingCardModule - { - UUID CreateCallingCard(UUID userID, UUID creatorID, UUID folderID); - } -} diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index 004b1a67a2..2be78dacf1 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -301,9 +301,9 @@ namespace OpenSim.Framework public delegate void ConfirmXfer(IClientAPI remoteClient, ulong xferID, uint packetID); public delegate void FriendActionDelegate( - IClientAPI remoteClient, UUID agentID, UUID transactionID, List callingCardFolders); + IClientAPI remoteClient, UUID transactionID, List callingCardFolders); - public delegate void FriendshipTermination(IClientAPI remoteClient, UUID agentID, UUID ExID); + public delegate void FriendshipTermination(IClientAPI remoteClient, UUID ExID); public delegate void MoneyTransferRequest( UUID sourceID, UUID destID, int amount, int transactionType, string description); @@ -464,7 +464,7 @@ namespace OpenSim.Framework public delegate void AvatarNotesUpdate(IClientAPI client, UUID targetID, string notes); public delegate void MuteListRequest(IClientAPI client, uint muteCRC); public delegate void AvatarInterestUpdate(IClientAPI client, uint wantmask, string wanttext, uint skillsmask, string skillstext, string languages); - public delegate void GrantUserFriendRights(IClientAPI client, UUID requester, UUID target, int rights); + public delegate void GrantUserFriendRights(IClientAPI client, UUID target, int rights); public delegate void PlacesQuery(UUID QueryID, UUID TransactionID, string QueryText, uint QueryFlags, byte Category, string SimName, IClientAPI client); public delegate void AgentFOV(IClientAPI client, float verticalAngle); @@ -717,7 +717,7 @@ namespace OpenSim.Framework /// The scene agent for this client. This will only be set if the client has an agent in a scene (i.e. if it /// is connected). /// - ISceneAgent SceneAgent { get; } + ISceneAgent SceneAgent { get; set; } UUID SessionId { get; } diff --git a/OpenSim/Framework/LandData.cs b/OpenSim/Framework/LandData.cs index 9a9a6bf607..dcaa46d960 100644 --- a/OpenSim/Framework/LandData.cs +++ b/OpenSim/Framework/LandData.cs @@ -69,7 +69,7 @@ namespace OpenSim.Framework (uint) ParcelFlags.AllowAPrimitiveEntry | (uint) ParcelFlags.AllowDeedToGroup | (uint) ParcelFlags.CreateObjects | (uint) ParcelFlags.AllowOtherScripts | - (uint) ParcelFlags.SoundLocal; + (uint) ParcelFlags.SoundLocal | (uint) ParcelFlags.AllowVoiceChat; private byte _landingType = 0; private string _name = "Your Parcel"; diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 63ec257c40..016a1744ef 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -39,7 +39,8 @@ namespace OpenSim RC1, RC2, Release, - Post_Fixes + Post_Fixes, + Extended } public static string Version diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index d0920d26ee..3118613afa 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -396,7 +396,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP } } public UUID AgentId { get { return m_agentId; } } - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } public UUID ActiveGroupId { get { return m_activeGroupID; } } public string ActiveGroupName { get { return m_activeGroupName; } } public ulong ActiveGroupPowers { get { return m_activeGroupPowers; } } @@ -719,7 +719,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public virtual void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); RefreshGroupMembership(); } @@ -5913,7 +5913,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP // My guess is this is the folder to stick the calling card into List callingCardFolders = new List(); - UUID agentID = afriendpack.AgentData.AgentID; UUID transactionID = afriendpack.TransactionBlock.TransactionID; for (int fi = 0; fi < afriendpack.FolderData.Length; fi++) @@ -5924,10 +5923,10 @@ namespace OpenSim.Region.ClientStack.LindenUDP FriendActionDelegate handlerApproveFriendRequest = OnApproveFriendRequest; if (handlerApproveFriendRequest != null) { - handlerApproveFriendRequest(this, agentID, transactionID, callingCardFolders); + handlerApproveFriendRequest(this, transactionID, callingCardFolders); } - return true; + return true; } private bool HandlerDeclineFriendship(IClientAPI sender, Packet Pack) @@ -5946,7 +5945,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (OnDenyFriendRequest != null) { OnDenyFriendRequest(this, - dfriendpack.AgentData.AgentID, dfriendpack.TransactionBlock.TransactionID, null); } @@ -5966,14 +5964,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP } #endregion - UUID listOwnerAgentID = tfriendpack.AgentData.AgentID; UUID exFriendID = tfriendpack.ExBlock.OtherID; FriendshipTermination TerminateFriendshipHandler = OnTerminateFriendship; if (TerminateFriendshipHandler != null) { - TerminateFriendshipHandler(this, listOwnerAgentID, exFriendID); + TerminateFriendshipHandler(this, exFriendID); return true; } + return false; } @@ -11378,12 +11376,13 @@ namespace OpenSim.Region.ClientStack.LindenUDP return true; } #endregion + GrantUserFriendRights GrantUserRightsHandler = OnGrantUserRights; if (GrantUserRightsHandler != null) GrantUserRightsHandler(this, - GrantUserRights.AgentData.AgentID, GrantUserRights.Rights[0].AgentRelated, GrantUserRights.Rights[0].RelatedRights); + return true; } @@ -12455,7 +12454,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP ItemData.Add(ItemDataMap); } - llsd.Add("ItemData", ItemData); + llsd.Add("InventoryData", ItemData); eq.Enqueue(BuildEvent("RemoveInventoryItem", llsd), AgentId); @@ -12499,6 +12498,14 @@ namespace OpenSim.Region.ClientStack.LindenUDP llsd), AgentId); } + private byte[] EncodeU32(uint val) + { + byte[] ret = BitConverter.GetBytes(val); + if (BitConverter.IsLittleEndian) + Array.Reverse(ret); + return ret; + } + public void SendBulkUpdateInventory(InventoryFolderBase[] folders, InventoryItemBase[] items) { IEventQueue eq = Scene.RequestModuleInterface(); @@ -12514,6 +12521,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP OSDMap AgentDataMap = new OSDMap(1); AgentDataMap.Add("AgentID", OSD.FromUUID(AgentId)); AgentDataMap.Add("SessionID", OSD.FromUUID(SessionId)); + AgentDataMap.Add("TransactionID", OSD.FromUUID(UUID.Random())); OSDArray AgentData = new OSDArray(1); AgentData.Add(AgentDataMap); @@ -12541,10 +12549,47 @@ namespace OpenSim.Region.ClientStack.LindenUDP foreach (InventoryItemBase item in items) { OSDMap ItemDataMap = new OSDMap(); + + ItemDataMap.Add("ItemID", OSD.FromUUID(item.ID)); + ItemDataMap.Add("FolderID", OSD.FromUUID(item.Folder)); + + ItemDataMap.Add("CreatorID", OSD.FromUUID(item.CreatorIdAsUuid)); + ItemDataMap.Add("OwnerID", OSD.FromUUID(item.Owner)); + ItemDataMap.Add("GroupID", OSD.FromUUID(item.GroupID)); + ItemDataMap.Add("BaseMask", OSD.FromBinary(EncodeU32((uint)item.BasePermissions))); + ItemDataMap.Add("OwnerMask", OSD.FromBinary(EncodeU32((uint)item.CurrentPermissions))); + ItemDataMap.Add("GroupMask", OSD.FromBinary(EncodeU32((uint)item.GroupPermissions))); + ItemDataMap.Add("EveryoneMask", OSD.FromBinary(EncodeU32((uint)item.EveryOnePermissions))); + ItemDataMap.Add("NextOwnerMask", OSD.FromBinary(EncodeU32((uint)item.NextPermissions))); + ItemDataMap.Add("GroupOwned", OSD.FromBoolean(item.GroupOwned)); + ItemDataMap.Add("AssetID", OSD.FromUUID(item.AssetID)); + ItemDataMap.Add("Type", OSD.FromInteger(item.AssetType)); + ItemDataMap.Add("InvType", OSD.FromInteger(item.InvType)); + ItemDataMap.Add("Flags", OSD.FromBinary(EncodeU32((uint)item.Flags))); + ItemDataMap.Add("SaleType", OSD.FromInteger((byte)item.SaleType)); + ItemDataMap.Add("SalePrice", OSD.FromInteger(item.SalePrice)); + ItemDataMap.Add("Name", OSD.FromString(item.Name)); + ItemDataMap.Add("Description", OSD.FromString(item.Description)); + ItemDataMap.Add("CreationDate", OSD.FromInteger(item.CreationDate)); + + ItemDataMap.Add("CRC", OSD.FromBinary(EncodeU32( + Helpers.InventoryCRC(1000, 0, (sbyte)item.InvType, + (sbyte)item.AssetType, item.AssetID, + item.GroupID, 100, + item.Owner, item.CreatorIdAsUuid, + item.ID, item.Folder, + (uint)PermissionMask.All, 1, (uint)PermissionMask.All, (uint)PermissionMask.All, + (uint)PermissionMask.All) + ))); + ItemDataMap.Add("CallbackID", 0); + ItemData.Add(ItemDataMap); } llsd.Add("ItemData", ItemData); + + eq.Enqueue(BuildEvent("BulkUpdateInventory", + llsd), AgentId); } } } diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs new file mode 100644 index 0000000000..d942e8742a --- /dev/null +++ b/OpenSim/Region/CoreModules/Avatar/Friends/CallingCardModule.cs @@ -0,0 +1,313 @@ +/* + * 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 log4net; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using Mono.Addins; + +namespace OpenSim.Region.CoreModules.Avatar.Friends +{ + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "XCallingCard")] + public class CallingCardModule : ISharedRegionModule, ICallingCardModule + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected List m_Scenes = new List(); + protected bool m_Enabled = true; + + public void Initialise(IConfigSource source) + { + IConfig ccConfig = source.Configs["XCallingCard"]; + if (ccConfig != null) + m_Enabled = ccConfig.GetBoolean("Enabled", true); + } + + public void AddRegion(Scene scene) + { + if (!m_Enabled) + return; + + m_Scenes.Add(scene); + + scene.RegisterModuleInterface(this); + } + + public void RemoveRegion(Scene scene) + { + if (!m_Enabled) + return; + + m_Scenes.Remove(scene); + + scene.EventManager.OnNewClient -= OnNewClient; + scene.EventManager.OnIncomingInstantMessage += + OnIncomingInstantMessage; + + scene.UnregisterModuleInterface(this); + } + + public void RegionLoaded(Scene scene) + { + if (!m_Enabled) + return; + scene.EventManager.OnNewClient += OnNewClient; + } + + public void PostInitialise() + { + } + + public void Close() + { + } + + public Type ReplaceableInterface + { + get { return null; } + } + + public string Name + { + get { return "XCallingCardModule"; } + } + + private void OnNewClient(IClientAPI client) + { + client.OnOfferCallingCard += OnOfferCallingCard; + client.OnAcceptCallingCard += OnAcceptCallingCard; + client.OnDeclineCallingCard += OnDeclineCallingCard; + } + + private void OnOfferCallingCard(IClientAPI client, UUID destID, UUID transactionID) + { + ScenePresence sp = GetClientPresence(client.AgentId); + if (sp != null) + { + // If we're in god mode, we reverse the meaning. Offer + // calling card becomes "Take a calling card" for that + // person, no matter if they agree or not. + if (sp.GodLevel >= 200) + { + CreateCallingCard(client.AgentId, destID, UUID.Zero, true); + return; + } + } + + IClientAPI dest = FindClientObject(destID); + if (dest != null) + { + DoCallingCardOffer(dest, client.AgentId); + return; + } + + IMessageTransferModule transferModule = + m_Scenes[0].RequestModuleInterface(); + + if (transferModule != null) + { + transferModule.SendInstantMessage(new GridInstantMessage( + client.Scene, client.AgentId, + client.FirstName+" "+client.LastName, + destID, (byte)211, false, + String.Empty, + transactionID, false, new Vector3(), new byte[0]), + delegate(bool success) {} ); + } + } + + private void DoCallingCardOffer(IClientAPI dest, UUID from) + { + UUID itemID = CreateCallingCard(dest.AgentId, from, UUID.Zero, false); + + dest.SendOfferCallingCard(from, itemID); + } + + // Create a calling card in the user's inventory. This is called + // from direct calling card creation, when the offer is forwarded, + // and from the friends module when the friend is confirmed. + // Because of the latter, it will send a bulk inventory update + // if the receiving user is in the same simulator. + public UUID CreateCallingCard(UUID userID, UUID creatorID, UUID folderID) + { + return CreateCallingCard(userID, creatorID, folderID, false); + } + + private UUID CreateCallingCard(UUID userID, UUID creatorID, UUID folderID, bool isGod) + { + IUserAccountService userv = m_Scenes[0].UserAccountService; + if (userv == null) + return UUID.Zero; + + UserAccount info = userv.GetUserAccount(UUID.Zero, creatorID); + if (info == null) + return UUID.Zero; + + IInventoryService inv = m_Scenes[0].InventoryService; + if (inv == null) + return UUID.Zero; + + if (folderID == UUID.Zero) + { + InventoryFolderBase folder = inv.GetFolderForType(userID, + AssetType.CallingCard); + + if (folder == null) // Nowhere to put it + return UUID.Zero; + + folderID = folder.ID; + } + + m_log.DebugFormat("[XCALLINGCARD]: Creating calling card for {0} in inventory of {1}", info.Name, userID); + + InventoryItemBase item = new InventoryItemBase(); + item.AssetID = UUID.Zero; + item.AssetType = (int)AssetType.CallingCard; + item.BasePermissions = (uint)(PermissionMask.Copy | PermissionMask.Modify); + if (isGod) + item.BasePermissions = (uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer | PermissionMask.Move); + + item.EveryOnePermissions = (uint)PermissionMask.None; + item.CurrentPermissions = item.BasePermissions; + item.NextPermissions = (uint)(PermissionMask.Copy | PermissionMask.Modify); + + item.ID = UUID.Random(); + item.CreatorId = creatorID.ToString(); + item.Owner = userID; + item.GroupID = UUID.Zero; + item.GroupOwned = false; + item.Folder = folderID; + + item.CreationDate = Util.UnixTimeSinceEpoch(); + item.InvType = (int)InventoryType.CallingCard; + item.Flags = 0; + + item.Name = info.Name; + item.Description = ""; + + item.SalePrice = 10; + item.SaleType = (byte)SaleType.Not; + + inv.AddItem(item); + + IClientAPI client = FindClientObject(userID); + if (client != null) + client.SendBulkUpdateInventory(item); + + return item.ID; + } + + private void OnAcceptCallingCard(IClientAPI client, UUID transactionID, UUID folderID) + { + } + + private void OnDeclineCallingCard(IClientAPI client, UUID transactionID) + { + IInventoryService invService = m_Scenes[0].InventoryService; + + InventoryFolderBase trashFolder = + invService.GetFolderForType(client.AgentId, AssetType.TrashFolder); + + InventoryItemBase item = new InventoryItemBase(transactionID, client.AgentId); + item = invService.GetItem(item); + + if (item != null && trashFolder != null) + { + item.Folder = trashFolder.ID; + List uuids = new List(); + uuids.Add(item.ID); + invService.DeleteItems(item.Owner, uuids); + m_Scenes[0].AddInventoryItem(client, item); + } + } + + public IClientAPI FindClientObject(UUID agentID) + { + Scene scene = GetClientScene(agentID); + if (scene == null) + return null; + + ScenePresence presence = scene.GetScenePresence(agentID); + if (presence == null) + return null; + + return presence.ControllingClient; + } + + private Scene GetClientScene(UUID agentId) + { + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null) + { + if (!presence.IsChildAgent) + return scene; + } + } + } + return null; + } + + private ScenePresence GetClientPresence(UUID agentId) + { + lock (m_Scenes) + { + foreach (Scene scene in m_Scenes) + { + ScenePresence presence = scene.GetScenePresence(agentId); + if (presence != null) + { + if (!presence.IsChildAgent) + return presence; + } + } + } + return null; + } + + private void OnIncomingInstantMessage(GridInstantMessage msg) + { + if (msg.dialog == (uint)211) + { + IClientAPI client = FindClientObject(new UUID(msg.toAgentID)); + if (client == null) + return; + + DoCallingCardOffer(client, new UUID(msg.fromAgentID)); + } + } + } +} diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 8e32fcc133..f64c161271 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -51,6 +51,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { public class FriendsModule : ISharedRegionModule, IFriendsModule { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + protected bool m_Enabled = false; protected class UserFriendData @@ -72,7 +74,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } protected static readonly FriendInfo[] EMPTY_FRIENDS = new FriendInfo[0]; - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); protected List m_Scenes = new List(); @@ -109,7 +110,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - protected IFriendsService FriendsService + public IFriendsService FriendsService { get { @@ -156,7 +157,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends InitModule(config); m_Enabled = true; - m_log.InfoFormat("[FRIENDS MODULE]: {0} enabled.", Name); + m_log.DebugFormat("[FRIENDS MODULE]: {0} enabled.", Name); } } } @@ -201,7 +202,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (!m_Enabled) return; - m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); +// m_log.DebugFormat("[FRIENDS MODULE]: AddRegion on {0}", Name); m_Scenes.Add(scene); scene.RegisterModuleInterface(this); @@ -212,14 +213,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends scene.EventManager.OnClientLogin += OnClientLogin; } - public virtual void RegionLoaded(Scene scene) - { - scene.AddCommand( - "Friends", this, "friends show cache", - "friends show cache [ ]", - "Show the friends cache for the given user", - HandleFriendsShowCacheCommand); - } + public virtual void RegionLoaded(Scene scene) {} public void RemoveRegion(Scene scene) { @@ -241,13 +235,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - public virtual uint GetFriendPerms(UUID principalID, UUID friendID) + public virtual int GetRightsGrantedByFriend(UUID principalID, UUID friendID) { - FriendInfo[] friends = GetFriends(principalID); + FriendInfo[] friends = GetFriendsFromCache(principalID); FriendInfo finfo = GetFriend(friends, friendID); if (finfo != null) { - return (uint)finfo.TheirFlags; + return finfo.TheirFlags; } return 0; @@ -258,9 +252,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnInstantMessage += OnInstantMessage; client.OnApproveFriendRequest += OnApproveFriendRequest; client.OnDenyFriendRequest += OnDenyFriendRequest; - client.OnTerminateFriendship += (thisClient, agentID, exfriendID) => RemoveFriendship(thisClient, exfriendID); - client.OnGrantUserRights += OnGrantUserRights; + client.OnTerminateFriendship += RemoveFriendship; + client.OnGrantUserRights += GrantRights; + // We need to cache information for child agents as well as root agents so that friend edit/move/delete + // permissions will work across borders where both regions are on different simulators. + // // Do not do this asynchronously. If we do, then subsequent code can outrace CacheFriends() and // return misleading results from the still empty friends cache. // If we absolutely need to do this asynchronously, then a signalling mechanism is needed so that calls @@ -352,18 +349,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Send the friends online List online = GetOnlineFriends(agentID); - if (online.Count > 0) - { - m_log.DebugFormat( - "[FRIENDS MODULE]: User {0} in region {1} has {2} friends online", - client.Name, client.Scene.RegionInfo.RegionName, online.Count); + if (online.Count > 0) client.SendAgentOnline(online.ToArray()); - } // Send outstanding friendship offers List outstanding = new List(); - FriendInfo[] friends = GetFriends(agentID); + FriendInfo[] friends = GetFriendsFromCache(agentID); foreach (FriendInfo fi in friends) { if (fi.TheirFlags == -1) @@ -419,23 +411,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends List GetOnlineFriends(UUID userID) { List friendList = new List(); - List online = new List(); - FriendInfo[] friends = GetFriends(userID); + FriendInfo[] friends = GetFriendsFromCache(userID); foreach (FriendInfo fi in friends) { - if (((fi.TheirFlags & 1) != 0) && (fi.TheirFlags != -1)) + if (((fi.TheirFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) friendList.Add(fi.Friend); } + List online = new List(); + if (friendList.Count > 0) GetOnlineFriends(userID, friendList, online); +// m_log.DebugFormat( +// "[FRIENDS MODULE]: User {0} has {1} friends online", userID, online.Count); + return online; } protected virtual void GetOnlineFriends(UUID userID, List friendList, /*collector*/ List online) { +// m_log.DebugFormat( +// "[FRIENDS MODULE]: Looking for online presence of {0} users for {1}", friendList.Count, userID); + PresenceInfo[] presence = PresenceService.GetAgents(friendList.ToArray()); foreach (PresenceInfo pi in presence) { @@ -486,13 +485,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends /// private void StatusChange(UUID agentID, bool online) { - FriendInfo[] friends = GetFriends(agentID); + FriendInfo[] friends = GetFriendsFromCache(agentID); if (friends.Length > 0) { List friendList = new List(); foreach (FriendInfo fi in friends) { - if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1)) + if (((fi.MyFlags & (int)FriendRights.CanSeeOnline) != 0) && (fi.TheirFlags != -1)) friendList.Add(fi); } @@ -558,7 +557,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2} ({3})", principalID, client.FirstName + client.LastName, friendID, im.fromAgentName); // Check that the friendship doesn't exist yet - FriendInfo[] finfos = GetFriends(principalID); + FriendInfo[] finfos = GetFriendsFromCache(principalID); if (finfos != null) { FriendInfo f = GetFriend(finfos, friendID); @@ -611,7 +610,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; } - protected virtual void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + protected virtual void OnApproveFriendRequest(IClientAPI client, UUID friendID, List callingCardFolders) { m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", client.AgentId, friendID); @@ -628,7 +627,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends ccm.CreateCallingCard(client.AgentId, friendID, UUID.Zero); } - // Update the local cache + // Update the local cache. RecacheFriends(client); // @@ -656,18 +655,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private void OnDenyFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + private void OnDenyFriendRequest(IClientAPI client, UUID friendID, List callingCardFolders) { - m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", agentID, friendID); + m_log.DebugFormat("[FRIENDS]: {0} denied friendship to {1}", client.AgentId, friendID); - DeleteFriendship(agentID, friendID); + DeleteFriendship(client.AgentId, friendID); // // Notify the friend // // Try local - if (LocalFriendshipDenied(agentID, client.Name, friendID)) + if (LocalFriendshipDenied(client.AgentId, client.Name, friendID)) return; PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); @@ -678,7 +677,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); if (region != null) - m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); + m_FriendsSimConnector.FriendshipDenied(region, client.AgentId, client.Name, friendID); else m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); } @@ -715,23 +714,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - private void OnGrantUserRights(IClientAPI remoteClient, UUID requester, UUID target, int rights) + public void GrantRights(IClientAPI remoteClient, UUID friendID, int rights) { - m_log.DebugFormat("[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", requester, rights, target); + UUID requester = remoteClient.AgentId; - FriendInfo[] friends = GetFriends(remoteClient.AgentId); + m_log.DebugFormat( + "[FRIENDS MODULE]: User {0} changing rights to {1} for friend {2}", + requester, rights, friendID); + + FriendInfo[] friends = GetFriendsFromCache(requester); if (friends.Length == 0) { return; } // Let's find the friend in this user's friend list - FriendInfo friend = GetFriend(friends, target); + FriendInfo friend = GetFriend(friends, friendID); if (friend != null) // Found it { // Store it on the DB - if (!StoreRights(requester, target, rights)) + if (!StoreRights(requester, friendID, rights)) { remoteClient.SendAlertMessage("Unable to grant rights."); return; @@ -742,17 +745,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends friend.MyFlags = rights; // Always send this back to the original client - remoteClient.SendChangeUserRights(requester, target, rights); + remoteClient.SendChangeUserRights(requester, friendID, rights); // // Notify the friend // // Try local - if (LocalGrantRights(requester, target, myFlags, rights)) + if (LocalGrantRights(requester, friendID, myFlags, rights)) return; - PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { target.ToString() }); + PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { PresenceInfo friendSession = friendSessions[0]; @@ -761,12 +764,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); // TODO: You might want to send the delta to save the lookup // on the other end!! - m_FriendsSimConnector.GrantRights(region, requester, target, myFlags, rights); + m_FriendsSimConnector.GrantRights(region, requester, friendID, myFlags, rights); } } } else - m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", target, requester); + { + m_log.DebugFormat("[FRIENDS MODULE]: friend {0} not found for {1}", friendID, requester); + } } protected virtual FriendInfo GetFriend(FriendInfo[] friends, UUID friendID) @@ -810,7 +815,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends ccm.CreateCallingCard(friendID, userID, UUID.Zero); } - // Update the local cache RecacheFriends(friendClient); @@ -904,20 +908,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion #region Get / Set friends in several flavours - /// - /// Get friends from local cache only - /// - /// - /// - /// An empty array if the user has no friends or friends have not been cached. - /// - protected FriendInfo[] GetFriends(UUID agentID) + + public FriendInfo[] GetFriendsFromCache(UUID userID) { UserFriendData friendsData; lock (m_Friends) { - if (m_Friends.TryGetValue(agentID, out friendsData)) + if (m_Friends.TryGetValue(userID, out friendsData)) return friendsData.Friends; } @@ -935,13 +933,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Update local cache lock (m_Friends) { - FriendInfo[] friends = GetFriends(friendID); + FriendInfo[] friends = GetFriendsFromCache(friendID); FriendInfo finfo = GetFriend(friends, userID); finfo.TheirFlags = rights; } } - protected virtual FriendInfo[] GetFriendsFromService(IClientAPI client) + public virtual FriendInfo[] GetFriendsFromService(IClientAPI client) { return FriendsService.GetFriends(client.AgentId); } @@ -959,12 +957,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - /// - /// Are friends cached on this simulator for a particular user? - /// - /// - /// - protected bool AreFriendsCached(UUID userID) + public bool AreFriendsCached(UUID userID) { lock (m_Friends) return m_Friends.ContainsKey(userID); @@ -983,8 +976,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected virtual void StoreFriendships(UUID agentID, UUID friendID) { - FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), 1); - FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), 1); + FriendsService.StoreFriend(agentID.ToString(), friendID.ToString(), (int)FriendRights.CanSeeOnline); + FriendsService.StoreFriend(friendID.ToString(), agentID.ToString(), (int)FriendRights.CanSeeOnline); } protected virtual bool DeleteFriendship(UUID agentID, UUID exfriendID) @@ -995,61 +988,5 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } #endregion - - protected void HandleFriendsShowCacheCommand(string module, string[] cmd) - { - if (cmd.Length != 5) - { - MainConsole.Instance.OutputFormat("Usage: friends show cache [ ]"); - return; - } - - string firstName = cmd[3]; - string lastName = cmd[4]; - - IUserManagement umModule = m_Scenes[0].RequestModuleInterface(); - UUID userId = umModule.GetUserIdByName(firstName, lastName); - -// UserAccount ua -// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, firstName, lastName); - - if (userId == UUID.Zero) - { - MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); - return; - } - - if (!AreFriendsCached(userId)) - { - MainConsole.Instance.OutputFormat("No friends cached on this simulator for {0} {1}", firstName, lastName); - return; - } - - MainConsole.Instance.OutputFormat("Cached friends for {0} {1}:", firstName, lastName); - - MainConsole.Instance.OutputFormat("UUID\n"); - - FriendInfo[] friends = GetFriends(userId); - - foreach (FriendInfo friend in friends) - { -// MainConsole.Instance.OutputFormat(friend.PrincipalID.ToString()); - -// string friendFirstName, friendLastName; -// -// UserAccount friendUa -// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friend.PrincipalID); - - UUID friendId; - string friendName; - - if (UUID.TryParse(friend.Friend, out friendId)) - friendName = umModule.GetUserName(friendId); - else - friendName = friend.Friend; - - MainConsole.Instance.OutputFormat("{0} {1} {2}", friendName, friend.MyFlags, friend.TheirFlags); - } - } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs index e50a84a76e..9a6d277252 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/HGFriendsModule.cs @@ -105,12 +105,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends #endregion - protected override void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) + protected override void OnApproveFriendRequest(IClientAPI client, UUID friendID, List callingCardFolders) { // Update the local cache. Yes, we need to do it right here // because the HGFriendsService placed something on the DB // from under the sim - base.OnApproveFriendRequest(client, agentID, friendID, callingCardFolders); + base.OnApproveFriendRequest(client, friendID, callingCardFolders); } protected override bool CacheFriends(IClientAPI client) @@ -163,7 +163,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(client.Scene.RegionInfo.ScopeID, client.AgentId); if (account == null) // foreign { - FriendInfo[] friends = GetFriends(client.AgentId); + FriendInfo[] friends = GetFriendsFromCache(client.AgentId); foreach (FriendInfo f in friends) { client.SendChangeUserRights(new UUID(f.Friend), client.AgentId, f.TheirFlags); @@ -300,8 +300,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends return null; } - - protected override FriendInfo[] GetFriendsFromService(IClientAPI client) + public override FriendInfo[] GetFriendsFromService(IClientAPI client) { // m_log.DebugFormat("[HGFRIENDS MODULE]: Entering GetFriendsFromService for {0}", client.Name); Boolean agentIsLocal = true; @@ -346,7 +345,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (agentIsLocal) // agent is local, friend is foreigner { - FriendInfo[] finfos = GetFriends(agentID); + FriendInfo[] finfos = GetFriendsFromCache(agentID); FriendInfo finfo = GetFriend(finfos, friendID); if (finfo != null) { @@ -453,7 +452,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends bool confirming = false; if (friendUUI == string.Empty) { - finfos = GetFriends(agentID); + finfos = GetFriendsFromCache(agentID); foreach (FriendInfo finfo in finfos) { if (finfo.TheirFlags == -1) @@ -546,7 +545,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Delete any previous friendship relations FriendInfo[] finfos = null; FriendInfo f = null; - finfos = GetFriends(a1); + finfos = GetFriendsFromCache(a1); if (finfos != null) { f = GetFriend(finfos, a2); @@ -558,7 +557,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends } } - finfos = GetFriends(a2); + finfos = GetFriendsFromCache(a2); if (finfos != null) { f = GetFriend(finfos, a1); @@ -595,7 +594,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (agentIsLocal) // agent is local, 'friend' is foreigner { // We need to look for its information in the friends list itself - FriendInfo[] finfos = GetFriends(agentID); + FriendInfo[] finfos = GetFriendsFromCache(agentID); FriendInfo finfo = GetFriend(finfos, exfriendID); if (finfo != null) { @@ -639,7 +638,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private string GetUUI(UUID localUser, UUID foreignUser) { // Let's see if the user is here by any chance - FriendInfo[] finfos = GetFriends(localUser); + FriendInfo[] finfos = GetFriendsFromCache(localUser); if (finfos != EMPTY_FRIENDS) // friend is here, cool { FriendInfo finfo = GetFriend(finfos, foreignUser); diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs index 682fbab142..45b4264c91 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/Tests/FriendModuleTests.cs @@ -30,6 +30,7 @@ using System.Collections.Generic; using Nini.Config; using NUnit.Framework; using OpenMetaverse; +using OpenSim.Data.Null; using OpenSim.Framework; using OpenSim.Region.CoreModules.Avatar.Friends; using OpenSim.Region.Framework.Scenes; @@ -44,9 +45,30 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests private FriendsModule m_fm; private TestScene m_scene; + [TestFixtureSetUp] + public void FixtureInit() + { + // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. + Util.FireAndForgetMethod = FireAndForgetMethod.RegressionTest; + } + + [TestFixtureTearDown] + public void TearDown() + { + // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple + // threads. Possibly, later tests should be rewritten so none of them require async stuff (which regression + // tests really shouldn't). + Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod; + } + [SetUp] public void Init() { + // We must clear friends data between tests since Data.Null holds it in static properties. This is necessary + // so that different services and simulator can share the data in standalone mode. This is pretty horrible + // effectively the statics are global variables. + NullFriendsData.Clear(); + IConfigSource config = new IniConfigSource(); config.AddConfig("Modules"); // Not strictly necessary since FriendsModule assumes it is the default (!) @@ -62,7 +84,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests } [Test] - public void TestNoFriends() + public void TestLoginWithNoFriends() { TestHelpers.InMethod(); // log4net.Config.XmlConfigurator.Configure(); @@ -75,6 +97,76 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends.Tests Assert.That(((TestClient)sp.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); } + [Test] + public void TestLoginWithOfflineFriends() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID user1Id = TestHelpers.ParseTail(0x1); + UUID user2Id = TestHelpers.ParseTail(0x2); + +// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); +// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); +// +// m_fm.AddFriendship(user1Id, user2Id); + + ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); + ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id); + + m_fm.AddFriendship(sp1.ControllingClient, user2Id); + + // Not necessary for this test. CanSeeOnline is automatically granted. +// m_fm.GrantRights(sp1.ControllingClient, user2Id, (int)FriendRights.CanSeeOnline); + + // We must logout from the client end so that the presence service is correctly updated by the presence + // detector. This is listening to the OnConnectionClosed event on the client. + ((TestClient)sp1.ControllingClient).Logout(); + ((TestClient)sp2.ControllingClient).Logout(); +// m_scene.RemoveClient(sp1.UUID, true); +// m_scene.RemoveClient(sp2.UUID, true); + + ScenePresence sp1Redux = SceneHelpers.AddScenePresence(m_scene, user1Id); + + // We don't expect to receive notifications of offline friends on login, just online. + Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); + Assert.That(((TestClient)sp1Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(0)); + } + + [Test] + public void TestLoginWithOnlineFriends() + { + TestHelpers.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + UUID user1Id = TestHelpers.ParseTail(0x1); + UUID user2Id = TestHelpers.ParseTail(0x2); + +// UserAccountHelpers.CreateUserWithInventory(m_scene, user1Id); +// UserAccountHelpers.CreateUserWithInventory(m_scene, user2Id); +// +// m_fm.AddFriendship(user1Id, user2Id); + + ScenePresence sp1 = SceneHelpers.AddScenePresence(m_scene, user1Id); + ScenePresence sp2 = SceneHelpers.AddScenePresence(m_scene, user2Id); + + m_fm.AddFriendship(sp1.ControllingClient, user2Id); + + // Not necessary for this test. CanSeeOnline is automatically granted. +// m_fm.GrantRights(sp1.ControllingClient, user2Id, (int)FriendRights.CanSeeOnline); + + // We must logout from the client end so that the presence service is correctly updated by the presence + // detector. This is listening to the OnConnectionClosed event on the client. +// ((TestClient)sp1.ControllingClient).Logout(); + ((TestClient)sp2.ControllingClient).Logout(); +// m_scene.RemoveClient(user2Id, true); + + ScenePresence sp2Redux = SceneHelpers.AddScenePresence(m_scene, user2Id); + + Assert.That(((TestClient)sp2Redux.ControllingClient).ReceivedOfflineNotifications.Count, Is.EqualTo(0)); + Assert.That(((TestClient)sp2Redux.ControllingClient).ReceivedOnlineNotifications.Count, Is.EqualTo(1)); + } + [Test] public void TestAddFriendshipWhileOnline() { diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs index aaba7fde36..6fc8e4d434 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/HGEntityTransferModule.cs @@ -71,7 +71,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer if (name == Name) { InitialiseCommon(source); - IConfig transferConfig = source.Configs["HGEntityTransfer"]; + IConfig transferConfig = source.Configs["HGEntityTransferModule"]; if (transferConfig != null) m_RestrictInventoryAccessAbroad = transferConfig.GetBoolean("RestrictInventoryAccessAbroad", false); @@ -94,6 +94,31 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer client.OnTeleportHomeRequest += TriggerTeleportHome; client.OnTeleportLandmarkRequest += RequestTeleportLandmark; client.OnConnectionClosed += new Action(OnConnectionClosed); + client.OnCompleteMovementToRegion += new Action(OnCompleteMovementToRegion); + } + + protected void OnCompleteMovementToRegion(IClientAPI client, bool arg2) + { + // HACK HACK -- just seeing how the viewer responds + // Let's send the Suitcase or the real root folder folder for incoming HG agents + // Visiting agents get their suitcase contents; incoming local users get their real root folder's content + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: OnCompleteMovementToRegion of user {0}", client.AgentId); + object sp = null; + if (client.Scene.TryGetScenePresence(client.AgentId, out sp)) + { + if (sp is ScenePresence) + { + AgentCircuitData aCircuit = ((ScenePresence)sp).Scene.AuthenticateHandler.GetAgentCircuitData(client.AgentId); + if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) + { + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: ViaHGLogin"); + if (m_RestrictInventoryAccessAbroad) + { + RestoreRootFolderContents(client); + } + } + } + } } @@ -105,6 +130,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer { m_GatekeeperConnector = new GatekeeperServiceConnector(scene.AssetService); m_Initialized = true; + + scene.AddCommand( + "HG", this, "send inventory", + "send inventory", + "Don't use this", + HandleSendInventory); + } } @@ -374,7 +406,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); if (root != null) { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory"); + m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Removing root inventory for user {0}", client.AgentId); InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); UUID[] ids = new UUID[content.Folders.Count]; int i = 0; @@ -393,12 +425,26 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer private void RestoreRootFolderContents(IClientAPI client) { - // Restore the user's inventory, because we removed it earlier on - InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); - if (root != null) + if (client is IClientCore) { - m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory"); - client.SendBulkUpdateInventory(root); + IClientCore core = (IClientCore)client; + IClientInventory inv; + + if (core.TryGet(out inv)) + { + InventoryFolderBase root = m_Scenes[0].InventoryService.GetRootFolder(client.AgentId); + client.SendBulkUpdateInventory(root); + //if (root != null) + //{ + // m_log.DebugFormat("[HG ENTITY TRANSFER MODULE]: Restoring root inventory for user {0}", client.AgentId); + // InventoryCollection content = m_Scenes[0].InventoryService.GetFolderContent(client.AgentId, root.ID); + // m_log.DebugFormat("[XXX]: Folder name {0}, id {1}, parent {2}", root.Name, root.ID, root.ParentID); + // foreach (InventoryItemBase i in content.Items) + // m_log.DebugFormat("[XXX]: Name={0}, folderID={1}", i.Name, i.Folder); + + // inv.SendBulkUpdateInventory(content.Folders.ToArray(), content.Items.ToArray()); + //} + } } } @@ -418,5 +464,14 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer region.InternalEndPoint = new System.Net.IPEndPoint(System.Net.IPAddress.Parse("0.0.0.0"), (int)0); return region; } + + protected void HandleSendInventory(string module, string[] cmd) + { + m_Scenes[0].ForEachClient(delegate(IClientAPI client) + { + RestoreRootFolderContents(client); + }); + } + } } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 192d55fd90..aa996924af 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -966,6 +966,30 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } + int primcount = 0; + foreach (SceneObjectGroup g in objlist) + primcount += g.PrimCount; + + if (!m_Scene.Permissions.CanRezObject( + primcount, remoteClient.AgentId, pos) + && !isAttachment) + { + // The client operates in no fail mode. It will + // have already removed the item from the folder + // if it's no copy. + // Put it back if it's not an attachment + // + if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!isAttachment)) + remoteClient.SendBulkUpdateInventory(item); + + ILandObject land = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); + remoteClient.SendAlertMessage(string.Format( + "Can't rez object '{0}' at <{1:F3}, {2:F3}, {3:F3}> on parcel '{4}' in region {5}.", + item.Name, pos.X, pos.Y, pos.Z, land != null ? land.LandData.Name : "Unknown", m_Scene.RegionInfo.RegionName)); + + return false; + } + for (int i = 0; i < objlist.Count; i++) { SceneObjectGroup so = objlist[i]; diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs index ef9b4e069b..176c86de12 100644 --- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs @@ -319,7 +319,7 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm // Send message to avatar if (channel == 0) { - m_scene.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Owner, 0, pos, name, id, false); + m_scene.SimChatBroadcast(Utils.StringToBytes(msg), ChatTypeEnum.Broadcast, 0, pos, name, id, false); } List attachments = sp.GetAttachments(); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs index 6d3ace92a2..3b862daa2f 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/MapImage/MapImageServiceModule.cs @@ -93,8 +93,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage if (config == null) return; - int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime")); - if (refreshminutes <= 0) + int refreshminutes = Convert.ToInt32(config.GetString("RefreshTime", "-1")); + if (refreshminutes < 0) { m_log.WarnFormat("[MAP IMAGE SERVICE MODULE]: No refresh time given in config. Module disabled."); return; @@ -117,12 +117,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage return; } - m_refreshTimer.Enabled = true; - m_refreshTimer.AutoReset = true; - m_refreshTimer.Interval = m_refreshtime; - m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); + if (m_refreshtime > 0) + { + m_refreshTimer.Enabled = true; + m_refreshTimer.AutoReset = true; + m_refreshTimer.Interval = m_refreshtime; + m_refreshTimer.Elapsed += new ElapsedEventHandler(HandleMaptileRefresh); + } - m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0}min and service object {1}", + m_log.InfoFormat("[MAP IMAGE SERVICE MODULE]: enabled with refresh time {0} min and service object {1}", refreshminutes, service); m_enabled = true; @@ -238,4 +241,4 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.MapImage } } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs index e2e383f060..ccfbf78a29 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Presence/PresenceDetector.cs @@ -27,14 +27,12 @@ using System; using System.Collections.Generic; using System.Reflection; - +using log4net; +using OpenMetaverse; using OpenSim.Framework; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; -using OpenMetaverse; -using log4net; - namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence { public class PresenceDetector @@ -97,7 +95,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Presence // m_log.DebugFormat("[PRESENCE DETECTOR]: Detected client logout {0} in {1}", client.AgentId, client.Scene.RegionInfo.RegionName); m_PresenceService.LogoutAgent(client.SessionId); } - } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index 4a654a38dd..82ccaf8264 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs @@ -487,7 +487,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return false; } - protected bool IsFriendWithPerms(UUID user,UUID objectOwner) + protected bool IsFriendWithPerms(UUID user, UUID objectOwner) { if (user == UUID.Zero) return false; @@ -495,11 +495,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions if (m_friendsModule == null) return false; - uint friendPerms = m_friendsModule.GetFriendPerms(user, objectOwner); - if ((friendPerms & (uint)FriendRights.CanModifyObjects) != 0) - return true; - - return false; + int friendPerms = m_friendsModule.GetRightsGrantedByFriend(user, objectOwner); + return (friendPerms & (int)FriendRights.CanModifyObjects) != 0; } protected bool IsEstateManager(UUID user) @@ -508,6 +505,7 @@ namespace OpenSim.Region.CoreModules.World.Permissions return m_scene.RegionInfo.EstateSettings.IsEstateManager(user); } + #endregion public bool PropagatePermissions() diff --git a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs index ab8e1bf0b7..f5f35bb92e 100644 --- a/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs +++ b/OpenSim/Region/CoreModules/World/Vegetation/VegetationModule.cs @@ -79,7 +79,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Vegetation } SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID); + SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID); // if grass or tree, make phantom //rootPart.TrimPermissions(); diff --git a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs index 6163fd12fe..e6f2855b25 100644 --- a/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/Warp3DMap/MapImageModule.cs @@ -64,6 +64,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap private bool m_useAntiAliasing = false; // TODO: Make this a config option private bool m_Enabled = false; + private Bitmap lastImage = null; + private DateTime lastImageTime = DateTime.MinValue; + #region IRegionModule Members public void Initialise(IConfigSource source) @@ -86,14 +89,9 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); if (renderers.Count > 0) - { - m_primMesher = RenderingLoader.LoadRenderer(renderers[0]); - m_log.Info("[MAPTILE]: Loaded prim mesher " + m_primMesher.ToString()); - } + m_log.Info("[MAPTILE]: Loaded prim mesher " + renderers[0]); else - { m_log.Info("[MAPTILE]: No prim mesher loaded, prim rendering will be disabled"); - } m_scene.RegisterModuleInterface(this); } @@ -126,9 +124,25 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap public Bitmap CreateMapTile() { + if ((DateTime.Now - lastImageTime).TotalSeconds < 3600) + { + return lastImage.Clone(new Rectangle(0, 0, 256, 256), lastImage.PixelFormat); + } + + List renderers = RenderingLoader.ListRenderers(Util.ExecutingDirectory()); + if (renderers.Count > 0) + { + m_primMesher = RenderingLoader.LoadRenderer(renderers[0]); + } + Vector3 camPos = new Vector3(127.5f, 127.5f, 221.7025033688163f); Viewport viewport = new Viewport(camPos, -Vector3.UnitZ, 1024f, 0.1f, (int)Constants.RegionSize, (int)Constants.RegionSize, (float)Constants.RegionSize, (float)Constants.RegionSize); - return CreateMapTile(viewport, false); + Bitmap tile = CreateMapTile(viewport, false); + m_primMesher = null; + + lastImage = tile; + lastImageTime = DateTime.Now; + return lastImage.Clone(new Rectangle(0, 0, 256, 256), lastImage.PixelFormat); } public Bitmap CreateViewImage(Vector3 camPos, Vector3 camDir, float fov, int width, int height, bool useTextures) @@ -655,4 +669,4 @@ namespace OpenSim.Region.CoreModules.World.Warp3DMap return result; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs b/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs new file mode 100644 index 0000000000..69682aca0d --- /dev/null +++ b/OpenSim/Region/Framework/Interfaces/ICallingCardModule.cs @@ -0,0 +1,40 @@ +/* + * 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.Text; +using OpenMetaverse; +using OpenSim.Framework; + +namespace OpenSim.Framework +{ + public interface ICallingCardModule + { + UUID CreateCallingCard(UUID userID, UUID creatorID, UUID folderID); + } +} diff --git a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs index 061799e394..7e87006706 100644 --- a/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IFriendsModule.cs @@ -25,14 +25,31 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System.Collections.Generic; using OpenMetaverse; using OpenSim.Framework; -using System.Collections.Generic; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; namespace OpenSim.Region.Framework.Interfaces { public interface IFriendsModule { + /// + /// Are friends cached on this simulator for a particular user? + /// + /// + /// + bool AreFriendsCached(UUID userID); + + /// + /// Get friends from local cache only + /// + /// + /// + /// An empty array if the user has no friends or friends have not been cached. + /// + FriendInfo[] GetFriendsFromCache(UUID userID); + /// /// Add a friendship between two users. /// @@ -55,7 +72,27 @@ namespace OpenSim.Region.Framework.Interfaces /// void RemoveFriendship(IClientAPI client, UUID exFriendID); - uint GetFriendPerms(UUID PrincipalID, UUID FriendID); + /// + /// Get permissions granted by a friend. + /// + /// The user. + /// The friend that granted. + /// The permissions. These come from the FriendRights enum. + int GetRightsGrantedByFriend(UUID userID, UUID friendID); + + /// + /// Grant permissions for a friend. + /// + /// + /// This includes giving them the ability to see when the user is online and permission to edit the user's + /// objects. + /// Granting lower permissions than the friend currently has will rescind the extra permissions. + /// + /// The user granting the permissions. + /// The friend. + /// These come from the FriendRights enum. + void GrantRights(IClientAPI remoteClient, UUID friendID, int perms); + bool SendFriendsOnlineIfNeeded(IClientAPI client); } -} +} \ No newline at end of file diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index 470ce2e4a1..741d23336e 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -75,6 +75,7 @@ namespace OpenSim.Region.Framework.Scenes /// Triggered when a new client is added to the scene. /// /// + /// This is triggered for both child and root agent client connections. /// Triggered before OnClientLogin. /// public event OnNewClientDelegate OnNewClient; @@ -195,7 +196,7 @@ namespace OpenSim.Region.Framework.Scenes public delegate void ClientClosed(UUID clientID, Scene scene); /// - /// Fired when a client is removed from a scene. + /// Fired when a client is removed from a scene whether it's a child or a root agent. /// /// /// At the point of firing, the scene still contains the client's scene presence. diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index cac178d3f6..539ca14410 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -1883,7 +1883,7 @@ namespace OpenSim.Region.Framework.Scenes { AddRestoredSceneObject(group, true, true); EventManager.TriggerOnSceneObjectLoaded(group); - SceneObjectPart rootPart = group.GetChildPart(group.UUID); + SceneObjectPart rootPart = group.GetPart(group.UUID); rootPart.Flags &= ~PrimFlags.Scripted; rootPart.TrimPermissions(); @@ -2031,10 +2031,16 @@ namespace OpenSim.Region.Framework.Scenes if (Permissions.CanRezObject(1, ownerID, pos)) { // rez ON the ground, not IN the ground - // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground + // pos.Z += 0.25F; The rez point should now be correct so that its not in the ground AddNewPrim(ownerID, groupID, pos, rot, shape); } + else + { + IClientAPI client = null; + if (TryGetClient(ownerID, out client)) + client.SendAlertMessage("You cannot create objects here."); + } } public virtual SceneObjectGroup AddNewPrim( @@ -2795,6 +2801,10 @@ namespace OpenSim.Region.Framework.Scenes sp.IsChildAgent ? "child" : "root", sp.Name, RegionInfo.RegionName); } + // We must set this here so that TriggerOnNewClient and TriggerOnClientLogin can determine whether the + // client is for a root or child agent. + client.SceneAgent = sp; + m_LastLogin = Util.EnvironmentTickCount(); // Cache the user's name @@ -4344,7 +4354,7 @@ namespace OpenSim.Region.Framework.Scenes { if (ent is SceneObjectGroup) { - SceneObjectPart part = ((SceneObjectGroup)ent).GetChildPart(((SceneObjectGroup)ent).UUID); + SceneObjectPart part = ((SceneObjectGroup)ent).GetPart(((SceneObjectGroup)ent).UUID); if (part != null) { if (part.Name == cmdparams[2]) diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index ccc3f32467..9fdbc54e5f 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -941,7 +941,7 @@ namespace OpenSim.Region.Framework.Scenes if (sog != null) { - if (sog.HasChildPrim(localID)) + if (sog.ContainsPart(localID)) { // m_log.DebugFormat( // "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.", @@ -969,7 +969,7 @@ namespace OpenSim.Region.Framework.Scenes if (ent is SceneObjectGroup) { sog = (SceneObjectGroup)ent; - if (sog.HasChildPrim(localID)) + if (sog.ContainsPart(localID)) { lock (SceneObjectGroupsByLocalPartID) SceneObjectGroupsByLocalPartID[localID] = sog; @@ -1007,7 +1007,7 @@ namespace OpenSim.Region.Framework.Scenes if (ent is SceneObjectGroup) { sog = (SceneObjectGroup)ent; - if (sog.HasChildPrim(fullID)) + if (sog.ContainsPart(fullID)) { lock (SceneObjectGroupsByFullPartID) SceneObjectGroupsByFullPartID[fullID] = sog; @@ -1096,7 +1096,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(localID); if (group == null) return null; - return group.GetChildPart(localID); + return group.GetPart(localID); } /// @@ -1143,7 +1143,7 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectGroup group = GetGroupByPrim(fullID); if (group == null) return null; - return group.GetChildPart(fullID); + return group.GetPart(fullID); } /// diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index f3660a5659..2effa251c7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -92,7 +92,7 @@ namespace OpenSim.Region.Framework.Scenes UUID newItemId = (copyItemID != UUID.Zero) ? copyItemID : item.ID; - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { TaskInventoryItem taskItem = new TaskInventoryItem(); @@ -166,7 +166,7 @@ namespace OpenSim.Region.Framework.Scenes /// null if the item does not exist public TaskInventoryItem GetInventoryItem(uint primID, UUID itemID) { - SceneObjectPart part = GetChildPart(primID); + SceneObjectPart part = GetPart(primID); if (part != null) { return part.Inventory.GetInventoryItem(itemID); @@ -190,7 +190,7 @@ namespace OpenSim.Region.Framework.Scenes /// false if the item did not exist, true if the update occurred succesfully public bool UpdateInventoryItem(TaskInventoryItem item) { - SceneObjectPart part = GetChildPart(item.ParentPartID); + SceneObjectPart part = GetPart(item.ParentPartID); if (part != null) { part.Inventory.UpdateInventoryItem(item); @@ -210,7 +210,7 @@ namespace OpenSim.Region.Framework.Scenes public int RemoveInventoryItem(uint localID, UUID itemID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { int type = part.Inventory.RemoveInventoryItem(itemID); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 90ad098556..11fd7215e5 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -412,6 +412,24 @@ namespace OpenSim.Region.Framework.Scenes return m_parts.ContainsKey(partID); } + /// + /// Does this group contain the given part? + /// should be able to remove these methods once we have a entity index in scene + /// + /// + /// + public bool ContainsPart(uint localID) + { + SceneObjectPart[] parts = m_parts.GetArray(); + for (int i = 0; i < parts.Length; i++) + { + if (parts[i].LocalId == localID) + return true; + } + + return false; + } + /// /// The root part of this scene object /// @@ -1636,7 +1654,7 @@ namespace OpenSim.Region.Framework.Scenes public UUID GetPartsFullID(uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { return part.UUID; @@ -1652,7 +1670,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - SceneObjectPart part = GetChildPart(localId); + SceneObjectPart part = GetPart(localId); OnGrabPart(part, offsetPos, remoteClient); } } @@ -2513,8 +2531,8 @@ namespace OpenSim.Region.Framework.Scenes /// Get a part with a given UUID /// /// - /// null if a child part with the primID was not found - public SceneObjectPart GetChildPart(UUID primID) + /// null if a part with the primID was not found + public SceneObjectPart GetPart(UUID primID) { SceneObjectPart childPart; m_parts.TryGetValue(primID, out childPart); @@ -2525,8 +2543,8 @@ namespace OpenSim.Region.Framework.Scenes /// Get a part with a given local ID /// /// - /// null if a child part with the local ID was not found - public SceneObjectPart GetChildPart(uint localID) + /// null if a part with the local ID was not found + public SceneObjectPart GetPart(uint localID) { SceneObjectPart[] parts = m_parts.GetArray(); for (int i = 0; i < parts.Length; i++) @@ -2538,35 +2556,6 @@ namespace OpenSim.Region.Framework.Scenes return null; } - /// - /// Does this group contain the child prim - /// should be able to remove these methods once we have a entity index in scene - /// - /// - /// - public bool HasChildPrim(UUID primID) - { - return m_parts.ContainsKey(primID); - } - - /// - /// Does this group contain the child prim - /// should be able to remove these methods once we have a entity index in scene - /// - /// - /// - public bool HasChildPrim(uint localID) - { - SceneObjectPart[] parts = m_parts.GetArray(); - for (int i = 0; i < parts.Length; i++) - { - if (parts[i].LocalId == localID) - return true; - } - - return false; - } - #endregion #region Packet Handlers @@ -2720,7 +2709,7 @@ namespace OpenSim.Region.Framework.Scenes /// The object group of the newly delinked prim. Null if part could not be found public SceneObjectGroup DelinkFromGroup(uint partID, bool sendEvents) { - SceneObjectPart linkPart = GetChildPart(partID); + SceneObjectPart linkPart = GetPart(partID); if (linkPart != null) { @@ -3024,7 +3013,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void SetPartName(string name, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.Name = name; @@ -3033,7 +3022,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetPartDescription(string des, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.Description = des; @@ -3042,7 +3031,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetPartText(string text, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.SetText(text); @@ -3051,7 +3040,7 @@ namespace OpenSim.Region.Framework.Scenes public void SetPartText(string text, UUID partID) { - SceneObjectPart part = GetChildPart(partID); + SceneObjectPart part = GetPart(partID); if (part != null) { part.SetText(text); @@ -3060,7 +3049,7 @@ namespace OpenSim.Region.Framework.Scenes public string GetPartName(uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { return part.Name; @@ -3070,7 +3059,7 @@ namespace OpenSim.Region.Framework.Scenes public string GetPartDescription(uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { return part.Description; @@ -3088,7 +3077,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdatePrimFlags(uint localID, bool UsePhysics, bool SetTemporary, bool SetPhantom, bool SetVolumeDetect) { - SceneObjectPart selectionPart = GetChildPart(localID); + SceneObjectPart selectionPart = GetPart(localID); if (SetTemporary && Scene != null) { @@ -3148,7 +3137,7 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateExtraParam(uint localID, ushort type, bool inUse, byte[] data) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.UpdateExtraParam(type, inUse, data); @@ -3173,7 +3162,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateTextureEntry(uint localID, byte[] textureEntry) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.UpdateTextureEntry(textureEntry); @@ -3205,7 +3194,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateShape(ObjectShapePacket.ObjectDataBlock shapeBlock, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { part.UpdateShape(shapeBlock); @@ -3395,7 +3384,7 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateSinglePosition(Vector3 pos, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { @@ -3508,7 +3497,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateSingleRotation(Quaternion rot, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); + SceneObjectPart[] parts = m_parts.GetArray(); if (part != null) @@ -3537,7 +3527,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void UpdateSingleRotation(Quaternion rot, Vector3 pos, uint localID) { - SceneObjectPart part = GetChildPart(localID); + SceneObjectPart part = GetPart(localID); if (part != null) { if (m_rootPart.PhysActor != null) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index ac44ce9402..a2649eed91 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -815,7 +815,7 @@ namespace OpenSim.Region.Framework.Scenes group.ResetIDs(); - SceneObjectPart rootPart = group.GetChildPart(group.UUID); + SceneObjectPart rootPart = group.GetPart(group.UUID); // Since renaming the item in the inventory does not affect the name stored // in the serialization, transfer the correct name from the inventory to the diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index ee8a236f50..ed3a7f11fa 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -1237,22 +1237,6 @@ namespace OpenSim.Region.Framework.Scenes friendsModule.SendFriendsOnlineIfNeeded(ControllingClient); } - // HACK HACK -- just seeing how the viewer responds - // Let's send the Suitcase or the real root folder folder for incoming HG agents - // Visiting agents get their suitcase contents; incoming local users get their real root folder's content - AgentCircuitData aCircuit = m_scene.AuthenticateHandler.GetAgentCircuitData(UUID); - if ((aCircuit.teleportFlags & (uint)Constants.TeleportFlags.ViaHGLogin) != 0) - { - // HACK FOR NOW. JUST TESTING, SO KEEPING EVERYONE ELSE OUT OF THESE TESTS - IConfig config = m_scene.Config.Configs["HGEntityTransferModule"]; - if (config != null && config.GetBoolean("RestrictInventoryAccessAbroad", false)) - { - m_log.DebugFormat("[SCENE]: Sending root folder to viewer..."); - InventoryFolderBase root = m_scene.InventoryService.GetRootFolder(client.AgentId); - //InventoryCollection rootContents = InventoryService.GetFolderContent(client.AgentId, root.ID); - client.SendBulkUpdateInventory(root); - } - } // m_log.DebugFormat( // "[SCENE PRESENCE]: Completing movement of {0} into region {1} took {2}ms", diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 655f3a5097..a37e99714d 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server private UUID m_agentID = UUID.Random(); - public ISceneAgent SceneAgent { get; private set; } + public ISceneAgent SceneAgent { get; set; } private string m_username; private string m_nick; @@ -903,7 +903,7 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void Start() { - SceneAgent = m_scene.AddNewClient(this, PresenceType.User); + m_scene.AddNewClient(this, PresenceType.User); // Mimicking LLClientView which gets always set appearance from client. AvatarAppearance appearance; diff --git a/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs new file mode 100644 index 0000000000..e68f9d07a3 --- /dev/null +++ b/OpenSim/Region/OptionalModules/Avatar/Friends/FriendsCommandsModule.cs @@ -0,0 +1,189 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using System.Reflection; +using System.Text; +using log4net; +using Mono.Addins; +using NDesk.Options; +using Nini.Config; +using OpenMetaverse; +using OpenSim.Framework; +using OpenSim.Framework.Console; +using OpenSim.Framework.Statistics; +using OpenSim.Region.ClientStack.LindenUDP; +using OpenSim.Region.CoreModules.Avatar.Friends; +using OpenSim.Region.Framework.Interfaces; +using OpenSim.Region.Framework.Scenes; +using OpenSim.Services.Interfaces; +using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; + +namespace OpenSim.Region.OptionalModules.Avatar.Friends +{ + /// + /// A module that just holds commands for inspecting avatar appearance. + /// + [Extension(Path = "/OpenSim/RegionModules", NodeName = "RegionModule", Id = "FriendsCommandModule")] + public class FriendsCommandsModule : ISharedRegionModule + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private Scene m_scene; + private IFriendsModule m_friendsModule; + private IUserManagement m_userManagementModule; + +// private IAvatarFactoryModule m_avatarFactory; + + public string Name { get { return "Appearance Information Module"; } } + + public Type ReplaceableInterface { get { return null; } } + + public void Initialise(IConfigSource source) + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: INITIALIZED MODULE"); + } + + public void PostInitialise() + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: POST INITIALIZED MODULE"); + } + + public void Close() + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: CLOSED MODULE"); + } + + public void AddRegion(Scene scene) + { +// m_log.DebugFormat("[FRIENDS COMMANDO MODULE]: REGION {0} ADDED", scene.RegionInfo.RegionName); + } + + public void RemoveRegion(Scene scene) + { +// m_log.DebugFormat("[FRIENDS COMMAND MODULE]: REGION {0} REMOVED", scene.RegionInfo.RegionName); + } + + public void RegionLoaded(Scene scene) + { +// m_log.DebugFormat("[APPEARANCE INFO MODULE]: REGION {0} LOADED", scene.RegionInfo.RegionName); + + if (m_scene == null) + m_scene = scene; + + m_friendsModule = m_scene.RequestModuleInterface(); + m_userManagementModule = m_scene.RequestModuleInterface(); + + if (m_friendsModule != null && m_userManagementModule != null) + { + m_scene.AddCommand( + "Friends", this, "friends show", + "friends show [--cache] ", + "Show the friends for the given user if they exist.\n", + "The --cache option will show locally cached information for that user.", + HandleFriendsShowCommand); + } + } + + protected void HandleFriendsShowCommand(string module, string[] cmd) + { + Dictionary options = new Dictionary(); + OptionSet optionSet = new OptionSet().Add("c|cache", delegate (string v) { options["cache"] = v != null; }); + + List mainParams = optionSet.Parse(cmd); + + if (mainParams.Count != 4) + { + MainConsole.Instance.OutputFormat("Usage: friends show [--cache] "); + return; + } + + string firstName = mainParams[2]; + string lastName = mainParams[3]; + + UUID userId = m_userManagementModule.GetUserIdByName(firstName, lastName); + +// UserAccount ua +// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, firstName, lastName); + + if (userId == UUID.Zero) + { + MainConsole.Instance.OutputFormat("No such user as {0} {1}", firstName, lastName); + return; + } + + FriendInfo[] friends; + + if (options.ContainsKey("cache")) + { + if (!m_friendsModule.AreFriendsCached(userId)) + { + MainConsole.Instance.OutputFormat("No friends cached on this simulator for {0} {1}", firstName, lastName); + return; + } + else + { + friends = m_friendsModule.GetFriendsFromCache(userId); + } + } + else + { + // FIXME: We're forced to do this right now because IFriendsService has no region connectors. We can't + // just expose FriendsModule.GetFriendsFromService() because it forces an IClientAPI requirement that + // can't currently be changed because of HGFriendsModule code that takes the scene from the client. + friends = ((FriendsModule)m_friendsModule).FriendsService.GetFriends(userId); + } + + MainConsole.Instance.OutputFormat("Friends for {0} {1} {2}:", firstName, lastName, userId); + + MainConsole.Instance.OutputFormat("UUID, Name, MyFlags, TheirFlags"); + + foreach (FriendInfo friend in friends) + { +// MainConsole.Instance.OutputFormat(friend.PrincipalID.ToString()); + +// string friendFirstName, friendLastName; +// +// UserAccount friendUa +// = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, friend.PrincipalID); + + UUID friendId; + string friendName; + + if (UUID.TryParse(friend.Friend, out friendId)) + friendName = m_userManagementModule.GetUserName(friendId); + else + friendName = friend.Friend; + + MainConsole.Instance.OutputFormat( + "{0} {1} {2} {3}", friend.Friend, friendName, friend.MyFlags, friend.TheirFlags); + } + } + } +} \ No newline at end of file diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index a2375fe548..c3335f099e 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -72,7 +72,7 @@ namespace OpenSim.Region.OptionalModules.World.NPC get { return m_ownerID; } } - public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } + public ISceneAgent SceneAgent { get; set; } public void Say(string message) { diff --git a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs index a17eb41740..51b0592356 100644 --- a/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs +++ b/OpenSim/Region/OptionalModules/World/TreePopulator/TreePopulatorModule.cs @@ -510,7 +510,7 @@ namespace OpenSim.Region.OptionalModules.World.TreePopulator } SceneObjectGroup sceneObject = new SceneObjectGroup(ownerID, pos, rot, shape); - SceneObjectPart rootPart = sceneObject.GetChildPart(sceneObject.UUID); + SceneObjectPart rootPart = sceneObject.GetPart(sceneObject.UUID); rootPart.AddFlag(PrimFlags.Phantom); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 4d7c40eb46..ce05b8ccf9 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4214,7 +4214,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api World.ForEachRootScenePresence(delegate(ScenePresence presence) { SceneObjectPart sitPart = presence.ParentPart; - if (sitPart != null && m_host.ParentGroup.HasChildPrim(sitPart.LocalId)) + if (sitPart != null && m_host.ParentGroup.ContainsPart(sitPart.LocalId)) nametable.Add(presence.ControllingClient.Name); }); @@ -4680,12 +4680,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // agent must not be a god if (presence.GodLevel >= 200) return; + if (simname == String.Empty) + simname = World.RegionInfo.RegionName; + // agent must be over the owners land if (m_host.OwnerID == World.LandChannel.GetLandObject( presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) { World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation); } + else // or must be wearing the prim + { + if (m_host.ParentGroup.AttachmentPoint != 0 && m_host.OwnerID == presence.UUID) + { + World.RequestTeleportLocation(presence.ControllingClient, simname, new Vector3((float)pos.x, (float)pos.y, (float)pos.z), new Vector3((float)lookAt.x, (float)lookAt.y, (float)lookAt.z), (uint)TeleportFlags.ViaLocation); + } + } } } } diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs new file mode 100644 index 0000000000..cb686e26e6 --- /dev/null +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -0,0 +1,466 @@ +/* + * Copyright (c) Contributors, http://opensimulator.org/ + * See CONTRIBUTORS.TXT for a full list of copyright holders. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * * Neither the name of the OpenSimulator Project nor the + * names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY + * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED + * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY + * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; + * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +using System; +using System.Collections.Generic; +using System.Linq; +using OpenMetaverse; +using log4net; +using Nini.Config; +using System.Reflection; +using OpenSim.Services.Base; +using OpenSim.Services.Interfaces; +using OpenSim.Services.InventoryService; +using OpenSim.Data; +using OpenSim.Framework; +using OpenSim.Server.Base; + +namespace OpenSim.Services.HypergridService +{ + /// + /// Hypergrid inventory service. It serves the IInventoryService interface, + /// but implements it in ways that are appropriate for inter-grid + /// inventory exchanges. Specifically, it does not performs deletions + /// and it responds to GetRootFolder requests with the ID of the + /// Suitcase folder, not the actual "My Inventory" folder. + /// + public class HGSuitcaseInventoryService : XInventoryService, IInventoryService + { + private static readonly ILog m_log = + LogManager.GetLogger( + MethodBase.GetCurrentMethod().DeclaringType); + + private string m_HomeURL; + private IUserAccountService m_UserAccountService; + + private UserAccountCache m_Cache; + + private ExpiringCache> m_SuitcaseTrees = new ExpiringCache>(); + + public HGSuitcaseInventoryService(IConfigSource config, string configName) + : base(config, configName) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Starting with config name {0}", configName); + if (configName != string.Empty) + m_ConfigName = configName; + + if (m_Database == null) + m_log.WarnFormat("[XXX]: m_Database is null!"); + + // + // Try reading the [InventoryService] section, if it exists + // + IConfig invConfig = config.Configs[m_ConfigName]; + if (invConfig != null) + { + // realm = authConfig.GetString("Realm", realm); + string userAccountsDll = invConfig.GetString("UserAccountsService", string.Empty); + if (userAccountsDll == string.Empty) + throw new Exception("Please specify UserAccountsService in HGInventoryService configuration"); + + Object[] args = new Object[] { config }; + m_UserAccountService = ServerUtils.LoadPlugin(userAccountsDll, args); + if (m_UserAccountService == null) + throw new Exception(String.Format("Unable to create UserAccountService from {0}", userAccountsDll)); + + // legacy configuration [obsolete] + m_HomeURL = invConfig.GetString("ProfileServerURI", string.Empty); + // Preferred + m_HomeURL = invConfig.GetString("HomeURI", m_HomeURL); + + m_Cache = UserAccountCache.CreateUserAccountCache(m_UserAccountService); + } + + m_log.Debug("[HG SUITCASE INVENTORY SERVICE]: Starting..."); + } + + public override bool CreateUserInventory(UUID principalID) + { + // NOGO + return false; + } + + + public override List GetInventorySkeleton(UUID principalID) + { + // NOGO for this inventory service + return new List(); + } + + public override InventoryFolderBase GetRootFolder(UUID principalID) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetRootFolder for {0}", principalID); + if (m_Database == null) + m_log.ErrorFormat("[XXX]: m_Database is NULL!"); + + // Let's find out the local root folder + XInventoryFolder root = GetRootXFolder(principalID); ; + if (root == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to retrieve local root folder for user {0}", principalID); + } + + // Warp! Root folder for travelers is the suitcase folder + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + + if (suitcase == null) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: User {0} does not have a Suitcase folder. Creating it...", principalID); + // make one, and let's add it to the user's inventory as a direct child of the root folder + suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase"); + if (suitcase == null) + m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder"); + + m_Database.StoreFolder(suitcase); + } + + // Now let's change the folder ID to match that of the real root folder + SetAsRootFolder(suitcase, root.folderID); + + return ConvertToOpenSim(suitcase); + } + + public override InventoryFolderBase GetFolderForType(UUID principalID, AssetType type) + { + //m_log.DebugFormat("[HG INVENTORY SERVICE]: GetFolderForType for {0} {0}", principalID, type); + return GetRootFolder(principalID); + } + + public override InventoryCollection GetFolderContent(UUID principalID, UUID folderID) + { + InventoryCollection coll = null; + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + XInventoryFolder root = GetRootXFolder(principalID); + + if (!IsWithinSuitcaseTree(folderID, root, suitcase)) + return new InventoryCollection(); + + if (folderID == root.folderID) // someone's asking for the root folder, we'll give them the suitcase + { + if (suitcase != null) + { + coll = base.GetFolderContent(principalID, suitcase.folderID); + foreach (InventoryFolderBase f in coll.Folders) + f.ParentID = root.folderID; + foreach (InventoryItemBase i in coll.Items) + i.Folder = root.folderID; + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for root folder returned content for suitcase folder"); + } + } + else + { + coll = base.GetFolderContent(principalID, folderID); + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent for non-root folder {0}", folderID); + } + if (coll == null) + { + m_log.WarnFormat("[HG SUITCASE INVENTORY SERVICE]: Something wrong with user {0}'s suitcase folder", principalID); + coll = new InventoryCollection(); + } + return coll; + } + + public override List GetFolderItems(UUID principalID, UUID folderID) + { + // Let's do a bit of sanity checking, more than the base service does + // make sure the given folder exists under the suitcase tree of this user + XInventoryFolder root = GetRootXFolder(principalID); + XInventoryFolder suitcase = GetSuitcaseXFolder(principalID); + + if (!IsWithinSuitcaseTree(folderID, root, suitcase)) + return new List(); + + return base.GetFolderItems(principalID, folderID); + } + + public override bool AddFolder(InventoryFolderBase folder) + { + // Let's do a bit of sanity checking, more than the base service does + // make sure the given folder's parent folder exists under the suitcase tree of this user + XInventoryFolder root = GetRootXFolder(folder.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); + + if (!IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) + return false; + + // OK, it's legit + // Check if it's under the Root folder directly + if (folder.ParentID == root.folderID) + { + // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder for root folder for user {0}. Adding in suitcase instead", folder.Owner); + folder.ParentID = suitcase.folderID; + } + + return base.AddFolder(folder); + } + + public bool UpdateFolder(InventoryFolderBase folder) + { + XInventoryFolder root = GetRootXFolder(folder.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); + + if (!IsWithinSuitcaseTree(folder.ID, root, suitcase)) + return false; + + return base.UpdateFolder(folder); + } + + public override bool MoveFolder(InventoryFolderBase folder) + { + XInventoryFolder root = GetRootXFolder(folder.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(folder.Owner); + + if (!IsWithinSuitcaseTree(folder.ID, root, suitcase) || !IsWithinSuitcaseTree(folder.ParentID, root, suitcase)) + return false; + + if (folder.ParentID == root.folderID) + { + // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder to root folder for user {0}. Moving it to suitcase instead", folder.Owner); + folder.ParentID = suitcase.folderID; + } + + return base.MoveFolder(folder); + } + + public override bool DeleteFolders(UUID principalID, List folderIDs) + { + // NOGO + return false; + } + + public override bool PurgeFolder(InventoryFolderBase folder) + { + // NOGO + return false; + } + + public override bool AddItem(InventoryItemBase item) + { + // Let's do a bit of sanity checking, more than the base service does + // make sure the given folder's parent folder exists under the suitcase tree of this user + XInventoryFolder root = GetRootXFolder(item.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); + + if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + return false; + + // OK, it's legit + // Check if it's under the Root folder directly + if (item.Folder == root.folderID) + { + // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddItem for root folder for user {0}. Adding in suitcase instead", item.Owner); + item.Folder = suitcase.folderID; + } + + return base.AddItem(item); + + } + + public override bool UpdateItem(InventoryItemBase item) + { + XInventoryFolder root = GetRootXFolder(item.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(item.Owner); + + if (!IsWithinSuitcaseTree(item.Folder, root, suitcase)) + return false; + + return base.UpdateItem(item); + } + + public override bool MoveItems(UUID principalID, List items) + { + // Principal is b0rked. *sigh* + + XInventoryFolder root = GetRootXFolder(items[0].Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(items[0].Owner); + + if (!IsWithinSuitcaseTree(items[0].Folder, root, suitcase)) + return false; + + foreach (InventoryItemBase it in items) + if (it.Folder == root.folderID) + { + // someone's trying to add a subfolder of the root folder, we'll add it to the suitcase instead + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItem to root folder for user {0}. Moving it to suitcase instead", it.Owner); + it.Folder = suitcase.folderID; + } + + return base.MoveItems(principalID, items); + + } + + // Let these pass. Use inherited methods. + public override bool DeleteItems(UUID principalID, List itemIDs) + { + return false; + } + + public override InventoryItemBase GetItem(InventoryItemBase item) + { + InventoryItemBase it = base.GetItem(item); + XInventoryFolder root = GetRootXFolder(it.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(it.Owner); + + if (it != null) + { + if (!IsWithinSuitcaseTree(it.Folder, root, suitcase)) + return null; + + if (it.Folder == suitcase.folderID) + it.Folder = root.folderID; + + // UserAccount user = m_Cache.GetUser(it.CreatorId); + + // // Adjust the creator data + // if (user != null && it != null && (it.CreatorData == null || it.CreatorData == string.Empty)) + // it.CreatorData = m_HomeURL + ";" + user.FirstName + " " + user.LastName; + //} + } + + return it; + } + + public override InventoryFolderBase GetFolder(InventoryFolderBase folder) + { + InventoryFolderBase f = base.GetFolder(folder); + XInventoryFolder root = GetRootXFolder(f.Owner); + XInventoryFolder suitcase = GetSuitcaseXFolder(f.Owner); + + if (f != null) + { + if (!IsWithinSuitcaseTree(f.ID, root, suitcase)) + return null; + + if (f.ParentID == suitcase.folderID) + f.ParentID = root.folderID; + } + + return f; + } + + //public List GetActiveGestures(UUID principalID) + //{ + //} + + //public int GetAssetPermissions(UUID principalID, UUID assetID) + //{ + //} + + #region Auxiliary functions + private XInventoryFolder GetXFolder(UUID userID, UUID folderID) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "folderID" }, + new string[] { userID.ToString(), folderID.ToString() }); + + if (folders.Length == 0) + return null; + + return folders[0]; + } + + private XInventoryFolder GetRootXFolder(UUID principalID) + { + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "folderName", "type" }, + new string[] { principalID.ToString(), "My Inventory", ((int)AssetType.RootFolder).ToString() }); + + if (folders != null && folders.Length > 0) + return folders[0]; + return null; + } + + private XInventoryFolder GetSuitcaseXFolder(UUID principalID) + { + // Warp! Root folder for travelers + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "agentID", "type" }, + new string[] { principalID.ToString(), "100" }); // This is a special folder type... + + if (folders != null && folders.Length > 0) + return folders[0]; + return null; + } + + private void SetAsRootFolder(XInventoryFolder suitcase, UUID rootID) + { + suitcase.folderID = rootID; + suitcase.parentFolderID = UUID.Zero; + } + + private List GetFolderTree(UUID root) + { + List t = null; + if (m_SuitcaseTrees.TryGetValue(root, out t)) + return t; + + t = GetFolderTreeRecursive(root); + m_SuitcaseTrees.AddOrUpdate(root, t, 120); + return t; + } + + private List GetFolderTreeRecursive(UUID root) + { + List tree = new List(); + XInventoryFolder[] folders = m_Database.GetFolders( + new string[] { "parentFolderID" }, + new string[] { root.ToString() }); + + if (folders == null || (folders != null && folders.Length == 0)) + return tree; // empty tree + else + { + foreach (XInventoryFolder f in folders) + { + tree.Add(f); + tree.AddRange(GetFolderTreeRecursive(f.folderID)); + } + return tree; + } + + } + + private bool IsWithinSuitcaseTree(UUID folderID, XInventoryFolder root, XInventoryFolder suitcase) + { + List tree = new List(); + tree.Add(root); // Warp! the tree is the real root folder plus the children of the suitcase folder + tree.AddRange(GetFolderTree(suitcase.folderID)); + XInventoryFolder f = tree.Find(delegate(XInventoryFolder fl) + { + if (fl.folderID == folderID) return true; + else return false; + }); + + if (f == null) return false; + else return true; + } + #endregion + } +} diff --git a/OpenSim/Services/Interfaces/IFriendsService.cs b/OpenSim/Services/Interfaces/IFriendsService.cs index 1664f3b3e1..d0d3b1002d 100644 --- a/OpenSim/Services/Interfaces/IFriendsService.cs +++ b/OpenSim/Services/Interfaces/IFriendsService.cs @@ -36,7 +36,15 @@ namespace OpenSim.Services.Interfaces { public UUID PrincipalID; public string Friend; + + /// + /// The permissions that this user has granted to the friend. + /// public int MyFlags; + + /// + /// The permissions that the friend has granted to this user. + /// public int TheirFlags; public FriendInfo() @@ -51,7 +59,7 @@ namespace OpenSim.Services.Interfaces Friend = string.Empty; if (kvp.ContainsKey("Friend") && kvp["Friend"] != null) Friend = kvp["Friend"].ToString(); - MyFlags = 0; + MyFlags = (int)FriendRights.None; if (kvp.ContainsKey("MyFlags") && kvp["MyFlags"] != null) Int32.TryParse(kvp["MyFlags"].ToString(), out MyFlags); TheirFlags = 0; diff --git a/OpenSim/Services/PresenceService/PresenceService.cs b/OpenSim/Services/PresenceService/PresenceService.cs index c8ac38e63a..ed2703eda5 100644 --- a/OpenSim/Services/PresenceService/PresenceService.cs +++ b/OpenSim/Services/PresenceService/PresenceService.cs @@ -151,11 +151,12 @@ namespace OpenSim.Services.PresenceService info.Add(ret); } + +// m_log.DebugFormat( +// "[PRESENCE SERVICE]: GetAgents for {0} found {1} presences", userIDStr, data.Length); } - // m_log.DebugFormat("[PRESENCE SERVICE]: GetAgents for {0} userIDs found {1} presences", userIDs.Length, info.Count); return info.ToArray(); } - } -} +} \ No newline at end of file diff --git a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs index 7bf08ae702..318758d984 100644 --- a/OpenSim/Tests/Common/Helpers/SceneHelpers.cs +++ b/OpenSim/Tests/Common/Helpers/SceneHelpers.cs @@ -369,8 +369,11 @@ namespace OpenSim.Tests.Common agentData.AgentID = agentId; agentData.firstname = firstName; agentData.lastname = "testlastname"; - agentData.SessionID = UUID.Zero; - agentData.SecureSessionID = UUID.Zero; + + // XXX: Sessions must be unique, otherwise one presence can overwrite another in NullPresenceData. + agentData.SessionID = UUID.Random(); + agentData.SecureSessionID = UUID.Random(); + agentData.circuitcode = 123; agentData.BaseFolder = UUID.Zero; agentData.InventoryFolder = UUID.Zero; @@ -416,7 +419,10 @@ namespace OpenSim.Tests.Common // We emulate the proper login sequence here by doing things in four stages // Stage 0: login - scene.PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID); + // We need to punch through to the underlying service because scene will not, correctly, let us call it + // through it's reference to the LPSC + LocalPresenceServicesConnector lpsc = (LocalPresenceServicesConnector)scene.PresenceService; + lpsc.m_PresenceService.LoginAgent(agentData.AgentID.ToString(), agentData.SessionID, agentData.SecureSessionID); // Stages 1 & 2 ScenePresence sp = IntroduceClientToScene(scene, agentData, TeleportFlags.ViaLogin); diff --git a/OpenSim/Tests/Common/Mock/TestClient.cs b/OpenSim/Tests/Common/Mock/TestClient.cs index 81a5cf7cfd..6a7cb0aa83 100644 --- a/OpenSim/Tests/Common/Mock/TestClient.cs +++ b/OpenSim/Tests/Common/Mock/TestClient.cs @@ -329,7 +329,7 @@ namespace OpenSim.Tests.Common.Mock /// private UUID m_agentId; - public ISceneAgent SceneAgent { get { throw new NotImplementedException(); } } + public ISceneAgent SceneAgent { get; set; } /// /// The last caps seed url that this client was given. @@ -349,15 +349,9 @@ namespace OpenSim.Tests.Common.Mock get { return m_agentId; } } - public UUID SessionId - { - get { return UUID.Zero; } - } + public UUID SessionId { get; set; } - public UUID SecureSessionId - { - get { return UUID.Zero; } - } + public UUID SecureSessionId { get; set; } public virtual string FirstName { @@ -381,11 +375,9 @@ namespace OpenSim.Tests.Common.Mock get { return true; } set { } } - public bool IsLoggingOut - { - get { return false; } - set { } - } + + public bool IsLoggingOut { get; set; } + public UUID ActiveGroupId { get { return UUID.Zero; } @@ -451,6 +443,8 @@ namespace OpenSim.Tests.Common.Mock m_lastName = agentData.lastname; m_circuitCode = agentData.circuitcode; m_scene = scene; + SessionId = agentData.SessionID; + SecureSessionId = agentData.SecureSessionID; CapsSeedUrl = agentData.CapsPath; ReceivedOfflineNotifications = new List(); @@ -902,12 +896,29 @@ namespace OpenSim.Tests.Common.Mock { } + /// + /// This is a TestClient only method to do shutdown tasks that are normally carried out by LLUDPServer.RemoveClient() + /// + public void Logout() + { + // We must set this here so that the presence is removed from the PresenceService by the PresenceDetector + IsLoggingOut = true; + + Close(); + } + + public void Close(bool c) + { + Close(); + } + public void Close() { - Close(true); - } - public void Close(bool sendStop) - { + // Fire the callback for this connection closing + // This is necesary to get the presence detector to notice that a client has logged out. + if (OnConnectionClosed != null) + OnConnectionClosed(this); + m_scene.RemoveClient(AgentId, true); } diff --git a/bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config b/bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config index 026417a410..1bc7e413ff 100755 --- a/bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config +++ b/bin/Physics/OpenSim.Region.Physics.BulletSPlugin.dll.config @@ -1,6 +1,6 @@ - - - - + + + + diff --git a/bin/lib32/BulletSim.dll b/bin/lib32/BulletSim.dll index 5bef6e9a22..2c28063f4c 100755 Binary files a/bin/lib32/BulletSim.dll and b/bin/lib32/BulletSim.dll differ diff --git a/bin/lib32/libBulletSim.so b/bin/lib32/libBulletSim.so index 9882f5b8b1..f40f446213 100755 Binary files a/bin/lib32/libBulletSim.so and b/bin/lib32/libBulletSim.so differ diff --git a/bin/lib64/BulletSim.dll b/bin/lib64/BulletSim.dll index 9f09ef8bf5..d9e5e89874 100755 Binary files a/bin/lib64/BulletSim.dll and b/bin/lib64/BulletSim.dll differ diff --git a/bin/lib64/libBulletSim.so b/bin/lib64/libBulletSim.so index fa47bf1830..06770a4e69 100755 Binary files a/bin/lib64/libBulletSim.so and b/bin/lib64/libBulletSim.so differ diff --git a/bin/libBulletSim-x86_64.so b/bin/libBulletSim-x86_64.so deleted file mode 100755 index 527eda5780..0000000000 Binary files a/bin/libBulletSim-x86_64.so and /dev/null differ diff --git a/bin/libBulletSim.so b/bin/libBulletSim.so deleted file mode 100755 index 9f91bfd411..0000000000 Binary files a/bin/libBulletSim.so and /dev/null differ diff --git a/prebuild.xml b/prebuild.xml index 0123c2af68..2f114da19f 100644 --- a/prebuild.xml +++ b/prebuild.xml @@ -1325,6 +1325,7 @@ ../../../bin/ + @@ -1764,6 +1765,7 @@ + @@ -3009,6 +3011,7 @@ +