From 53b72ab4b8685d2bc77ca3d18a40522774a6cdb2 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Fri, 2 May 2014 13:31:58 +0100 Subject: [PATCH 01/20] minor: Comment out Cacheitems debug log lines for now --- .../Linden/Caps/UploadBakedTextureModule.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs index 3b39153690..8cdebcdbde 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/UploadBakedTextureModule.cs @@ -129,12 +129,12 @@ namespace OpenSim.Region.ClientStack.Linden m_BakedTextureModule = m_scene.RequestModuleInterface(); if (cacheItems.Length > 0) { - m_log.Debug("[Cacheitems]: " + cacheItems.Length); - for (int iter = 0; iter < maxCacheitemsLoop; iter++) - { - m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + - cacheItems[iter].TextureID); - } +// m_log.Debug("[Cacheitems]: " + cacheItems.Length); +// for (int iter = 0; iter < maxCacheitemsLoop; iter++) +// { +// m_log.Debug("[Cacheitems] {" + iter + "/" + cacheItems[iter].TextureIndex + "}: c-" + cacheItems[iter].CacheId + ", t-" + +// cacheItems[iter].TextureID); +// } ScenePresence p = null; if (m_scene.TryGetScenePresence(remoteClient.AgentId, out p)) From 7862d1e20dc8c405e594d888722d90178f0cd9f7 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Wed, 30 Apr 2014 08:48:05 +0300 Subject: [PATCH 02/20] Added range-checking for the parameters to PRIM_POINT_LIGHT (used in llSetLinkPrimitiveParamsFast() ) --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 4d20e136a9..0e6b24a59c 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -1884,9 +1884,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api part.Shape.LightColorR = Util.Clip((float)color.x, 0.0f, 1.0f); part.Shape.LightColorG = Util.Clip((float)color.y, 0.0f, 1.0f); part.Shape.LightColorB = Util.Clip((float)color.z, 0.0f, 1.0f); - part.Shape.LightIntensity = intensity; - part.Shape.LightRadius = radius; - part.Shape.LightFalloff = falloff; + part.Shape.LightIntensity = Util.Clip((float)intensity, 0.0f, 1.0f); + part.Shape.LightRadius = Util.Clip((float)radius, 0.1f, 20.0f); + part.Shape.LightFalloff = Util.Clip((float)falloff, 0.01f, 2.0f); } else { From 0fe08c8799b1a3a2d5a07c206c2f9680d1c0798e Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Sun, 4 May 2014 13:36:36 +0300 Subject: [PATCH 03/20] - When sending the "My Suitcase" folder to the client, always claim it has Folder Type 8. (Previously we had used Folder Type -1 in one place, and LLClientView didn't even bother changing Folder Type 100 to anything else.) --- OpenSim/Framework/InventoryItemBase.cs | 4 ++++ .../Region/ClientStack/Linden/UDP/LLClientView.cs | 5 ++++- .../HypergridService/HGSuitcaseInventoryService.cs | 14 +++++++------- .../Services/InventoryService/XInventoryService.cs | 4 ++-- 4 files changed, 17 insertions(+), 10 deletions(-) diff --git a/OpenSim/Framework/InventoryItemBase.cs b/OpenSim/Framework/InventoryItemBase.cs index 57612005a1..ce63ee067f 100644 --- a/OpenSim/Framework/InventoryItemBase.cs +++ b/OpenSim/Framework/InventoryItemBase.cs @@ -35,6 +35,10 @@ namespace OpenSim.Framework /// public class InventoryItemBase : InventoryNodeBase, ICloneable { + public static readonly string SUITCASE_FOLDER_NAME = "My Suitcase"; + public static readonly sbyte SUITCASE_FOLDER_TYPE = 100; + public static readonly sbyte SUITCASE_FOLDER_FAKE_TYPE = 8; + /// /// The inventory type of the item. This is slightly different from the asset type in some situations. /// diff --git a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs index 7cb5b53cfe..53217a09dc 100644 --- a/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/Linden/UDP/LLClientView.cs @@ -1761,6 +1761,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP newBlock.Name = Util.StringToBytes256(folder.Name); newBlock.ParentID = folder.ParentID; newBlock.Type = (sbyte)folder.Type; + if (newBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + newBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; return newBlock; } @@ -2010,8 +2012,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP folderBlock.FolderID = folder.ID; folderBlock.ParentID = folder.ParentID; - //folderBlock.Type = -1; folderBlock.Type = (sbyte)folder.Type; + if (folderBlock.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + folderBlock.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; folderBlock.Name = Util.StringToBytes256(folder.Name); return folderBlock; diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index 8269d36dd9..df797a5f34 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -156,9 +156,9 @@ namespace OpenSim.Services.HypergridService 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 - // In the DB we tag it as type 100, but we use -1 (Unknown) outside - suitcase = CreateFolder(principalID, root.folderID, 100, "My Suitcase"); + // Create the My Suitcase folder under the user's root folder. + // In the DB we tag it as type 100, but we use type 8 (Folder) outside, as this affects the sort order. + suitcase = CreateFolder(principalID, root.folderID, InventoryItemBase.SUITCASE_FOLDER_TYPE, InventoryItemBase.SUITCASE_FOLDER_NAME); if (suitcase == null) { m_log.ErrorFormat("[HG SUITCASE INVENTORY SERVICE]: Unable to create suitcase folder"); @@ -464,7 +464,7 @@ namespace OpenSim.Services.HypergridService // 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... + new string[] { principalID.ToString(), InventoryItemBase.SUITCASE_FOLDER_TYPE.ToString() }); // This is a special folder type... if (folders != null && folders.Length > 0) return folders[0]; @@ -472,13 +472,13 @@ namespace OpenSim.Services.HypergridService // check to see if we have the old Suitcase folder folders = m_Database.GetFolders( new string[] { "agentID", "folderName", "parentFolderID" }, - new string[] { principalID.ToString(), "My Suitcase", UUID.Zero.ToString() }); + new string[] { principalID.ToString(), InventoryItemBase.SUITCASE_FOLDER_NAME, UUID.Zero.ToString() }); if (folders != null && folders.Length > 0) { // Move it to under the root folder XInventoryFolder root = GetRootXFolder(principalID); folders[0].parentFolderID = root.folderID; - folders[0].type = 100; + folders[0].type = InventoryItemBase.SUITCASE_FOLDER_TYPE; m_Database.StoreFolder(folders[0]); return folders[0]; } @@ -488,7 +488,7 @@ namespace OpenSim.Services.HypergridService private void SetAsNormalFolder(XInventoryFolder suitcase) { - suitcase.type = (short)AssetType.Folder; + suitcase.type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; } private List GetFolderTree(UUID principalID, UUID folder) diff --git a/OpenSim/Services/InventoryService/XInventoryService.cs b/OpenSim/Services/InventoryService/XInventoryService.cs index 3bee4337ef..7c16ca945a 100644 --- a/OpenSim/Services/InventoryService/XInventoryService.cs +++ b/OpenSim/Services/InventoryService/XInventoryService.cs @@ -631,8 +631,8 @@ namespace OpenSim.Services.InventoryService newFolder.ParentID = folder.parentFolderID; newFolder.Type = (short)folder.type; // Viewer can't understand anything that's not in it's LLFolderType enum - if (newFolder.Type == 100) - newFolder.Type = -1; + if (newFolder.Type == InventoryItemBase.SUITCASE_FOLDER_TYPE) + newFolder.Type = InventoryItemBase.SUITCASE_FOLDER_FAKE_TYPE; newFolder.Version = (ushort)folder.version; newFolder.Name = folder.folderName; newFolder.Owner = folder.agentID; From df49196e17bae9a1472085402094718ba6997b1e Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 5 May 2014 10:20:04 +0300 Subject: [PATCH 04/20] Log whenever an inventory operation is blocked because the item/folder isn't in the Suitcase --- .../HGSuitcaseInventoryService.cs | 60 ++++++++++++++++--- 1 file changed, 52 insertions(+), 8 deletions(-) diff --git a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs index df797a5f34..3de2330410 100644 --- a/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs +++ b/OpenSim/Services/HypergridService/HGSuitcaseInventoryService.cs @@ -248,7 +248,10 @@ namespace OpenSim.Services.HypergridService InventoryCollection coll = null; if (!IsWithinSuitcaseTree(principalID, folderID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderContent: folder {0} is not within Suitcase tree", folderID); return new InventoryCollection(); + } coll = base.GetFolderContent(principalID, folderID); @@ -265,7 +268,10 @@ namespace OpenSim.Services.HypergridService // 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 if (!IsWithinSuitcaseTree(principalID, folderID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: GetFolderItems: folder {0} is not within Suitcase tree", folderID); return new List(); + } return base.GetFolderItems(principalID, folderID); } @@ -277,7 +283,10 @@ namespace OpenSim.Services.HypergridService // make sure the given folder's parent folder exists under the suitcase tree of this user if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddFolder: folder {0} is not within Suitcase tree", folder.ParentID); return false; + } // OK, it's legit if (base.AddFolder(folder)) @@ -297,7 +306,7 @@ namespace OpenSim.Services.HypergridService //m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Update folder {0}, version {1}", folder.ID, folder.Version); if (!IsWithinSuitcaseTree(folder.Owner, folder.ID)) { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: folder {0} not within Suitcase tree", folder.Name); + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: UpdateFolder: folder {0}/{1} is not within Suitcase tree", folder.Name, folder.ID); return false; } @@ -307,9 +316,17 @@ namespace OpenSim.Services.HypergridService public override bool MoveFolder(InventoryFolderBase folder) { - if (!IsWithinSuitcaseTree(folder.Owner, folder.ID) || - !IsWithinSuitcaseTree(folder.Owner, folder.ParentID)) + if (!IsWithinSuitcaseTree(folder.Owner, folder.ID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder: folder {0} is not within Suitcase tree", folder.ID); return false; + } + + if (!IsWithinSuitcaseTree(folder.Owner, folder.ParentID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveFolder: folder {0} is not within Suitcase tree", folder.ParentID); + return false; + } return base.MoveFolder(folder); } @@ -331,7 +348,10 @@ namespace OpenSim.Services.HypergridService // 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 if (!IsWithinSuitcaseTree(item.Owner, item.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: AddItem: folder {0} is not within Suitcase tree", item.Folder); return false; + } // OK, it's legit return base.AddItem(item); @@ -341,7 +361,10 @@ namespace OpenSim.Services.HypergridService public override bool UpdateItem(InventoryItemBase item) { if (!IsWithinSuitcaseTree(item.Owner, item.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: UpdateItem: folder {0} is not within Suitcase tree", item.Folder); return false; + } return base.UpdateItem(item); } @@ -350,11 +373,28 @@ namespace OpenSim.Services.HypergridService { // Principal is b0rked. *sigh* - if (!IsWithinSuitcaseTree(items[0].Owner, items[0].Folder)) - return false; + // Check the items' destination folders + foreach (InventoryItemBase item in items) + { + if (!IsWithinSuitcaseTree(item.Owner, item.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItems: folder {0} is not within Suitcase tree", item.Folder); + return false; + } + } + + // Check the items' current folders + foreach (InventoryItemBase item in items) + { + InventoryItemBase originalItem = base.GetItem(item); + if (!IsWithinSuitcaseTree(originalItem.Owner, originalItem.Folder)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: MoveItems: folder {0} is not within Suitcase tree", originalItem.Folder); + return false; + } + } return base.MoveItems(principalID, items); - } public override bool DeleteItems(UUID principalID, List itemIDs) @@ -374,8 +414,8 @@ namespace OpenSim.Services.HypergridService if (!IsWithinSuitcaseTree(it.Owner, it.Folder) && !IsPartOfAppearance(it.Owner, it.ID)) { - m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0} (folder {1}) is not within Suitcase", - it.Name, it.Folder); + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Item {0}/{1} (folder {2}) is not within Suitcase tree or Appearance", + it.Name, it.ID, it.Folder); return null; } @@ -396,7 +436,11 @@ namespace OpenSim.Services.HypergridService if (f != null) { if (!IsWithinSuitcaseTree(f.Owner, f.ID)) + { + m_log.DebugFormat("[HG SUITCASE INVENTORY SERVICE]: Folder {0}/{1} is not within Suitcase tree", + f.Name, f.ID); return null; + } } return f; From 1e5cff32fc41356971d6ad601cbee7ad62472c76 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 5 May 2014 11:06:49 +0300 Subject: [PATCH 05/20] Show more meaningful error messages when failed to give an item to another user --- OpenSim/Addons/Groups/GroupsModule.cs | 5 ++- .../Linden/Caps/BunchOfCaps/BunchOfCaps.cs | 18 ++++++--- .../Transfer/InventoryTransferModule.cs | 11 +++--- .../Framework/Scenes/Scene.Inventory.cs | 39 ++++++++++++++----- .../Scenes/Tests/UserInventoryTests.cs | 10 +++-- .../Avatar/XmlRpcGroups/GroupsModule.cs | 5 ++- 6 files changed, 59 insertions(+), 29 deletions(-) diff --git a/OpenSim/Addons/Groups/GroupsModule.cs b/OpenSim/Addons/Groups/GroupsModule.cs index f11606a7b4..2831326027 100644 --- a/OpenSim/Addons/Groups/GroupsModule.cs +++ b/OpenSim/Addons/Groups/GroupsModule.cs @@ -496,12 +496,13 @@ namespace OpenSim.Groups Util.ParseUniversalUserIdentifier(notice.noticeData.AttachmentOwnerID, out giver, out tmp, out tmp, out tmp, out tmp); m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); + string message; InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, - giver, notice.noticeData.AttachmentItemID); + giver, notice.noticeData.AttachmentItemID, out message); if (itemCopy == null) { - remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); + remoteClient.SendAgentAlertMessage(message, false); return; } diff --git a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs index 79bc5efabf..0eb15f8d43 100644 --- a/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs +++ b/OpenSim/Region/ClientStack/Linden/Caps/BunchOfCaps/BunchOfCaps.cs @@ -865,18 +865,26 @@ namespace OpenSim.Region.ClientStack.Linden item = m_Scene.InventoryService.GetItem(new InventoryItemBase(itemID)); if (item != null) { - copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID); - if (copyItem != null && client != null) + string message; + copyItem = m_Scene.GiveInventoryItem(m_HostCapsObj.AgentID, item.Owner, itemID, folderID, out message); + if (client != null) { - m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder); - client.SendBulkUpdateInventory(copyItem); + if (copyItem != null) + { + m_log.InfoFormat("[CAPS]: CopyInventoryFromNotecard, ItemID:{0}, FolderID:{1}", copyItem.ID, copyItem.Folder); + client.SendBulkUpdateInventory(copyItem); + } + else + { + client.SendAgentAlertMessage(message, false); + } } } else { m_log.ErrorFormat("[CAPS]: CopyInventoryFromNotecard - Failed to retrieve item {0} from notecard {1}", itemID, notecardID); if (client != null) - client.SendAlertMessage("Failed to retrieve item"); + client.SendAgentAlertMessage("Failed to retrieve item", false); } } catch (Exception e) diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index 0b10dd83db..c632798a74 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -180,8 +180,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer "[INVENTORY TRANSFER]: Inserting original folder {0} into agent {1}'s inventory", folderID, new UUID(im.toAgentID)); - InventoryFolderBase folderCopy - = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); + InventoryFolderBase folderCopy + = scene.GiveInventoryFolder(client, receipientID, client.AgentId, folderID, UUID.Zero); if (folderCopy == null) { @@ -217,13 +217,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer "into agent {1}'s inventory", itemID, new UUID(im.toAgentID)); - InventoryItemBase itemCopy = scene.GiveInventoryItem( - new UUID(im.toAgentID), - client.AgentId, itemID); + string message; + InventoryItemBase itemCopy = scene.GiveInventoryItem(new UUID(im.toAgentID), client.AgentId, itemID, out message); if (itemCopy == null) { - client.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); + client.SendAgentAlertMessage(message, false); return; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index bb9f457db0..27cd5c6c42 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -46,7 +46,7 @@ namespace OpenSim.Region.Framework.Scenes { public partial class Scene { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly string LogHeader = "[SCENE INVENTORY]"; /// @@ -534,9 +534,9 @@ namespace OpenSim.Region.Framework.Scenes /// /// ID of the sender of the item /// - public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId) + public virtual void GiveInventoryItem(IClientAPI recipientClient, UUID senderId, UUID itemId, out string message) { - InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId); + InventoryItemBase itemCopy = GiveInventoryItem(recipientClient.AgentId, senderId, itemId, out message); if (itemCopy != null) recipientClient.SendBulkUpdateInventory(itemCopy); @@ -549,9 +549,9 @@ namespace OpenSim.Region.Framework.Scenes /// ID of the sender of the item /// /// The inventory item copy given, null if the give was unsuccessful - public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId) + public virtual InventoryItemBase GiveInventoryItem(UUID recipient, UUID senderId, UUID itemId, out string message) { - return GiveInventoryItem(recipient, senderId, itemId, UUID.Zero); + return GiveInventoryItem(recipient, senderId, itemId, UUID.Zero, out message); } /// @@ -568,12 +568,15 @@ namespace OpenSim.Region.Framework.Scenes /// The inventory item copy given, null if the give was unsuccessful /// public virtual InventoryItemBase GiveInventoryItem( - UUID recipient, UUID senderId, UUID itemId, UUID recipientFolderId) + UUID recipient, UUID senderId, UUID itemId, UUID recipientFolderId, out string message) { //Console.WriteLine("Scene.Inventory.cs: GiveInventoryItem"); if (!Permissions.CanTransferUserInventory(itemId, senderId, recipient)) + { + message = "Not allowed to transfer this item."; return null; + } InventoryItemBase item = new InventoryItemBase(itemId, senderId); item = InventoryService.GetItem(item); @@ -582,6 +585,7 @@ namespace OpenSim.Region.Framework.Scenes { m_log.WarnFormat( "[AGENT INVENTORY]: Failed to find item {0} sent by {1} to {2}", itemId, senderId, recipient); + message = string.Format("Item not found: {0}.", itemId); return null; } @@ -590,6 +594,7 @@ namespace OpenSim.Region.Framework.Scenes m_log.WarnFormat( "[AGENT INVENTORY]: Attempt to send item {0} {1} to {2} failed because sender {3} did not match item owner {4}", item.Name, item.ID, recipient, senderId, item.Owner); + message = "Sender did not match item owner."; return null; } @@ -600,7 +605,10 @@ namespace OpenSim.Region.Framework.Scenes if (!Permissions.BypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + { + message = "Item doesn't have the Transfer permission."; return null; + } } // Insert a copy of the item into the recipient @@ -736,9 +744,14 @@ namespace OpenSim.Region.Framework.Scenes InventoryFolderBase root = InventoryService.GetRootFolder(recipient); if (root != null) + { itemCopy.Folder = root.ID; + } else - return null; // No destination + { + message = "Can't find a folder to add the item to."; + return null; + } } } @@ -763,6 +776,7 @@ namespace OpenSim.Region.Framework.Scenes } } + message = null; return itemCopy; } @@ -780,7 +794,7 @@ namespace OpenSim.Region.Framework.Scenes /// /// The inventory folder copy given, null if the copy was unsuccessful /// - public virtual InventoryFolderBase GiveInventoryFolder( + public virtual InventoryFolderBase GiveInventoryFolder(IClientAPI client, UUID recipientId, UUID senderId, UUID folderId, UUID recipientParentFolderId) { //// Retrieve the folder from the sender @@ -815,13 +829,18 @@ namespace OpenSim.Region.Framework.Scenes InventoryCollection contents = InventoryService.GetFolderContent(senderId, folderId); foreach (InventoryFolderBase childFolder in contents.Folders) { - GiveInventoryFolder(recipientId, senderId, childFolder.ID, newFolder.ID); + GiveInventoryFolder(client, recipientId, senderId, childFolder.ID, newFolder.ID); } // Give all the items foreach (InventoryItemBase item in contents.Items) { - GiveInventoryItem(recipientId, senderId, item.ID, newFolder.ID); + string message; + if (GiveInventoryItem(recipientId, senderId, item.ID, newFolder.ID, out message) == null) + { + if (client != null) + client.SendAgentAlertMessage(message, false); + } } return newFolder; diff --git a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs index e50b4da6a9..0736278e16 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/UserInventoryTests.cs @@ -95,7 +95,9 @@ namespace OpenSim.Region.Framework.Tests UserAccount user2 = UserAccountHelpers.CreateUserWithInventory(scene, TestHelpers.ParseTail(1002)); InventoryItemBase item1 = UserInventoryHelpers.CreateInventoryItem(scene, "item1", user1.PrincipalID); - scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID); + string message; + + scene.GiveInventoryItem(user2.PrincipalID, user1.PrincipalID, item1.ID, out message); InventoryItemBase retrievedItem1 = UserInventoryHelpers.GetInventoryItem(scene.InventoryService, user2.PrincipalID, "Notecards/item1"); @@ -103,7 +105,7 @@ namespace OpenSim.Region.Framework.Tests Assert.That(retrievedItem1, Is.Not.Null); // Try giving back the freshly received item - scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID); + scene.GiveInventoryItem(user1.PrincipalID, user2.PrincipalID, retrievedItem1.ID, out message); List reretrievedItems = UserInventoryHelpers.GetInventoryItems(scene.InventoryService, user1.PrincipalID, "Notecards/item1"); @@ -123,7 +125,7 @@ namespace OpenSim.Region.Framework.Tests InventoryFolderBase folder1 = UserInventoryHelpers.CreateInventoryFolder(scene.InventoryService, user1.PrincipalID, "folder1", false); - scene.GiveInventoryFolder(user2.PrincipalID, user1.PrincipalID, folder1.ID, UUID.Zero); + scene.GiveInventoryFolder(null, user2.PrincipalID, user1.PrincipalID, folder1.ID, UUID.Zero); InventoryFolderBase retrievedFolder1 = UserInventoryHelpers.GetInventoryFolder(scene.InventoryService, user2.PrincipalID, "folder1"); @@ -131,7 +133,7 @@ namespace OpenSim.Region.Framework.Tests Assert.That(retrievedFolder1, Is.Not.Null); // Try giving back the freshly received folder - scene.GiveInventoryFolder(user1.PrincipalID, user2.PrincipalID, retrievedFolder1.ID, UUID.Zero); + scene.GiveInventoryFolder(null, user1.PrincipalID, user2.PrincipalID, retrievedFolder1.ID, UUID.Zero); List reretrievedFolders = UserInventoryHelpers.GetInventoryFolders(scene.InventoryService, user1.PrincipalID, "folder1"); diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index fc8cae2664..f34152c17c 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -560,12 +560,13 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (m_debugEnabled) m_log.DebugFormat("[Groups]: Giving inventory from {0} to {1}", giver, remoteClient.AgentId); + string message; InventoryItemBase itemCopy = ((Scene)(remoteClient.Scene)).GiveInventoryItem(remoteClient.AgentId, - giver, attachmentUUID); + giver, attachmentUUID, out message); if (itemCopy == null) { - remoteClient.SendAgentAlertMessage("Can't find item to give. Nothing given.", false); + remoteClient.SendAgentAlertMessage(message, false); return; } From eb79c882eab090ee5ee51cadac7bd1dc2e5ddb9f Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 5 May 2014 15:59:24 +0300 Subject: [PATCH 06/20] Show more meaningful error messages when failed to move an item from a prim to a user's inventory. Also, actually show the error to the user in more cases. (Previously, sometimes the operation failed without telling the user anything.) --- .../Framework/Scenes/Scene.Inventory.cs | 64 ++++++++++++------- .../Scenes/Tests/TaskInventoryTests.cs | 6 +- .../Shared/Api/Implementation/LSL_Api.cs | 6 +- .../Shared/Api/Implementation/OSSL_Api.cs | 9 +-- 4 files changed, 56 insertions(+), 29 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 27cd5c6c42..498886819d 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1167,11 +1167,19 @@ namespace OpenSim.Region.Framework.Scenes InventoryFolderBase destFolder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.TrashFolder); - // Move the item to trash. If this is a copiable item, only + // Move the item to trash. If this is a copyable item, only // a copy will be moved and we will still need to delete - // the item from the prim. If it was no copy, is will be + // the item from the prim. If it was no copy, it will be // deleted by this method. - MoveTaskInventoryItem(remoteClient, destFolder.ID, part, itemID); + string message; + InventoryItemBase item2 = MoveTaskInventoryItem(remoteClient, destFolder.ID, part, itemID, out message); + + if (item2 == null) + { + m_log.WarnFormat("[SCENE INVENTORY]: RemoveTaskInventory of item {0} failed: {1}", itemID, message); + remoteClient.SendAgentAlertMessage(message, false); + return; + } if (group.GetInventoryItem(localID, itemID) != null) { @@ -1183,11 +1191,12 @@ namespace OpenSim.Region.Framework.Scenes group.RemoveInventoryItem(localID, itemID); } + part.SendPropertiesToClient(remoteClient); } } - private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) + private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId, out string message) { TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); @@ -1198,12 +1207,13 @@ namespace OpenSim.Region.Framework.Scenes + " inventory item from a prim's inventory item " + " but the required item does not exist in the prim's inventory", itemId, part.Name, part.UUID); - + message = "Item not found: " + itemId; return null; } if ((destAgent != taskItem.OwnerID) && ((taskItem.CurrentPermissions & (uint)PermissionMask.Transfer) == 0)) { + message = "Item doesn't have the Transfer permission."; return null; } @@ -1263,6 +1273,7 @@ namespace OpenSim.Region.Framework.Scenes } } + message = null; return agentItem; } @@ -1273,19 +1284,19 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId) + public InventoryItemBase MoveTaskInventoryItem(IClientAPI remoteClient, UUID folderId, SceneObjectPart part, UUID itemId, out string message) { m_log.DebugFormat( "[PRIM INVENTORY]: Adding item {0} from {1} to folder {2} for {3}", itemId, part.Name, folderId, remoteClient.Name); - InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId); - + InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(remoteClient.AgentId, part, itemId, out message); if (agentItem == null) return null; agentItem.Folder = folderId; AddInventoryItem(remoteClient, agentItem); + message = null; return agentItem; } @@ -1336,7 +1347,11 @@ namespace OpenSim.Region.Framework.Scenes return; } - MoveTaskInventoryItem(remoteClient, folderId, part, itemId); + string message; + InventoryItemBase item = MoveTaskInventoryItem(remoteClient, folderId, part, itemId, out message); + + if (item == null) + remoteClient.SendAgentAlertMessage(message, false); } /// @@ -1350,17 +1365,17 @@ namespace OpenSim.Region.Framework.Scenes /// /// /// - public InventoryItemBase MoveTaskInventoryItem(UUID avatarId, UUID folderId, SceneObjectPart part, UUID itemId) + public InventoryItemBase MoveTaskInventoryItem(UUID avatarId, UUID folderId, SceneObjectPart part, UUID itemId, out string message) { ScenePresence avatar; if (TryGetScenePresence(avatarId, out avatar)) { - return MoveTaskInventoryItem(avatar.ControllingClient, folderId, part, itemId); + return MoveTaskInventoryItem(avatar.ControllingClient, folderId, part, itemId, out message); } else { - InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(avatarId, part, itemId); + InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(avatarId, part, itemId, out message); if (agentItem == null) return null; @@ -1474,6 +1489,11 @@ namespace OpenSim.Region.Framework.Scenes public UUID MoveTaskInventoryItems(UUID destID, string category, SceneObjectPart host, List items) { + ScenePresence avatar; + IClientAPI remoteClient = null; + if (TryGetScenePresence(destID, out avatar)) + remoteClient = avatar.ControllingClient; + InventoryFolderBase rootFolder = InventoryService.GetRootFolder(destID); UUID newFolderID = UUID.Random(); @@ -1483,7 +1503,8 @@ namespace OpenSim.Region.Framework.Scenes foreach (UUID itemID in items) { - InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(destID, host, itemID); + string message; + InventoryItemBase agentItem = CreateAgentInventoryItemFromTask(destID, host, itemID, out message); if (agentItem != null) { @@ -1491,18 +1512,17 @@ namespace OpenSim.Region.Framework.Scenes AddInventoryItem(agentItem); } + else + { + if (remoteClient != null) + remoteClient.SendAgentAlertMessage(message, false); + } } - ScenePresence avatar = null; - if (TryGetScenePresence(destID, out avatar)) + if (remoteClient != null) { - //profile.SendInventoryDecendents(avatar.ControllingClient, - // profile.RootFolder.ID, true, false); - //profile.SendInventoryDecendents(avatar.ControllingClient, - // newFolderID, false, true); - - SendInventoryUpdate(avatar.ControllingClient, rootFolder, true, false); - SendInventoryUpdate(avatar.ControllingClient, newFolder, false, true); + SendInventoryUpdate(remoteClient, rootFolder, true, false); + SendInventoryUpdate(remoteClient, newFolder, false, true); } return newFolderID; diff --git a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs index 6e0ea7d869..f809267c8f 100644 --- a/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs +++ b/OpenSim/Region/Framework/Scenes/Tests/TaskInventoryTests.cs @@ -136,7 +136,8 @@ namespace OpenSim.Region.Framework.Tests = InventoryArchiveUtils.FindFoldersByPath(scene.InventoryService, user1.PrincipalID, "Objects")[0]; // Perform test - scene.MoveTaskInventoryItem(user1.PrincipalID, folder.ID, sop1, sopItem1.ItemID); + string message; + scene.MoveTaskInventoryItem(user1.PrincipalID, folder.ID, sop1, sopItem1.ItemID, out message); InventoryItemBase ncUserItem = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Objects/ncItem"); @@ -165,7 +166,8 @@ namespace OpenSim.Region.Framework.Tests scene, sop1, "ncItem", TestHelpers.ParseTail(0x800), TestHelpers.ParseTail(0x900), "Hello World!"); // Perform test - scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID); + string message; + scene.MoveTaskInventoryItem(user1.PrincipalID, UUID.Zero, sop1, sopItem1.ItemID, out message); InventoryItemBase ncUserItem = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, user1.PrincipalID, "Notecards/ncItem"); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 0e6b24a59c..d169912290 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -4127,10 +4127,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } // destination is an avatar - InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId); + string message; + InventoryItemBase agentItem = World.MoveTaskInventoryItem(destId, UUID.Zero, m_host, objId, out message); if (agentItem == null) + { + llSay(0, message); return; + } if (m_TransferModule != null) { diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 6302455d12..de2c3f7fef 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -3397,14 +3397,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (sp == null) return; - InventoryItemBase newItem = World.MoveTaskInventoryItem(sp.UUID, UUID.Zero, m_host, item.ItemID); + string message; + InventoryItemBase newItem = World.MoveTaskInventoryItem(sp.UUID, UUID.Zero, m_host, item.ItemID, out message); if (newItem == null) { m_log.ErrorFormat( - "[OSSL API]: Could not create user inventory item {0} for {1}, attach point {2} in {3}", - itemName, m_host.Name, attachmentPoint, World.Name); - + "[OSSL API]: Could not create user inventory item {0} for {1}, attach point {2} in {3}: {4}", + itemName, m_host.Name, attachmentPoint, World.Name, message); + ((LSL_Api)m_LSL_Api).llSay(0, message); return; } From 614b9e14c42d69bf8048218c889cc047756b0b5a Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Mon, 5 May 2014 16:09:51 +0300 Subject: [PATCH 07/20] When moving an item from a prim to a user's inventory, don't delete the item from the prim until it was successfully copied to the user --- .../Framework/Scenes/Scene.Inventory.cs | 29 ++++++++++++++++--- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index 498886819d..91f1b633e4 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -1196,6 +1196,10 @@ namespace OpenSim.Region.Framework.Scenes } } + + /// + /// Creates (in memory only) a user inventory item that will contain a copy of a task inventory item. + /// private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId, out string message) { TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); @@ -1259,11 +1263,24 @@ namespace OpenSim.Region.Framework.Scenes agentItem.GroupPermissions = taskItem.GroupPermissions; } + message = null; + return agentItem; + } + + /// + /// If the task item is not-copyable then remove it from the prim. + /// + private void RemoveNonCopyTaskItemFromPrim(SceneObjectPart part, UUID itemId) + { + TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); + if (taskItem == null) + return; + if (!Permissions.BypassPermissions()) { if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) { - if (taskItem.Type == 10) + if (taskItem.Type == (int)AssetType.LSLText) { part.RemoveScriptEvents(itemId); EventManager.TriggerRemoveScript(part.LocalId, itemId); @@ -1272,9 +1289,6 @@ namespace OpenSim.Region.Framework.Scenes part.Inventory.RemoveInventoryItem(itemId); } } - - message = null; - return agentItem; } /// @@ -1296,6 +1310,9 @@ namespace OpenSim.Region.Framework.Scenes agentItem.Folder = folderId; AddInventoryItem(remoteClient, agentItem); + + RemoveNonCopyTaskItemFromPrim(part, itemId); + message = null; return agentItem; } @@ -1384,6 +1401,8 @@ namespace OpenSim.Region.Framework.Scenes AddInventoryItem(agentItem); + RemoveNonCopyTaskItemFromPrim(part, itemId); + return agentItem; } } @@ -1511,6 +1530,8 @@ namespace OpenSim.Region.Framework.Scenes agentItem.Folder = newFolderID; AddInventoryItem(agentItem); + + RemoveNonCopyTaskItemFromPrim(host, itemID); } else { From ef262799ca2795cabf9e2f63e29698872e0c9414 Mon Sep 17 00:00:00 2001 From: Oren Hurvitz Date: Tue, 6 May 2014 09:43:07 +0300 Subject: [PATCH 08/20] Better error handling in AssetServerPostHandler. Invalid XML causes an InvalidOperationException, not an XmlException --- OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs index 5122a77b6c..a77e67d1a5 100644 --- a/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs +++ b/OpenSim/Server/Handlers/Asset/AssetServerPostHandler.cs @@ -64,7 +64,7 @@ namespace OpenSim.Server.Handlers.Asset { asset = (AssetBase)xs.Deserialize(request); } - catch (XmlException) + catch (Exception) { httpResponse.StatusCode = (int)HttpStatusCode.BadRequest; return null; From 539165e6bd87b3a4cc76b5a730abb88017bff555 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 6 May 2014 17:28:21 +0100 Subject: [PATCH 09/20] minor: Change configuration text in config files to reflect the existing situation of BulletSim as the default physics engine. --- bin/OpenSim.ini.example | 11 ++++++----- bin/OpenSimDefaults.ini | 9 ++++++--- 2 files changed, 12 insertions(+), 8 deletions(-) diff --git a/bin/OpenSim.ini.example b/bin/OpenSim.ini.example index 8742313aeb..7f2cba6c31 100644 --- a/bin/OpenSim.ini.example +++ b/bin/OpenSim.ini.example @@ -204,11 +204,12 @@ ; meshing = ZeroMesher ;; Choose one of the physics engines below - ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} OpenDynamicsEngine - ;; OpenDynamicsEngine is by some distance the most developed physics engine - ;; BulletSim is experimental and in active development. - ;; basicphysics effectively does not model physics at all, making all - ;; objects phantom. + ;# {physics} {} {Select physics engine} {OpenDynamicsEngine BulletSim basicphysics POS} BulletSim + ;; BulletSim is the default physics engine. It provides the best performance and most functionality. + ;; BulletSim supports varregions. + ;; OpenDynamicsEngine was the previous default physics engine in OpenSimulator 0.7.6.1 and before. + ;; It continues to provide a workable physics implementation. It does not currently support varregions. + ;; basicphysics effectively does not model physics at all, making all objects phantom. ;; Default is OpenDynamicsEngine ; physics = OpenDynamicsEngine ; physics = BulletSim diff --git a/bin/OpenSimDefaults.ini b/bin/OpenSimDefaults.ini index df332ca48e..cae29589fb 100644 --- a/bin/OpenSimDefaults.ini +++ b/bin/OpenSimDefaults.ini @@ -234,9 +234,12 @@ ; to false if you have compatibility problems. ;CacheSculptMaps = true - ; Choose one of the physics engines below. - ; BulletSim is a high performance physics engine. It is the default OpenSimulator physics engine - ; OpenDynamicsEngine is another developed physics engine that was the previous default in OpenSimulator 0.7.6 and before + ;; BulletSim is the default physics engine. It provides the best performance and most functionality. + ;; BulletSim supports varregions. + ;; OpenDynamicsEngine was the previous default physics engine in OpenSimulator 0.7.6.1 and before. + ;; It continues to provide a workable physics implementation. It does not currently support varregions. + ;; basicphysics effectively does not model physics at all, making all objects phantom. + ;; Default is OpenDynamicsEngine physics = BulletSim ;physics = modified_BulletX ;physics = OpenDynamicsEngine From c9742c826d7bf2bd0f99c93cf7ecb4edc9940064 Mon Sep 17 00:00:00 2001 From: Talun Date: Fri, 2 May 2014 19:48:22 +0100 Subject: [PATCH 10/20] Mantis 7146 The lsl function llGetMassMKS is not implemented This patch implements llGetMassMKS as it is described in the wiki http://wiki.secondlife.com/wiki/LlGetMassMKS --- .../ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 7 +++++++ .../Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs | 1 + OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs | 5 +++++ 3 files changed, 13 insertions(+) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index d169912290..1dcd1ccf61 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -3162,6 +3162,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } + public LSL_Float llGetMassMKS() + { + // this is what the wiki says it does! + // http://wiki.secondlife.com/wiki/LlGetMassMKS + return llGetMass() * 100.0; + } + public void llCollisionFilter(string name, string id, int accept) { m_host.AddScriptLPS(1); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 340edb3ff5..18a1e846bc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -149,6 +149,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Vector llGetLocalPos(); LSL_Rotation llGetLocalRot(); LSL_Float llGetMass(); + LSL_Float llGetMassMKS(); LSL_Integer llGetMemoryLimit(); void llGetNextEmail(string address, string subject); LSL_String llGetNotecardLine(string name, int line); diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs index 7cd17e7bad..49e39fec6f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LSL_Stub.cs @@ -584,6 +584,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase return m_LSL_Functions.llGetMass(); } + public LSL_Float llGetMassMKS() + { + return m_LSL_Functions.llGetMassMKS(); + } + public LSL_Integer llGetMemoryLimit() { return m_LSL_Functions.llGetMemoryLimit(); From e245638f2421f77bb4478705ef126f849a28c9ad Mon Sep 17 00:00:00 2001 From: Vegaslon Date: Mon, 5 May 2014 19:56:35 -0400 Subject: [PATCH 11/20] Change llUnSit to be able to unsit any avatar that is currently sat on the object, not just avatars sitting on the sittarget in the object containing the script. or when the object is owned by the parcel, land group or estate owner. --- .../Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 1dcd1ccf61..5590cd53b7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -6155,10 +6155,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (UUID.TryParse(id, out key)) { ScenePresence av = World.GetScenePresence(key); + List sittingAvatars = m_host.ParentGroup.GetSittingAvatars(); if (av != null) { - if (llAvatarOnSitTarget() == id) + if (sittingAvatars.Contains(av)) { // if the avatar is sitting on this object, then // we can unsit them. We don't want random scripts unsitting random people From 0faba7dc33e2048c68f55b8708ade1b1164fcff3 Mon Sep 17 00:00:00 2001 From: Vegaslon Date: Tue, 6 May 2014 11:00:27 -0400 Subject: [PATCH 12/20] Fix avatars going to corner of region when they are sitting on a child prim and the prim is deleted. --- OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 0356599d34..3b1c5d89e6 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1421,7 +1421,7 @@ namespace OpenSim.Region.Framework.Scenes Scene.ForEachScenePresence(sp => { - if (!sp.IsChildAgent && sp.ParentID == LocalId) + if (!sp.IsChildAgent && sp.ParentID == part.LocalId) sp.StandUp(); if (!silent) From cecb446e0e91ede0b05ea9cf40c1313782241f3d Mon Sep 17 00:00:00 2001 From: Kunta Kinte Date: Tue, 29 Apr 2014 07:26:07 -0700 Subject: [PATCH 13/20] fix infinite recursion loop in SendGridInstantMessageViaXMLRPCAsync() --- .../InstantMessage/MessageTransferModule.cs | 188 ++++++++---------- 1 file changed, 84 insertions(+), 104 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 40a400f957..4f8e2cdbfc 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -428,7 +428,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage /// /// delegate for sending a grid instant message asynchronously /// - public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID); + public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); protected virtual void GridInstantMessageCompleted(IAsyncResult iar) { @@ -442,138 +442,118 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; - d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); + d.BeginInvoke(im, result, GridInstantMessageCompleted, d); } /// - /// Recursive SendGridInstantMessage over XMLRPC method. + /// Internal SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. - /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from - /// itself, prevRegionHandle will be the last region handle that we tried to send. - /// If the handles are the same, we look up the user's location using the grid. - /// If the handles are still the same, we end. The send failed. /// - /// - /// Pass in 0 the first time this method is called. It will be called recursively with the last - /// regionhandle tried - /// - protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) + private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) { UUID toAgentID = new UUID(im.toAgentID); + UUID regionID; + bool lookupAgent; - PresenceInfo upd = null; - - bool lookupAgent = false; - + /* + * Try to get what region the agent is in from the cache. + */ lock (m_UserRegionMap) { - if (m_UserRegionMap.ContainsKey(toAgentID)) - { - upd = new PresenceInfo(); - upd.RegionID = m_UserRegionMap[toAgentID]; - - // We need to compare the current regionhandle with the previous region handle - // or the recursive loop will never end because it will never try to lookup the agent again - if (prevRegionID == upd.RegionID) - { - lookupAgent = true; - } - } - else - { - lookupAgent = true; - } + lookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID); } - - // Are we needing to look-up an agent? - if (lookupAgent) + while (true) { - // Non-cached user agent lookup. - PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); - if (presences != null && presences.Length > 0) + + /* + * If not in cache, try to find out what region the agent is in. + * Also do this if we know the existing cache entry is bad. + */ + if (lookupAgent) { - foreach (PresenceInfo p in presences) + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + + regionID = UUID.Zero; + if (presences != null) { - if (p.RegionID != UUID.Zero) + foreach (PresenceInfo p in presences) { - upd = p; - break; + if (p.RegionID != UUID.Zero) + { + regionID = p.RegionID; + break; + } } } - } - if (upd != null) - { - // check if we've tried this before.. - // This is one way to end the recursive loop - // - if (upd.RegionID == prevRegionID) + // If not found, message is undeliverable + if (regionID == UUID.Zero) { - // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - HandleUndeliveredMessage(im, result); - return; + break; } } - else + + /* + * Try to find out about region. + * If unable, message is undeliverable. + */ + GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID); + if (reginfo == null) { - // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - HandleUndeliveredMessage(im, result); + m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); + break; + } + + /* + * Try to send message to agent in the region. + */ + Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); + msgdata["region_handle"] = 0; + bool imresult = doIMSending(reginfo, msgdata); + + /* + * If message delivery successful, save cache entry because we know it is good. + * Then tell caller message has been delivered and we are done. + */ + if (imresult) + { + lock (m_UserRegionMap) + { + m_UserRegionMap[toAgentID] = regionID; + } + result(true); return; } + + /* + * Message delivery failed. + * If we just looked up what region the agent is in, message is undeliverable. + */ + if (lookupAgent) + { + break; + } + + /* + * We used a cached entry that we now know is bad. + * Try again by searching the grid for the user. + */ + lookupAgent = true; } - if (upd != null) + /* + * Message is undeliverable for one reason or another. + * Remove possible bad entry from cache. + * Then inform caller that the message is undeliverable. + */ + lock (m_UserRegionMap) { - GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, - upd.RegionID); - if (reginfo != null) - { - Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); - // Not actually used anymore, left in for compatibility - // Remove at next interface change - // - msgdata["region_handle"] = 0; - bool imresult = doIMSending(reginfo, msgdata); - if (imresult) - { - // IM delivery successful, so store the Agent's location in our local cache. - lock (m_UserRegionMap) - { - if (m_UserRegionMap.ContainsKey(toAgentID)) - { - m_UserRegionMap[toAgentID] = upd.RegionID; - } - else - { - m_UserRegionMap.Add(toAgentID, upd.RegionID); - } - } - result(true); - } - else - { - // try again, but lookup user this time. - // Warning, this must call the Async version - // of this method or we'll be making thousands of threads - // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync - // The version that spawns the thread is SendGridInstantMessageViaXMLRPC + m_UserRegionMap.Remove(toAgentID); + } - // This is recursive!!!!! - SendGridInstantMessageViaXMLRPCAsync(im, result, - upd.RegionID); - } - } - else - { - m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); - HandleUndeliveredMessage(im, result); - } - } - else - { - HandleUndeliveredMessage(im, result); - } + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + HandleUndeliveredMessage(im, result); } /// From 8b3c2f7d0c655d72bbca9dcbd092d3ab275d47c5 Mon Sep 17 00:00:00 2001 From: Matt Lehmann Date: Wed, 30 Apr 2014 19:12:52 -0700 Subject: [PATCH 14/20] updated version of default user switch for load oar :q :q --- OpenSim/Region/Application/OpenSim.cs | 1 + .../World/Archiver/ArchiveReadRequest.cs | 22 ++++++++++++---- .../World/Archiver/ArchiverModule.cs | 26 ++++++++++++++++++- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index 544accf9fb..cc505f8540 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -272,6 +272,7 @@ namespace OpenSim + " [--no-objects]" + " [--rotation degrees] [--rotation-center \"\"]" + " [--displacement \"\"]" + + " [--default-user \"User Name\"]" + " []", "Load a region's data from an OAR archive.", "--merge will merge the OAR with the existing scene (suppresses terrain and parcel info loading)." + Environment.NewLine diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index a1629fba10..fe8735037f 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -160,10 +160,22 @@ namespace OpenSim.Region.CoreModules.World.Archiver private IAssetService m_assetService = null; + private UUID m_defaultUser; + public ArchiveReadRequest(Scene scene, string loadPath, Guid requestId, Dictionaryoptions) { m_rootScene = scene; + if (options.ContainsKey("default-user")) + { + m_defaultUser = (UUID)options["default-user"]; + m_log.InfoFormat("Using User {0} as default user", m_defaultUser.ToString()); + } + else + { + m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; + } + m_loadPath = loadPath; try { @@ -562,16 +574,16 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (string.IsNullOrEmpty(part.CreatorData)) { if (!ResolveUserUuid(scene, part.CreatorID)) - part.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + part.CreatorID = m_defaultUser; } if (UserManager != null) UserManager.AddUser(part.CreatorID, part.CreatorData); if (!(ResolveUserUuid(scene, part.OwnerID) || ResolveGroupUuid(part.OwnerID))) - part.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + part.OwnerID = m_defaultUser; if (!(ResolveUserUuid(scene, part.LastOwnerID) || ResolveGroupUuid(part.LastOwnerID))) - part.LastOwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + part.LastOwnerID = m_defaultUser; if (!ResolveGroupUuid(part.GroupID)) part.GroupID = UUID.Zero; @@ -590,13 +602,13 @@ namespace OpenSim.Region.CoreModules.World.Archiver { if (!(ResolveUserUuid(scene, kvp.Value.OwnerID) || ResolveGroupUuid(kvp.Value.OwnerID))) { - kvp.Value.OwnerID = scene.RegionInfo.EstateSettings.EstateOwner; + kvp.Value.OwnerID = m_defaultUser; } if (string.IsNullOrEmpty(kvp.Value.CreatorData)) { if (!ResolveUserUuid(scene, kvp.Value.CreatorID)) - kvp.Value.CreatorID = scene.RegionInfo.EstateSettings.EstateOwner; + kvp.Value.CreatorID = m_defaultUser; } if (UserManager != null) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 2b2da6f2de..6a09cafa73 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs @@ -108,6 +108,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver bool forceParcels = false; bool noObjects = false; Vector3 displacement = new Vector3(0f, 0f, 0f); + String defaultUser = ""; float rotation = 0f; Vector3 rotationCenter = new Vector3(Constants.RegionSize / 2f, Constants.RegionSize / 2f, 0); @@ -119,6 +120,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver options.Add("force-parcels", delegate (string v) { forceParcels = (v != null); }); options.Add("forceparcels", delegate (string v) { forceParcels = (v != null); }); // downward compatibility options.Add("no-objects", delegate (string v) { noObjects = (v != null); }); + options.Add("default-user=", delegate(string v) { defaultUser = (v == null) ? "" : v; }); options.Add("displacement=", delegate (string v) { try { @@ -131,7 +133,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver return; } }); - options.Add("rotation=", delegate (string v) { + options.Add("rotation=", delegate(string v) + { try { rotation = v == null ? 0f : float.Parse(v); @@ -181,6 +184,27 @@ namespace OpenSim.Region.CoreModules.World.Archiver if (forceTerrain) archiveOptions.Add("force-terrain", null); if (forceParcels) archiveOptions.Add("force-parcels", null); if (noObjects) archiveOptions.Add("no-objects", null); + if (defaultUser != "") + { + UUID defaultUserUUID = UUID.Zero; + try + { + defaultUserUUID = Scene.UserManagementModule.GetUserIdByName(defaultUser); + } + catch + { + m_log.ErrorFormat("[ARCHIVER MODULE] default user must be in format \"First Last\"", defaultUser); + } + if (defaultUserUUID == UUID.Zero) + { + m_log.ErrorFormat("[ARCHIVER MODULE] cannot find specified default user {0}", defaultUser); + return; + } + else + { + archiveOptions.Add("default-user", defaultUserUUID); + } + } archiveOptions.Add("displacement", displacement); archiveOptions.Add("rotation", rotation); archiveOptions.Add("rotation-center", rotationCenter); From 9e83b430092be363d87c829955f7d266ed996598 Mon Sep 17 00:00:00 2001 From: Matt Lehmann Date: Fri, 2 May 2014 18:00:34 -0700 Subject: [PATCH 15/20] new version of patch to add default-user switch new version :qw :wq updated version of default user switch for load oar :q :q --- OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index fe8735037f..e9c6fb63cd 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs @@ -218,6 +218,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver m_merge = options.ContainsKey("merge"); m_requestId = requestId; + m_defaultUser = scene.RegionInfo.EstateSettings.EstateOwner; + // Zero can never be a valid user id m_validUserUuids[UUID.Zero] = false; From 78015bbbdc50d41cc002aab838487ab902750c4f Mon Sep 17 00:00:00 2001 From: Dev Random Date: Sat, 12 Apr 2014 17:33:45 -0400 Subject: [PATCH 16/20] Console commands for Estate Mgmt --- OpenSim/Region/Application/OpenSim.cs | 113 ++++++++++++++++++ .../World/Estate/EstateManagementModule.cs | 63 ++++++++++ .../Framework/Interfaces/IEstateModule.cs | 3 + 3 files changed, 179 insertions(+) diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index cc505f8540..59b461439f 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -402,6 +402,12 @@ namespace OpenSim "Delete a region from disk", RunCommand); + m_console.Commands.AddCommand("Estates", false, "estate create", + "estate create ", + "Creates a new estate with the specified name, owned by the specified user." + + " Estate name must be unique.", + CreateEstateCommand); + m_console.Commands.AddCommand("Estates", false, "estate set owner", "estate set owner [ | ]", "Sets the owner of the specified estate to the specified UUID or user. ", @@ -411,6 +417,11 @@ namespace OpenSim "estate set name ", "Sets the name of the specified estate to the specified value. New name must be unique.", SetEstateNameCommand); + + m_console.Commands.AddCommand("Estates", false, "estate link region", + "estate link region ", + "Attaches the specified region to the specified estate.", + EstateLinkRegionCommand); } protected override void ShutdownSpecific() @@ -1177,6 +1188,58 @@ namespace OpenSim SceneManager.SaveCurrentSceneToArchive(cmdparams); } + protected void CreateEstateCommand(string module, string[] args) + { + string response = null; + UUID userID; + + if (args.Length == 2) + { + response = "No user specified."; + } + else if (!UUID.TryParse(args[2], out userID)) + { + response = String.Format("{0} is not a valid UUID", args[2]); + } + else if (args.Length == 3) + { + response = "No estate name specified."; + } + else + { + Scene scene = SceneManager.CurrentOrFirstScene; + + // TODO: Is there a better choice here? + UUID scopeID = UUID.Zero; + UserAccount account = scene.UserAccountService.GetUserAccount(scopeID, userID); + if (account == null) + { + response = String.Format("Could not find user {0}", userID); + } + else + { + // concatenate it all to "name" + StringBuilder sb = new StringBuilder(args[3]); + for (int i = 4; i < args.Length; i++) + sb.Append (" " + args[i]); + string estateName = sb.ToString().Trim(); + + // send it off for processing. + IEstateModule estateModule = scene.RequestModuleInterface(); + response = estateModule.CreateEstate(estateName, userID); + if (response == String.Empty) + { + List estates = scene.EstateDataService.GetEstates(estateName); + response = String.Format("Estate {0} created as \"{1}\"", estates.ElementAt(0), estateName); + } + } + } + + // give the user some feedback + if (response != null) + MainConsole.Instance.Output(response); + } + protected void SetEstateOwnerCommand(string module, string[] args) { string response = null; @@ -1299,6 +1362,56 @@ namespace OpenSim MainConsole.Instance.Output(response); } + private void EstateLinkRegionCommand(string module, string[] args) + { + int estateId =-1; + UUID regionId = UUID.Zero; + Scene scene = null; + string response = null; + + if (args.Length == 3) + { + response = "No estate specified."; + } + else if (!int.TryParse(args [3], out estateId)) + { + response = String.Format("\"{0}\" is not a valid ID for an Estate", args [3]); + } + else if (args.Length == 4) + { + response = "No region specified."; + } + else if (!UUID.TryParse(args[4], out regionId)) + { + response = String.Format("\"{0}\" is not a valid UUID for a Region", args [4]); + } + else if (!SceneManager.TryGetScene(regionId, out scene)) + { + // region may exist, but on a different sim. + response = String.Format("No access to Region \"{0}\"", args [4]); + } + + if (response != null) + { + MainConsole.Instance.Output(response); + return; + } + + // send it off for processing. + IEstateModule estateModule = scene.RequestModuleInterface(); + response = estateModule.SetRegionEstate(scene.RegionInfo, estateId); + if (response == String.Empty) + { + estateModule.TriggerRegionInfoChange(); + estateModule.sendRegionHandshakeToAll(); + response = String.Format ("Region {0} is now attached to estate {1}", regionId, estateId); + } + + // give the user some feedback + if (response != null) + MainConsole.Instance.Output (response); + } + #endregion private static string CombineParams(string[] commandParams, int pos) diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 54a7302c58..a032bc73d3 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs @@ -313,6 +313,69 @@ namespace OpenSim.Region.CoreModules.World.Estate return response; } + public string SetRegionEstate(RegionInfo regionInfo, int estateID) + { + string response; + + if (regionInfo.EstateSettings.EstateID == estateID) + { + response = String.Format("\"{0}\" is already part of estate {1}", regionInfo.RegionName, estateID); + } + else + { + // get the current settings from DB + EstateSettings dbSettings = Scene.EstateDataService.LoadEstateSettings(estateID); + if (dbSettings.EstateID == 0) + { + response = String.Format("No estate found with ID {0}", estateID); + } + else if (Scene.EstateDataService.LinkRegion(regionInfo.RegionID, estateID)) + { + // make sure there's a log entry to document the change + m_log.InfoFormat("[ESTATE]: Region {0} ({1}) moved to Estate {2} ({3}).", regionInfo.RegionID, regionInfo.RegionName, estateID, dbSettings.EstateName); + + // propagate the change + ChangeDelegate change = OnEstateInfoChange; + + if (change != null) + change(regionInfo.RegionID); + + response = String.Empty; + } + else + { + response = String.Format("Could not move \"{0}\" to estate {1}", regionInfo.RegionName, estateID); + } + } + return response; + } + + public string CreateEstate(string estateName, UUID ownerID) + { + string response; + if (string.IsNullOrEmpty(estateName)) + { + response = "No estate name specified."; + } + else + { + List estates = Scene.EstateDataService.GetEstates(estateName); + if (estates.Count() > 0) + { + response = String.Format("An estate named \"{0}\" already exists.", estateName); + } + else + { + EstateSettings settings = Scene.EstateDataService.CreateNewEstate(); + settings.EstateOwner = ownerID; + settings.EstateName = estateName; + settings.Save(); + response = String.Empty; + } + } + return response; + } + #endregion #region Packet Data Responders diff --git a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs index 600ecfe732..461c880fe0 100644 --- a/OpenSim/Region/Framework/Interfaces/IEstateModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEstateModule.cs @@ -26,6 +26,7 @@ */ using OpenMetaverse; +using OpenSim.Framework; using OpenSim.Services.Interfaces; namespace OpenSim.Region.Framework.Interfaces @@ -44,6 +45,8 @@ namespace OpenSim.Region.Framework.Interfaces string SetEstateOwner(int estateID, UserAccount account); string SetEstateName(int estateID, string newName); + string SetRegionEstate(RegionInfo regionInfo, int estateID); + string CreateEstate(string estateName, UUID ownerID); /// /// Tell all clients about the current state of the region (terrain textures, water height, etc.). From e44450cce1cd3a9077aec5514a1b9e65b8cffa0a Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 6 May 2014 19:53:35 +0100 Subject: [PATCH 17/20] Revert "fix infinite recursion loop in SendGridInstantMessageViaXMLRPCAsync()" There is a problem here with infinite recursion, but this patch loses the 'hunting' behaviour where the code will attempt multiple lookups if the avatar is teleporting rapidly around different simulators. This patch only does a single lookup before giving up. This reverts commit cecb446e0e91ede0b05ea9cf40c1313782241f3d. --- .../InstantMessage/MessageTransferModule.cs | 192 ++++++++++-------- 1 file changed, 106 insertions(+), 86 deletions(-) diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 4f8e2cdbfc..40a400f957 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -428,7 +428,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage /// /// delegate for sending a grid instant message asynchronously /// - public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result); + public delegate void GridInstantMessageDelegate(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID); protected virtual void GridInstantMessageCompleted(IAsyncResult iar) { @@ -442,118 +442,138 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage { GridInstantMessageDelegate d = SendGridInstantMessageViaXMLRPCAsync; - d.BeginInvoke(im, result, GridInstantMessageCompleted, d); + d.BeginInvoke(im, result, UUID.Zero, GridInstantMessageCompleted, d); } /// - /// Internal SendGridInstantMessage over XMLRPC method. + /// Recursive SendGridInstantMessage over XMLRPC method. /// This is called from within a dedicated thread. + /// The first time this is called, prevRegionHandle will be 0 Subsequent times this is called from + /// itself, prevRegionHandle will be the last region handle that we tried to send. + /// If the handles are the same, we look up the user's location using the grid. + /// If the handles are still the same, we end. The send failed. /// - private void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result) + /// + /// Pass in 0 the first time this method is called. It will be called recursively with the last + /// regionhandle tried + /// + protected virtual void SendGridInstantMessageViaXMLRPCAsync(GridInstantMessage im, MessageResultNotification result, UUID prevRegionID) { UUID toAgentID = new UUID(im.toAgentID); - UUID regionID; - bool lookupAgent; - /* - * Try to get what region the agent is in from the cache. - */ + PresenceInfo upd = null; + + bool lookupAgent = false; + lock (m_UserRegionMap) { - lookupAgent = !m_UserRegionMap.TryGetValue(toAgentID, out regionID); - } - - while (true) - { - - /* - * If not in cache, try to find out what region the agent is in. - * Also do this if we know the existing cache entry is bad. - */ - if (lookupAgent) + if (m_UserRegionMap.ContainsKey(toAgentID)) { - PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + upd = new PresenceInfo(); + upd.RegionID = m_UserRegionMap[toAgentID]; - regionID = UUID.Zero; - if (presences != null) + // We need to compare the current regionhandle with the previous region handle + // or the recursive loop will never end because it will never try to lookup the agent again + if (prevRegionID == upd.RegionID) { - foreach (PresenceInfo p in presences) + lookupAgent = true; + } + } + else + { + lookupAgent = true; + } + } + + + // Are we needing to look-up an agent? + if (lookupAgent) + { + // Non-cached user agent lookup. + PresenceInfo[] presences = PresenceService.GetAgents(new string[] { toAgentID.ToString() }); + if (presences != null && presences.Length > 0) + { + foreach (PresenceInfo p in presences) + { + if (p.RegionID != UUID.Zero) { - if (p.RegionID != UUID.Zero) - { - regionID = p.RegionID; - break; - } + upd = p; + break; } } - - // If not found, message is undeliverable - if (regionID == UUID.Zero) - { - break; - } } - /* - * Try to find out about region. - * If unable, message is undeliverable. - */ - GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, regionID); - if (reginfo == null) + if (upd != null) { - m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", regionID); - break; - } - - /* - * Try to send message to agent in the region. - */ - Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); - msgdata["region_handle"] = 0; - bool imresult = doIMSending(reginfo, msgdata); - - /* - * If message delivery successful, save cache entry because we know it is good. - * Then tell caller message has been delivered and we are done. - */ - if (imresult) - { - lock (m_UserRegionMap) + // check if we've tried this before.. + // This is one way to end the recursive loop + // + if (upd.RegionID == prevRegionID) { - m_UserRegionMap[toAgentID] = regionID; + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + HandleUndeliveredMessage(im, result); + return; } - result(true); + } + else + { + // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); + HandleUndeliveredMessage(im, result); return; } - - /* - * Message delivery failed. - * If we just looked up what region the agent is in, message is undeliverable. - */ - if (lookupAgent) - { - break; - } - - /* - * We used a cached entry that we now know is bad. - * Try again by searching the grid for the user. - */ - lookupAgent = true; } - /* - * Message is undeliverable for one reason or another. - * Remove possible bad entry from cache. - * Then inform caller that the message is undeliverable. - */ - lock (m_UserRegionMap) + if (upd != null) { - m_UserRegionMap.Remove(toAgentID); - } + GridRegion reginfo = m_Scenes[0].GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, + upd.RegionID); + if (reginfo != null) + { + Hashtable msgdata = ConvertGridInstantMessageToXMLRPC(im); + // Not actually used anymore, left in for compatibility + // Remove at next interface change + // + msgdata["region_handle"] = 0; + bool imresult = doIMSending(reginfo, msgdata); + if (imresult) + { + // IM delivery successful, so store the Agent's location in our local cache. + lock (m_UserRegionMap) + { + if (m_UserRegionMap.ContainsKey(toAgentID)) + { + m_UserRegionMap[toAgentID] = upd.RegionID; + } + else + { + m_UserRegionMap.Add(toAgentID, upd.RegionID); + } + } + result(true); + } + else + { + // try again, but lookup user this time. + // Warning, this must call the Async version + // of this method or we'll be making thousands of threads + // The version within the spawned thread is SendGridInstantMessageViaXMLRPCAsync + // The version that spawns the thread is SendGridInstantMessageViaXMLRPC - // m_log.Error("[GRID INSTANT MESSAGE]: Unable to deliver an instant message"); - HandleUndeliveredMessage(im, result); + // This is recursive!!!!! + SendGridInstantMessageViaXMLRPCAsync(im, result, + upd.RegionID); + } + } + else + { + m_log.WarnFormat("[GRID INSTANT MESSAGE]: Unable to find region {0}", upd.RegionID); + HandleUndeliveredMessage(im, result); + } + } + else + { + HandleUndeliveredMessage(im, result); + } } /// From 2fbafc74655892aa5f660a3ed840fa8c19f7e1d8 Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Tue, 6 May 2014 22:37:26 +0100 Subject: [PATCH 18/20] Add Matt Lehmann to contributors --- CONTRIBUTORS.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index f378925a89..fa79ea7d54 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -127,6 +127,7 @@ what it is today. * maimedleech * Mana Janus * MarcelEdward +* Matt Lehmann * Mic Bowman * Michelle Argus * Michael Cortez (The Flotsam Project, http://osflotsam.org/) From 812f5e124df0ef77a24c4937cc35cef0cac13cad Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 7 May 2014 18:39:56 +0100 Subject: [PATCH 19/20] Remove duplicate HypergridLinker entry from [GridService] in Robust.HG.ini.example --- bin/Robust.HG.ini.example | 2 -- 1 file changed, 2 deletions(-) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 14e9bff296..3dd984effc 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -163,8 +163,6 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset [GridService] LocalServiceModule = "OpenSim.Services.GridService.dll:GridService" - HypergridLinker = true - ; Realm = "regions" ; AllowDuplicateNames = "True" From 2b33677402c3a18ed753e78e02bb191bfcdcee5b Mon Sep 17 00:00:00 2001 From: "Justin Clark-Casey (justincc)" Date: Wed, 7 May 2014 23:32:02 +0100 Subject: [PATCH 20/20] Add GridUserService service config to [UserAccountService] in Robust[.HG].ini.example so that home can be set for new users rather than always warning that it can't be set. Code already exists to do this but forgot to put entry into config files a long time ago. Thanks to AliciaRaven for the spot. Relates to http://opensimulator.org/mantis/view.php?id=7155 --- bin/Robust.HG.ini.example | 1 + bin/Robust.ini.example | 1 + 2 files changed, 2 insertions(+) diff --git a/bin/Robust.HG.ini.example b/bin/Robust.HG.ini.example index 3dd984effc..e385200cdb 100644 --- a/bin/Robust.HG.ini.example +++ b/bin/Robust.HG.ini.example @@ -282,6 +282,7 @@ HGAssetServiceConnector = "HGAssetService@8002/OpenSim.Server.Handlers.dll:Asset GridService = "OpenSim.Services.GridService.dll:GridService" InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" + GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 ;; to show a default "Ruth" avatar rather than a cloud for a newly created user. diff --git a/bin/Robust.ini.example b/bin/Robust.ini.example index 829e3930b5..2f1a627961 100644 --- a/bin/Robust.ini.example +++ b/bin/Robust.ini.example @@ -240,6 +240,7 @@ MapGetServiceConnector = "8002/OpenSim.Server.Handlers.dll:MapGetServiceConnecto GridService = "OpenSim.Services.GridService.dll:GridService" InventoryService = "OpenSim.Services.InventoryService.dll:XInventoryService" AvatarService = "OpenSim.Services.AvatarService.dll:AvatarService" + GridUserService = "OpenSim.Services.UserAccountService.dll:GridUserService" ;; This switch creates the minimum set of body parts and avatar entries for a viewer 2 ;; to show a default "Ruth" avatar rather than a cloud for a newly created user.