From 915593bfbc2f0d6729efe4dfe8d4c8a3f0fc9fbe Mon Sep 17 00:00:00 2001 From: Justin Clarke Casey Date: Fri, 21 Nov 2008 21:16:42 +0000 Subject: * refactor: Rip out SOP inventory from the partial into a separate class * SceneObjectPartInventory.cs isn't a particularly good name but it's probably not got a long life * A proper inventory interface to follow * Parallel changes for other inventory partial classes to follow at a later date --- .../Agent/AssetTransaction/AssetXferUploader.cs | 2 +- .../Modules/World/Permissions/PermissionsModule.cs | 6 +- .../Region/Environment/Scenes/Scene.Inventory.cs | 40 +- OpenSim/Region/Environment/Scenes/Scene.cs | 8 +- .../Scenes/SceneObjectGroup.Inventory.cs | 27 +- .../Region/Environment/Scenes/SceneObjectGroup.cs | 6 +- .../Scenes/SceneObjectPart.Inventory.cs | 846 -------------------- .../Region/Environment/Scenes/SceneObjectPart.cs | 67 +- .../Environment/Scenes/SceneObjectPartInventory.cs | 872 +++++++++++++++++++++ OpenSim/Region/Environment/Scenes/ScenePresence.cs | 2 +- 10 files changed, 965 insertions(+), 911 deletions(-) delete mode 100644 OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs create mode 100644 OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs (limited to 'OpenSim/Region/Environment') diff --git a/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetXferUploader.cs index 05b7fa3..3ef2e1f 100644 --- a/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/Environment/Modules/Agent/AssetTransaction/AssetXferUploader.cs @@ -267,7 +267,7 @@ namespace OpenSim.Region.Environment.Modules.Agent.AssetTransaction m_userTransactions.Manager.MyScene.CommsManager.AssetCache.AddAsset(m_asset); - if (part.UpdateInventoryItem(item)) + if (part.Inventory.UpdateInventoryItem(item)) part.GetProperties(remoteClient); } diff --git a/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs index e41f975..d7865b2 100644 --- a/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/Environment/Modules/World/Permissions/PermissionsModule.cs @@ -796,7 +796,7 @@ namespace OpenSim.Region.Environment.Modules.World.Permissions if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; - TaskInventoryItem ti = part.GetInventoryItem(notecard); + TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); if (ti == null) return false; @@ -1188,7 +1188,7 @@ namespace OpenSim.Region.Environment.Modules.World.Permissions if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; - TaskInventoryItem ti = part.GetInventoryItem(script); + TaskInventoryItem ti = part.Inventory.GetInventoryItem(script); if (ti == null) return false; @@ -1266,7 +1266,7 @@ namespace OpenSim.Region.Environment.Modules.World.Permissions if ((part.OwnerMask & (uint)PermissionMask.Modify) == 0) return false; - TaskInventoryItem ti = part.GetInventoryItem(notecard); + TaskInventoryItem ti = part.Inventory.GetInventoryItem(notecard); if (ti == null) return false; diff --git a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs index 19b8e16..686f4ba 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.Inventory.cs @@ -280,7 +280,7 @@ namespace OpenSim.Region.Environment.Scenes if (isScriptRunning) { - part.RemoveScriptInstance(item.ItemID); + part.Inventory.RemoveScriptInstance(item.ItemID); } // Update item with new asset item.AssetID = asset.FullID; @@ -292,7 +292,7 @@ namespace OpenSim.Region.Environment.Scenes { // Needs to determine which engine was running it and use that // - part.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); + part.Inventory.CreateScriptInstance(item.ItemID, 0, false, DefaultScriptEngine, 0); } else { @@ -945,7 +945,7 @@ namespace OpenSim.Region.Environment.Scenes private InventoryItemBase CreateAgentInventoryItemFromTask(UUID destAgent, SceneObjectPart part, UUID itemId) { - TaskInventoryItem taskItem = part.GetInventoryItem(itemId); + TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); if (null == taskItem) { @@ -995,7 +995,7 @@ namespace OpenSim.Region.Environment.Scenes if (!ExternalChecks.ExternalChecksBypassPermissions()) { if ((taskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - part.RemoveInventoryItem(itemId); + part.Inventory.RemoveInventoryItem(itemId); } return agentItem; @@ -1040,7 +1040,7 @@ namespace OpenSim.Region.Environment.Scenes return; } - TaskInventoryItem taskItem = part.GetInventoryItem(itemId); + TaskInventoryItem taskItem = part.Inventory.GetInventoryItem(itemId); if (null == taskItem) { @@ -1104,7 +1104,7 @@ namespace OpenSim.Region.Environment.Scenes /// public void MoveTaskInventoryItem(UUID destId, SceneObjectPart part, UUID itemId) { - TaskInventoryItem srcTaskItem = part.GetInventoryItem(itemId); + TaskInventoryItem srcTaskItem = part.Inventory.GetInventoryItem(itemId); if (srcTaskItem == null) { @@ -1184,10 +1184,10 @@ namespace OpenSim.Region.Environment.Scenes destTaskItem.InvType = srcTaskItem.InvType; destTaskItem.Type = srcTaskItem.Type; - destPart.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID); + destPart.Inventory.AddInventoryItem(destTaskItem, part.OwnerID != destPart.OwnerID); if ((srcTaskItem.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - part.RemoveInventoryItem(itemId); + part.Inventory.RemoveInventoryItem(itemId); ScenePresence avatar; @@ -1254,7 +1254,7 @@ namespace OpenSim.Region.Environment.Scenes if (part != null) { - TaskInventoryItem currentItem = part.GetInventoryItem(itemID); + TaskInventoryItem currentItem = part.Inventory.GetInventoryItem(itemID); bool allowInventoryDrop = (part.GetEffectiveObjectFlags() & (uint)PrimFlags.AllowInventoryDrop) != 0; @@ -1314,7 +1314,7 @@ namespace OpenSim.Region.Environment.Scenes agentTransactions.HandleTaskItemUpdateFromTransaction( remoteClient, part, transactionID, currentItem); } - if (part.UpdateInventoryItem(itemInfo)) + if (part.Inventory.UpdateInventoryItem(itemInfo)) part.GetProperties(remoteClient); } } @@ -1364,7 +1364,7 @@ namespace OpenSim.Region.Environment.Scenes part.ParentGroup.AddInventoryItem(remoteClient, localID, item, copyID); // TODO: switch to posting on_rez here when scripts // have state in inventory - part.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); + part.Inventory.CreateScriptInstance(copyID, 0, false, DefaultScriptEngine, 0); // m_log.InfoFormat("[PRIMINVENTORY]: " + // "Rezzed script {0} into prim local ID {1} for user {2}", @@ -1430,10 +1430,10 @@ namespace OpenSim.Region.Environment.Scenes taskItem.PermsMask = 0; taskItem.AssetID = asset.FullID; - part.AddInventoryItem(taskItem, false); + part.Inventory.AddInventoryItem(taskItem, false); part.GetProperties(remoteClient); - part.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); + part.Inventory.CreateScriptInstance(taskItem, 0, false, DefaultScriptEngine, 0); } } @@ -1445,7 +1445,7 @@ namespace OpenSim.Region.Environment.Scenes /// public void RezScript(UUID srcId, SceneObjectPart srcPart, UUID destId, int pin, int running, int start_param) { - TaskInventoryItem srcTaskItem = srcPart.GetInventoryItem(srcId); + TaskInventoryItem srcTaskItem = srcPart.Inventory.GetInventoryItem(srcId); if (srcTaskItem == null) { @@ -1525,11 +1525,11 @@ namespace OpenSim.Region.Environment.Scenes destTaskItem.InvType = srcTaskItem.InvType; destTaskItem.Type = srcTaskItem.Type; - destPart.AddInventoryItemExclusive(destTaskItem, false); + destPart.Inventory.AddInventoryItemExclusive(destTaskItem, false); if (running > 0) { - destPart.CreateScriptInstance(destTaskItem, 0, false, DefaultScriptEngine, 0); + destPart.Inventory.CreateScriptInstance(destTaskItem, 0, false, DefaultScriptEngine, 0); } ScenePresence avatar; @@ -2064,7 +2064,7 @@ namespace OpenSim.Region.Environment.Scenes { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; - part.ChangeInventoryOwner(item.Owner); + part.Inventory.ChangeInventoryOwner(item.Owner); } else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! { @@ -2178,7 +2178,7 @@ namespace OpenSim.Region.Environment.Scenes { part.LastOwnerID = part.OwnerID; part.OwnerID = item.OwnerID; - part.ChangeInventoryOwner(item.OwnerID); + part.Inventory.ChangeInventoryOwner(item.OwnerID); } else if ((item.CurrentPermissions & 8) != 0) // Slam! { @@ -2200,7 +2200,7 @@ namespace OpenSim.Region.Environment.Scenes if (!ExternalChecks.ExternalChecksBypassPermissions()) { if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - sourcePart.RemoveInventoryItem(item.ItemID); + sourcePart.Inventory.RemoveInventoryItem(item.ItemID); } return rootPart.ParentGroup; } @@ -2368,7 +2368,7 @@ namespace OpenSim.Region.Environment.Scenes if (part != null && part.ParentGroup != null) { part.ParentGroup.SetOwnerId(ownerID); - part.ChangeInventoryOwner(ownerID); + part.Inventory.ChangeInventoryOwner(ownerID); part.ParentGroup.SetGroup(groupID, remoteClient); } } diff --git a/OpenSim/Region/Environment/Scenes/Scene.cs b/OpenSim/Region/Environment/Scenes/Scene.cs index 221af44..9c29c44 100644 --- a/OpenSim/Region/Environment/Scenes/Scene.cs +++ b/OpenSim/Region/Environment/Scenes/Scene.cs @@ -4277,8 +4277,8 @@ namespace OpenSim.Region.Environment.Scenes { foreach (SceneObjectPart child in partList) { - child.ChangeInventoryOwner(remoteClient.AgentId); - child.ApplyNextOwnerPermissions(); + child.Inventory.ChangeInventoryOwner(remoteClient.AgentId); + child.Inventory.ApplyNextOwnerPermissions(); } } @@ -4355,13 +4355,13 @@ namespace OpenSim.Region.Environment.Scenes break; case 3: // Sell contents - List invList = part.GetInventoryList(); + List invList = part.Inventory.GetInventoryList(); bool okToSell = true; foreach (UUID invID in invList) { - TaskInventoryItem item = part.GetInventoryItem(invID); + TaskInventoryItem item = part.Inventory.GetInventoryItem(invID); if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) { diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs index 21c7905..9ca5564 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.Inventory.cs @@ -50,7 +50,7 @@ namespace OpenSim.Region.Environment.Scenes { foreach (SceneObjectPart part in m_parts.Values) { - part.ForceInventoryPersistence(); + part.Inventory.ForceInventoryPersistence(); } } } @@ -66,8 +66,7 @@ namespace OpenSim.Region.Environment.Scenes { foreach (SceneObjectPart part in m_parts.Values) { - part.CreateScriptInstances(startParam, postOnRez, engine, - stateSource); + part.Inventory.CreateScriptInstances(startParam, postOnRez, engine, stateSource); } } } @@ -81,7 +80,7 @@ namespace OpenSim.Region.Environment.Scenes { foreach (SceneObjectPart part in m_parts.Values) { - part.RemoveScriptInstances(); + part.Inventory.RemoveScriptInstances(); } } } @@ -96,7 +95,7 @@ namespace OpenSim.Region.Environment.Scenes SceneObjectPart part = GetChildPart(localID); if (part != null) { - return part.GetInventoryFileName(remoteClient, localID); + return part.Inventory.GetInventoryFileName(remoteClient, localID); } else { @@ -118,7 +117,7 @@ namespace OpenSim.Region.Environment.Scenes SceneObjectPart part = GetChildPart(localID); if (part != null) { - part.RequestInventoryFile(client, xferManager); + part.Inventory.RequestInventoryFile(client, xferManager); } else { @@ -191,7 +190,7 @@ namespace OpenSim.Region.Environment.Scenes addFromAllowedDrop = remoteClient.AgentId != part.OwnerID; } - part.AddInventoryItem(taskItem, addFromAllowedDrop); + part.Inventory.AddInventoryItem(taskItem, addFromAllowedDrop); return true; } @@ -217,7 +216,7 @@ namespace OpenSim.Region.Environment.Scenes SceneObjectPart part = GetChildPart(primID); if (part != null) { - return part.GetInventoryItem(itemID); + return part.Inventory.GetInventoryItem(itemID); } else { @@ -241,7 +240,7 @@ namespace OpenSim.Region.Environment.Scenes SceneObjectPart part = GetChildPart(item.ParentPartID); if (part != null) { - part.UpdateInventoryItem(item); + part.Inventory.UpdateInventoryItem(item); return true; } @@ -261,7 +260,7 @@ namespace OpenSim.Region.Environment.Scenes SceneObjectPart part = GetChildPart(localID); if (part != null) { - int type = part.RemoveInventoryItem(itemID); + int type = part.Inventory.RemoveInventoryItem(itemID); return type; } @@ -280,7 +279,7 @@ namespace OpenSim.Region.Environment.Scenes foreach (SceneObjectPart part in m_parts.Values) { ownerMask &= part.OwnerMask; - perms &= part.MaskEffectivePermissions(); + perms &= part.Inventory.MaskEffectivePermissions(); } if ((ownerMask & (uint)PermissionMask.Modify) == 0) @@ -303,7 +302,7 @@ namespace OpenSim.Region.Environment.Scenes public void ApplyNextOwnerPermissions() { foreach (SceneObjectPart part in m_parts.Values) - part.ApplyNextOwnerPermissions(); + part.Inventory.ApplyNextOwnerPermissions(); } public string GetStateSnapshot() @@ -313,13 +312,13 @@ namespace OpenSim.Region.Environment.Scenes foreach (SceneObjectPart part in m_parts.Values) { - foreach (string a in part.GetScriptAssemblies()) + foreach (string a in part.Inventory.GetScriptAssemblies()) { if (a != "" && !assemblies.Contains(a)) assemblies.Add(a); } - foreach (KeyValuePair s in part.GetScriptStates()) + foreach (KeyValuePair s in part.Inventory.GetScriptStates()) { states[s.Key] = s.Value; } diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs index f9eaa89..fcda37b 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectGroup.cs @@ -1044,7 +1044,7 @@ namespace OpenSim.Region.Environment.Scenes { foreach (SceneObjectPart part in m_parts.Values) { -// part.RemoveScriptInstances(); +// part.Inventory.RemoveScriptInstances(); List avatars = Scene.GetScenePresences(); for (int i = 0; i < avatars.Count; i++) @@ -1251,7 +1251,7 @@ namespace OpenSim.Region.Environment.Scenes datastore.StoreObject(backup_group, m_scene.RegionInfo.RegionID); - backup_group.ForEachPart(delegate(SceneObjectPart part) { part.ProcessInventoryBackup(datastore); }); + backup_group.ForEachPart(delegate(SceneObjectPart part) { part.Inventory.ProcessInventoryBackup(datastore); }); backup_group = null; } @@ -2828,7 +2828,7 @@ namespace OpenSim.Region.Environment.Scenes foreach (SceneObjectPart part in m_parts.Values) { part.SetGroup(GroupID, client); - part.ChangeInventoryGroup(GroupID); + part.Inventory.ChangeInventoryGroup(GroupID); } HasGroupChanged = true; diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs deleted file mode 100644 index ba638e5..0000000 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.Inventory.cs +++ /dev/null @@ -1,846 +0,0 @@ -/* - * Copyright (c) Contributors, http://opensimulator.org/ - * See CONTRIBUTORS.TXT for a full list of copyright holders. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions are met: - * * Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * * Neither the name of the OpenSim 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 OpenMetaverse; -using log4net; -using OpenSim.Framework; -using OpenSim.Framework.Communications.Cache; -using OpenSim.Region.Interfaces; -using OpenSim.Region.Environment.Interfaces; -using OpenSim.Region.Environment.Scenes.Scripting; - -namespace OpenSim.Region.Environment.Scenes -{ - public partial class SceneObjectPart : IScriptHost - { - private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); - - private string m_inventoryFileName = String.Empty; - private int m_inventoryFileNameSerial = 0; - - /// - /// Serial count for inventory file , used to tell if inventory has changed - /// no need for this to be part of Database backup - /// - protected uint m_inventorySerial = 0; - - /// - /// Holds in memory prim inventory - /// - protected TaskInventoryDictionary m_taskInventory = new TaskInventoryDictionary(); - - /// - /// Tracks whether inventory has changed since the last persistent backup - /// - protected bool HasInventoryChanged; - - /// - /// Force the task inventory of this prim to persist at the next update sweep - /// - public void ForceInventoryPersistence() - { - HasInventoryChanged = true; - } - - /// - /// Reset UUIDs for all the items in the prim's inventory. This involves either generating - /// new ones or setting existing UUIDs to the correct parent UUIDs. - /// - /// If this method is called and there are inventory items, then we regard the inventory as having changed. - /// - /// Link number for the part - public void ResetInventoryIDs() - { - lock (TaskInventory) - { - if (0 == TaskInventory.Count) - return; - - HasInventoryChanged = true; - ParentGroup.HasGroupChanged = true; - IList items = new List(TaskInventory.Values); - TaskInventory.Clear(); - - foreach (TaskInventoryItem item in items) - { - item.ResetIDs(UUID); - TaskInventory.Add(item.ItemID, item); - } - } - } - - /// - /// Change every item in this prim's inventory to a new owner. - /// - /// - public void ChangeInventoryOwner(UUID ownerId) - { - lock (TaskInventory) - { - if (0 == TaskInventory.Count) - { - return; - } - - HasInventoryChanged = true; - ParentGroup.HasGroupChanged = true; - IList items = new List(TaskInventory.Values); - foreach (TaskInventoryItem item in items) - { - if (ownerId != item.OwnerID) - { - item.LastOwnerID = item.OwnerID; - item.OwnerID = ownerId; - } - } - } - } - - public void ChangeInventoryGroup(UUID groupID) - { - lock (TaskInventory) - { - if (0 == TaskInventory.Count) - { - return; - } - - HasInventoryChanged = true; - ParentGroup.HasGroupChanged = true; - IList items = new List(TaskInventory.Values); - foreach (TaskInventoryItem item in items) - { - if (groupID != item.GroupID) - { - item.GroupID = groupID; - } - } - } - } - - /// - /// Start all the scripts contained in this prim's inventory - /// - public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) - { - lock (m_taskInventory) - { - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if ((int)InventoryType.LSL == item.InvType) - { - CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); - } - } - } - } - - /// - /// Stop all the scripts in this prim. - /// - public void RemoveScriptInstances() - { - lock (m_taskInventory) - { - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if ((int)InventoryType.LSL == item.InvType) - { - RemoveScriptInstance(item.ItemID); - RemoveScriptEvents(item.ItemID); - } - } - } - } - - /// - /// Start a script which is in this prim's inventory. - /// - /// - /// - public void CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource) - { - // m_log.InfoFormat( - // "[PRIM INVENTORY]: " + - // "Starting script {0}, {1} in prim {2}, {3}", - // item.Name, item.ItemID, Name, UUID); - - if (!m_parentGroup.Scene.ExternalChecks.ExternalChecksCanRunScript(item.ItemID, UUID, item.OwnerID)) - return; - - AddFlag(PrimFlags.Scripted); - - if (!m_parentGroup.Scene.RegionInfo.RegionSettings.DisableScripts) - { - AssetCache cache = m_parentGroup.Scene.AssetCache; - - cache.GetAsset(item.AssetID, delegate(UUID assetID, AssetBase asset) - { - if (null == asset) - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't start script {0}, {1} since asset ID {2} could not be found", - item.Name, item.ItemID, item.AssetID); - } - else - { - m_taskInventory[item.ItemID].PermsMask = 0; - m_taskInventory[item.ItemID].PermsGranter = UUID.Zero; - string script = Utils.BytesToString(asset.Data); - m_parentGroup.Scene.EventManager.TriggerRezScript(LocalId, item.ItemID, script, - startParam, postOnRez, engine, stateSource); - m_parentGroup.AddActiveScriptCount(1); - ScheduleFullUpdate(); - } - }, false); - } - } - - /// - /// Start a script which is in this prim's inventory. - /// - /// - /// A - /// - public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) - { - lock (m_taskInventory) - { - if (m_taskInventory.ContainsKey(itemId)) - { - CreateScriptInstance(m_taskInventory[itemId], startParam, postOnRez, engine, stateSource); - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", - itemId, Name, UUID); - } - } - } - - /// - /// Stop a script which is in this prim's inventory. - /// - /// - public void RemoveScriptInstance(UUID itemId) - { - if (m_taskInventory.ContainsKey(itemId)) - { - m_parentGroup.Scene.EventManager.TriggerRemoveScript(LocalId, itemId); - m_parentGroup.AddActiveScriptCount(-1); - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2}", - itemId, Name, UUID); - } - } - - /// - /// Check if the inventory holds an item with a given name. - /// This method assumes that the task inventory is already locked. - /// - /// - /// - private bool InventoryContainsName(string name) - { - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if (item.Name == name) - return true; - } - return false; - } - - /// - /// For a given item name, return that name if it is available. Otherwise, return the next available - /// similar name (which is currently the original name with the next available numeric suffix). - /// - /// - /// - private string FindAvailableInventoryName(string name) - { - if (!InventoryContainsName(name)) - return name; - - int suffix=1; - while (suffix < 256) - { - string tryName=String.Format("{0} {1}", name, suffix); - if (!InventoryContainsName(tryName)) - return tryName; - suffix++; - } - return String.Empty; - } - - /// - /// Add an item to this prim's inventory. If an item with the same name already exists, then an alternative - /// name is chosen. - /// - /// - public void AddInventoryItem(TaskInventoryItem item, bool allowedDrop) - { - AddInventoryItem(item.Name, item, allowedDrop); - } - - /// - /// Add an item to this prim's inventory. If an item with the same name already exists, it is replaced. - /// - /// - public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) - { - List il = new List(m_taskInventory.Values); - foreach (TaskInventoryItem i in il) - { - if (i.Name == item.Name) - { - if (i.InvType == (int)InventoryType.LSL) - RemoveScriptInstance(i.ItemID); - - RemoveInventoryItem(i.ItemID); - break; - } - } - - AddInventoryItem(item.Name, item, allowedDrop); - } - - /// - /// Add an item to this prim's inventory. - /// - /// The name that the new item should have. - /// - /// The item itself. The name within this structure is ignored in favour of the name - /// given in this method's arguments - /// - /// - /// Item was only added to inventory because AllowedDrop is set - /// - protected void AddInventoryItem(string name, TaskInventoryItem item, bool allowedDrop) - { - name = FindAvailableInventoryName(name); - if (name == String.Empty) - return; - - item.ParentID = UUID; - item.ParentPartID = UUID; - item.Name = name; - - lock (m_taskInventory) - { - m_taskInventory.Add(item.ItemID, item); - - if (allowedDrop) - TriggerScriptChangedEvent(Changed.ALLOWED_DROP); - else - TriggerScriptChangedEvent(Changed.INVENTORY); - } - - m_inventorySerial++; - //m_inventorySerial += 2; - HasInventoryChanged = true; - ParentGroup.HasGroupChanged = true; - } - - /// - /// Restore a whole collection of items to the prim's inventory at once. - /// We assume that the items already have all their fields correctly filled out. - /// The items are not flagged for persistence to the database, since they are being restored - /// from persistence rather than being newly added. - /// - /// - public void RestoreInventoryItems(ICollection items) - { - lock (m_taskInventory) - { - foreach (TaskInventoryItem item in items) - { - m_taskInventory.Add(item.ItemID, item); - TriggerScriptChangedEvent(Changed.INVENTORY); - } - } - - m_inventorySerial++; - } - - /// - /// Returns an existing inventory item. Returns the original, so any changes will be live. - /// - /// - /// null if the item does not exist - public TaskInventoryItem GetInventoryItem(UUID itemId) - { - TaskInventoryItem item; - m_taskInventory.TryGetValue(itemId, out item); - - return item; - } - - /// - /// Update an existing inventory item. - /// - /// The updated item. An item with the same id must already exist - /// in this prim's inventory. - /// false if the item did not exist, true if the update occurred successfully - public bool UpdateInventoryItem(TaskInventoryItem item) - { - lock (m_taskInventory) - { - if (m_taskInventory.ContainsKey(item.ItemID)) - { - item.ParentID = UUID; - item.ParentPartID = UUID; - item.Flags=m_taskInventory[item.ItemID].Flags; - if (item.AssetID == UUID.Zero) - { - item.AssetID = m_taskInventory[item.ItemID].AssetID; - } - else if ((InventoryType)item.Type == InventoryType.Notecard) - { - ScenePresence presence = - m_parentGroup.Scene.GetScenePresence( - item.OwnerID); - - if (presence != null) - { - presence.ControllingClient.SendAgentAlertMessage( - "Notecard saved", false); - } - } - - m_taskInventory[item.ItemID] = item; - m_inventorySerial++; - TriggerScriptChangedEvent(Changed.INVENTORY); - - HasInventoryChanged = true; - ParentGroup.HasGroupChanged = true; - - return true; - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", - item.ItemID, Name, UUID); - } - } - - return false; - } - - public void AddScriptLPS(int count) - { - m_parentGroup.AddScriptLPS(count); - } - - /// - /// Remove an item from this prim's inventory - /// - /// - /// Numeric asset type of the item removed. Returns -1 if the item did not exist - /// in this prim's inventory. - public int RemoveInventoryItem(UUID itemID) - { - lock (m_taskInventory) - { - if (m_taskInventory.ContainsKey(itemID)) - { - int type = m_taskInventory[itemID].InvType; - m_taskInventory.Remove(itemID); - m_inventorySerial++; - TriggerScriptChangedEvent(Changed.INVENTORY); - - HasInventoryChanged = true; - ParentGroup.HasGroupChanged = true; - - int scriptcount = 0; - lock (m_taskInventory) - { - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if (item.Type == 10) - { - scriptcount++; - } - } - - } - - if (scriptcount <= 0) - { - RemFlag(PrimFlags.Scripted); - } - - ScheduleFullUpdate(); - - return type; - } - else - { - m_log.ErrorFormat( - "[PRIM INVENTORY]: " + - "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", - itemID, Name, UUID); - } - } - - return -1; - } - - public string GetInventoryFileName() - { - if (m_inventoryFileName == String.Empty) - m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; - if (m_inventoryFileNameSerial < m_inventorySerial) - { - m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; - } - return m_inventoryFileName; - } - - /// - /// Return the name with which a client can request a xfer of this prim's inventory metadata - /// - /// - /// - public bool GetInventoryFileName(IClientAPI client, uint localID) - { -// m_log.DebugFormat( -// "[PRIM INVENTORY]: Received request from client {0} for inventory file name of {1}, {2}", -// client.AgentId, Name, UUID); - - if (m_inventorySerial > 0) - { - client.SendTaskInventory(m_uuid, (short)m_inventorySerial, - Utils.StringToBytes(GetInventoryFileName())); - return true; - } - else - { - client.SendTaskInventory(m_uuid, 0, new byte[0]); - return false; - } - } - - /// - /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client - /// - /// - public void RequestInventoryFile(IClientAPI client, IXfer xferManager) - { - byte[] fileData = new byte[0]; - - // Confusingly, the folder item has to be the object id, while the 'parent id' has to be zero. This matches - // what appears to happen in the Second Life protocol. If this isn't the case. then various functionality - // isn't available (such as drag from prim inventory to agent inventory) - InventoryStringBuilder invString = new InventoryStringBuilder(UUID, UUID.Zero); - - lock (m_taskInventory) - { - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - UUID ownerID = item.OwnerID; - uint everyoneMask = 0; - uint baseMask = item.BasePermissions; - uint ownerMask = item.CurrentPermissions; - - invString.AddItemStart(); - invString.AddNameValueLine("item_id", item.ItemID.ToString()); - invString.AddNameValueLine("parent_id", UUID.ToString()); - - invString.AddPermissionsStart(); - - invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); - invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); - invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); - invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); - invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); - - invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); - invString.AddNameValueLine("owner_id", ownerID.ToString()); - - invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); - - invString.AddNameValueLine("group_id", item.GroupID.ToString()); - invString.AddSectionEnd(); - - invString.AddNameValueLine("asset_id", item.AssetID.ToString()); - invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); - invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); - invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); - - invString.AddSaleStart(); - invString.AddNameValueLine("sale_type", "not"); - invString.AddNameValueLine("sale_price", "0"); - invString.AddSectionEnd(); - - invString.AddNameValueLine("name", item.Name + "|"); - invString.AddNameValueLine("desc", item.Description + "|"); - - invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); - invString.AddSectionEnd(); - } - } - - fileData = Utils.StringToBytes(invString.BuildString); - - //Console.WriteLine(Utils.BytesToString(fileData)); - //m_log.Debug("[PRIM INVENTORY]: RequestInventoryFile fileData: " + Utils.BytesToString(fileData)); - - if (fileData.Length > 2) - { - xferManager.AddNewFile(m_inventoryFileName, fileData); - } - } - - /// - /// Process inventory backup - /// - /// - public void ProcessInventoryBackup(IRegionDataStore datastore) - { - if (HasInventoryChanged) - { - lock (TaskInventory) - { - datastore.StorePrimInventory(UUID, TaskInventory.Values); - } - - HasInventoryChanged = false; - } - } - - public class InventoryStringBuilder - { - public string BuildString = String.Empty; - - public InventoryStringBuilder(UUID folderID, UUID parentID) - { - BuildString += "\tinv_object\t0\n\t{\n"; - AddNameValueLine("obj_id", folderID.ToString()); - AddNameValueLine("parent_id", parentID.ToString()); - AddNameValueLine("type", "category"); - AddNameValueLine("name", "Contents|"); - AddSectionEnd(); - } - - public void AddItemStart() - { - BuildString += "\tinv_item\t0\n"; - AddSectionStart(); - } - - public void AddPermissionsStart() - { - BuildString += "\tpermissions 0\n"; - AddSectionStart(); - } - - public void AddSaleStart() - { - BuildString += "\tsale_info\t0\n"; - AddSectionStart(); - } - - protected void AddSectionStart() - { - BuildString += "\t{\n"; - } - - public void AddSectionEnd() - { - BuildString += "\t}\n"; - } - - public void AddLine(string addLine) - { - BuildString += addLine; - } - - public void AddNameValueLine(string name, string value) - { - BuildString += "\t\t"; - BuildString += name + "\t"; - BuildString += value + "\n"; - } - - public void Close() - { - } - } - - public uint MaskEffectivePermissions() - { - uint mask=0x7fffffff; - - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if (item.InvType != 6) - { - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) - mask &= ~((uint)PermissionMask.Copy >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) - mask &= ~((uint)PermissionMask.Transfer >> 13); - if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~((uint)PermissionMask.Modify >> 13); - } - else - { - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - mask &= ~((uint)PermissionMask.Copy >> 13); - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - mask &= ~((uint)PermissionMask.Transfer >> 13); - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - mask &= ~((uint)PermissionMask.Modify >> 13); - } - - if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) - mask &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) - mask &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) - mask &= ~(uint)PermissionMask.Modify; - } - return mask; - } - - public void ApplyNextOwnerPermissions() - { - _baseMask &= _nextOwnerMask; - _ownerMask &= _nextOwnerMask; - _everyoneMask &= _nextOwnerMask; - - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if (item.InvType == 6 && (item.CurrentPermissions & 7) != 0) - { - if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Copy; - if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; - if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) - item.CurrentPermissions &= ~(uint)PermissionMask.Modify; - } - item.CurrentPermissions &= item.NextPermissions; - item.BasePermissions &= item.NextPermissions; - item.EveryonePermissions &= item.NextPermissions; - } - - TriggerScriptChangedEvent(Changed.OWNER); - } - - public void ApplyGodPermissions(uint perms) - { - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - item.CurrentPermissions = perms; - item.BasePermissions = perms; - } - } - - public bool ContainsScripts() - { - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if (item.InvType == 10) - { - return true; - } - } - return false; - } - - public List GetInventoryList() - { - List ret = new List(); - - foreach (TaskInventoryItem item in m_taskInventory.Values) - ret.Add(item.ItemID); - - return ret; - } - - public string[] GetScriptAssemblies() - { - IScriptModule[] engines = m_parentGroup.Scene.RequestModuleInterfaces(); - - List ret = new List(); - - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if (item.InvType == 10) - { - foreach (IScriptModule e in engines) - { - string n = e.GetAssemblyName(item.ItemID); - if (n != "") - { - if (!ret.Contains(n)) - ret.Add(n); - break; - } - } - } - } - return ret.ToArray(); - } - - public Dictionary GetScriptStates() - { - IScriptModule[] engines = m_parentGroup.Scene.RequestModuleInterfaces(); - Dictionary ret = new Dictionary(); - - foreach (TaskInventoryItem item in m_taskInventory.Values) - { - if (item.InvType == 10) - { - foreach (IScriptModule e in engines) - { - string n = e.GetXMLState(item.ItemID); - if (n != "") - { - if (!ret.ContainsKey(item.ItemID)) - ret[item.ItemID] = n; - break; - } - } - } - } - return ret; - } - } -} diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs index 888643e..250c803 100644 --- a/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPart.cs @@ -28,20 +28,20 @@ using System; using System.Collections.Generic; using System.Drawing; +using System.Reflection; using System.Runtime.Serialization; using System.Security.Permissions; using System.Xml; using System.Xml.Serialization; - +using log4net; using OpenMetaverse; using OpenMetaverse.Packets; - using OpenSim.Framework; using OpenSim.Region.Environment.Scenes.Scripting; using OpenSim.Region.Physics.Manager; namespace OpenSim.Region.Environment.Scenes -{ +{ #region Enumerations [Flags] @@ -92,8 +92,10 @@ namespace OpenSim.Region.Environment.Scenes #endregion Enumerations [Serializable] - public partial class SceneObjectPart : IScriptHost, ISerializable + public class SceneObjectPart : IScriptHost, ISerializable { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + #region Fields [XmlIgnore] @@ -140,6 +142,12 @@ namespace OpenSim.Region.Environment.Scenes public uint AttachmentPoint = (byte)0; [XmlIgnore] public PhysicsVector RotationAxis = new PhysicsVector(1f,1f,1f); + + /// + /// This part's inventory + /// + [XmlIgnore] + public readonly SceneObjectPartInventory Inventory; [XmlIgnore] public bool Undoing = false; @@ -218,6 +226,8 @@ namespace OpenSim.Region.Environment.Scenes m_TextureAnimation = new byte[0]; m_particleSystem = new byte[0]; Rezzed = DateTime.Now; + + Inventory = new SceneObjectPartInventory(this); } /// @@ -266,6 +276,8 @@ namespace OpenSim.Region.Environment.Scenes TrimPermissions(); //m_undo = new UndoStack(ParentGroup.GetSceneMaxUndo()); + + Inventory = new SceneObjectPartInventory(this); } protected SceneObjectPart(SerializationInfo info, StreamingContext context) @@ -285,6 +297,8 @@ namespace OpenSim.Region.Environment.Scenes //System.Console.WriteLine("SceneObjectPart Deserialize END"); Rezzed = DateTime.Now; + + Inventory = new SceneObjectPartInventory(this); } #endregion Constructors @@ -332,16 +346,22 @@ namespace OpenSim.Region.Environment.Scenes set { } // Don't allow assignment, or legacy prims wil b0rk } + /// + /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes + /// public uint InventorySerial { - get { return m_inventorySerial; } - set { m_inventorySerial = value; } + get { return Inventory.Serial; } + set { Inventory.Serial = value; } } + /// + /// Access should be via Inventory directly - this property temporarily remains for xml serialization purposes + /// public TaskInventoryDictionary TaskInventory { - get { return m_taskInventory; } - set { m_taskInventory = value; } + get { return Inventory.Items; } + set { Inventory.Items = value; } } public uint ObjectFlags @@ -1239,7 +1259,7 @@ if (m_shape != null) { dupe._category = _category; dupe.m_rezzed = m_rezzed; - dupe.TaskInventory = (TaskInventoryDictionary)dupe.TaskInventory.Clone(); + dupe.Inventory.Items = (TaskInventoryDictionary)dupe.Inventory.Items.Clone(); if (userExposed) dupe.ResetIDs(linkNum); @@ -1412,7 +1432,7 @@ if (m_shape != null) { throw new ArgumentNullException("info"); } - info.AddValue("m_inventoryFileName", GetInventoryFileName()); + info.AddValue("m_inventoryFileName", Inventory.GetInventoryFileName()); info.AddValue("m_folderID", UUID); info.AddValue("PhysActor", PhysActor); @@ -1452,7 +1472,7 @@ if (m_shape != null) { info.AddValue("m_updateFlag", m_updateFlag); info.AddValue("CreatorID", _creatorID.Guid); - info.AddValue("m_inventorySerial", m_inventorySerial); + info.AddValue("m_inventorySerial", Inventory.Serial); info.AddValue("m_uuid", m_uuid.Guid); info.AddValue("m_localID", m_localId); info.AddValue("m_name", m_name); @@ -1929,8 +1949,7 @@ if (m_shape != null) { UUID = UUID.Random(); LinkNum = linkNum; LocalId = 0; - - ResetInventoryIDs(); + Inventory.ResetInventoryIDs(); } /// @@ -2993,7 +3012,7 @@ if (m_shape != null) { if (god) { _baseMask = ApplyMask(_baseMask, set, mask); - ApplyGodPermissions(_baseMask); + Inventory.ApplyGodPermissions(_baseMask); } break; @@ -3394,9 +3413,19 @@ if (m_shape != null) { RotationalVelocity, state, FromAssetID, OwnerID, (int)AttachmentPoint); } - } -} - - - + + public void AddScriptLPS(int count) + { + m_parentGroup.AddScriptLPS(count); + } + + public void ApplyNextOwnerPermissions() + { + _baseMask &= _nextOwnerMask; + _ownerMask &= _nextOwnerMask; + _everyoneMask &= _nextOwnerMask; + Inventory.ApplyNextOwnerPermissions(); + } + } +} diff --git a/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs new file mode 100644 index 0000000..0a6f22c --- /dev/null +++ b/OpenSim/Region/Environment/Scenes/SceneObjectPartInventory.cs @@ -0,0 +1,872 @@ +/* + * 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 OpenSim 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 OpenMetaverse; +using log4net; +using OpenSim.Framework; +using OpenSim.Framework.Communications.Cache; +using OpenSim.Region.Interfaces; +using OpenSim.Region.Environment.Interfaces; +using OpenSim.Region.Environment.Scenes.Scripting; + +namespace OpenSim.Region.Environment.Scenes +{ + public class SceneObjectPartInventory + { + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + + private string m_inventoryFileName = String.Empty; + private int m_inventoryFileNameSerial = 0; + + /// + /// The part to which the inventory belongs. + /// + private SceneObjectPart m_part; + + /// + /// Serial count for inventory file , used to tell if inventory has changed + /// no need for this to be part of Database backup + /// + protected uint m_inventorySerial = 0; + + /// + /// Holds in memory prim inventory + /// + protected TaskInventoryDictionary m_items = new TaskInventoryDictionary(); + + /// + /// Tracks whether inventory has changed since the last persistent backup + /// + protected bool HasInventoryChanged; + + /// + /// Inventory serial number + /// + public uint Serial + { + get { return m_inventorySerial; } + set { m_inventorySerial = value; } + } + + /// + /// Raw inventory data + /// + public TaskInventoryDictionary Items + { + get { return m_items; } + set { m_items = value; } + } + + /// + /// Constructor + /// + /// + /// A + /// + public SceneObjectPartInventory(SceneObjectPart part) + { + m_part = part; + } + + /// + /// Force the task inventory of this prim to persist at the next update sweep + /// + public void ForceInventoryPersistence() + { + HasInventoryChanged = true; + } + + /// + /// Reset UUIDs for all the items in the prim's inventory. This involves either generating + /// new ones or setting existing UUIDs to the correct parent UUIDs. + /// + /// If this method is called and there are inventory items, then we regard the inventory as having changed. + /// + /// Link number for the part + public void ResetInventoryIDs() + { + lock (Items) + { + if (0 == Items.Count) + return; + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + Items.Clear(); + + foreach (TaskInventoryItem item in items) + { + item.ResetIDs(m_part.UUID); + Items.Add(item.ItemID, item); + } + } + } + + /// + /// Change every item in this inventory to a new owner. + /// + /// + public void ChangeInventoryOwner(UUID ownerId) + { + lock (Items) + { + if (0 == Items.Count) + { + return; + } + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + foreach (TaskInventoryItem item in items) + { + if (ownerId != item.OwnerID) + { + item.LastOwnerID = item.OwnerID; + item.OwnerID = ownerId; + } + } + } + } + + /// + /// Change every item in this inventory to a new group. + /// + /// + public void ChangeInventoryGroup(UUID groupID) + { + lock (Items) + { + if (0 == Items.Count) + { + return; + } + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + IList items = new List(Items.Values); + foreach (TaskInventoryItem item in items) + { + if (groupID != item.GroupID) + { + item.GroupID = groupID; + } + } + } + } + + /// + /// Start all the scripts contained in this prim's inventory + /// + public void CreateScriptInstances(int startParam, bool postOnRez, string engine, int stateSource) + { + lock (m_items) + { + foreach (TaskInventoryItem item in Items.Values) + { + if ((int)InventoryType.LSL == item.InvType) + { + CreateScriptInstance(item, startParam, postOnRez, engine, stateSource); + } + } + } + } + + /// + /// Stop all the scripts in this prim. + /// + public void RemoveScriptInstances() + { + lock (Items) + { + foreach (TaskInventoryItem item in Items.Values) + { + if ((int)InventoryType.LSL == item.InvType) + { + RemoveScriptInstance(item.ItemID); + m_part.RemoveScriptEvents(item.ItemID); + } + } + } + } + + /// + /// Start a script which is in this prim's inventory. + /// + /// + /// + public void CreateScriptInstance(TaskInventoryItem item, int startParam, bool postOnRez, string engine, int stateSource) + { + // m_log.InfoFormat( + // "[PRIM INVENTORY]: " + + // "Starting script {0}, {1} in prim {2}, {3}", + // item.Name, item.ItemID, Name, UUID); + + if (!m_part.ParentGroup.Scene.ExternalChecks.ExternalChecksCanRunScript(item.ItemID, m_part.UUID, item.OwnerID)) + return; + + m_part.AddFlag(PrimFlags.Scripted); + + if (!m_part.ParentGroup.Scene.RegionInfo.RegionSettings.DisableScripts) + { + AssetCache cache = m_part.ParentGroup.Scene.AssetCache; + + cache.GetAsset(item.AssetID, delegate(UUID assetID, AssetBase asset) + { + if (null == asset) + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't start script {0}, {1} since asset ID {2} could not be found", + item.Name, item.ItemID, item.AssetID); + } + else + { + m_items[item.ItemID].PermsMask = 0; + m_items[item.ItemID].PermsGranter = UUID.Zero; + string script = Utils.BytesToString(asset.Data); + m_part.ParentGroup.Scene.EventManager.TriggerRezScript( + m_part.LocalId, item.ItemID, script, startParam, postOnRez, engine, stateSource); + m_part.ParentGroup.AddActiveScriptCount(1); + m_part.ScheduleFullUpdate(); + } + }, false); + } + } + + /// + /// Start a script which is in this prim's inventory. + /// + /// + /// A + /// + public void CreateScriptInstance(UUID itemId, int startParam, bool postOnRez, string engine, int stateSource) + { + lock (m_items) + { + if (m_items.ContainsKey(itemId)) + { + CreateScriptInstance(m_items[itemId], startParam, postOnRez, engine, stateSource); + } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't start script with ID {0} since it couldn't be found for prim {1}, {2}", + itemId, m_part.Name, m_part.UUID); + } + } + } + + /// + /// Stop a script which is in this prim's inventory. + /// + /// + public void RemoveScriptInstance(UUID itemId) + { + if (m_items.ContainsKey(itemId)) + { + m_part.ParentGroup.Scene.EventManager.TriggerRemoveScript(m_part.LocalId, itemId); + m_part.ParentGroup.AddActiveScriptCount(-1); + } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Couldn't stop script with ID {0} since it couldn't be found for prim {1}, {2}", + itemId, m_part.Name, m_part.UUID); + } + } + + /// + /// Check if the inventory holds an item with a given name. + /// This method assumes that the task inventory is already locked. + /// + /// + /// + private bool InventoryContainsName(string name) + { + foreach (TaskInventoryItem item in Items.Values) + { + if (item.Name == name) + return true; + } + return false; + } + + /// + /// For a given item name, return that name if it is available. Otherwise, return the next available + /// similar name (which is currently the original name with the next available numeric suffix). + /// + /// + /// + private string FindAvailableInventoryName(string name) + { + if (!InventoryContainsName(name)) + return name; + + int suffix=1; + while (suffix < 256) + { + string tryName=String.Format("{0} {1}", name, suffix); + if (!InventoryContainsName(tryName)) + return tryName; + suffix++; + } + return String.Empty; + } + + /// + /// Add an item to this prim's inventory. If an item with the same name already exists, then an alternative + /// name is chosen. + /// + /// + public void AddInventoryItem(TaskInventoryItem item, bool allowedDrop) + { + AddInventoryItem(item.Name, item, allowedDrop); + } + + /// + /// Add an item to this prim's inventory. If an item with the same name already exists, it is replaced. + /// + /// + public void AddInventoryItemExclusive(TaskInventoryItem item, bool allowedDrop) + { + List il = new List(m_items.Values); + foreach (TaskInventoryItem i in il) + { + if (i.Name == item.Name) + { + if (i.InvType == (int)InventoryType.LSL) + RemoveScriptInstance(i.ItemID); + + RemoveInventoryItem(i.ItemID); + break; + } + } + + AddInventoryItem(item.Name, item, allowedDrop); + } + + /// + /// Add an item to this prim's inventory. + /// + /// The name that the new item should have. + /// + /// The item itself. The name within this structure is ignored in favour of the name + /// given in this method's arguments + /// + /// + /// Item was only added to inventory because AllowedDrop is set + /// + protected void AddInventoryItem(string name, TaskInventoryItem item, bool allowedDrop) + { + name = FindAvailableInventoryName(name); + if (name == String.Empty) + return; + + item.ParentID = m_part.UUID; + item.ParentPartID = m_part.UUID; + item.Name = name; + + lock (m_items) + { + m_items.Add(item.ItemID, item); + + if (allowedDrop) + m_part.TriggerScriptChangedEvent(Changed.ALLOWED_DROP); + else + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + } + + m_inventorySerial++; + //m_inventorySerial += 2; + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + } + + /// + /// Restore a whole collection of items to the prim's inventory at once. + /// We assume that the items already have all their fields correctly filled out. + /// The items are not flagged for persistence to the database, since they are being restored + /// from persistence rather than being newly added. + /// + /// + public void RestoreInventoryItems(ICollection items) + { + lock (m_items) + { + foreach (TaskInventoryItem item in items) + { + m_items.Add(item.ItemID, item); + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + } + } + + m_inventorySerial++; + } + + /// + /// Returns an existing inventory item. Returns the original, so any changes will be live. + /// + /// + /// null if the item does not exist + public TaskInventoryItem GetInventoryItem(UUID itemId) + { + TaskInventoryItem item; + m_items.TryGetValue(itemId, out item); + + return item; + } + + /// + /// Update an existing inventory item. + /// + /// The updated item. An item with the same id must already exist + /// in this prim's inventory. + /// false if the item did not exist, true if the update occurred successfully + public bool UpdateInventoryItem(TaskInventoryItem item) + { + lock (m_items) + { + if (m_items.ContainsKey(item.ItemID)) + { + item.ParentID = m_part.UUID; + item.ParentPartID = m_part.UUID; + item.Flags = m_items[item.ItemID].Flags; + if (item.AssetID == UUID.Zero) + { + item.AssetID = m_items[item.ItemID].AssetID; + } + else if ((InventoryType)item.Type == InventoryType.Notecard) + { + ScenePresence presence = m_part.ParentGroup.Scene.GetScenePresence(item.OwnerID); + + if (presence != null) + { + presence.ControllingClient.SendAgentAlertMessage( + "Notecard saved", false); + } + } + + m_items[item.ItemID] = item; + m_inventorySerial++; + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + + return true; + } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Tried to retrieve item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + item.ItemID, m_part.Name, m_part.UUID); + } + } + + return false; + } + + /// + /// Remove an item from this prim's inventory + /// + /// + /// Numeric asset type of the item removed. Returns -1 if the item did not exist + /// in this prim's inventory. + public int RemoveInventoryItem(UUID itemID) + { + lock (m_items) + { + if (m_items.ContainsKey(itemID)) + { + int type = m_items[itemID].InvType; + m_items.Remove(itemID); + m_inventorySerial++; + m_part.TriggerScriptChangedEvent(Changed.INVENTORY); + + HasInventoryChanged = true; + m_part.ParentGroup.HasGroupChanged = true; + + int scriptcount = 0; + lock (m_items) + { + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.Type == 10) + { + scriptcount++; + } + } + } + + if (scriptcount <= 0) + { + m_part.RemFlag(PrimFlags.Scripted); + } + + m_part.ScheduleFullUpdate(); + + return type; + } + else + { + m_log.ErrorFormat( + "[PRIM INVENTORY]: " + + "Tried to remove item ID {0} from prim {1}, {2} but the item does not exist in this inventory", + itemID, m_part.Name, m_part.UUID); + } + } + + return -1; + } + + public string GetInventoryFileName() + { + if (m_inventoryFileName == String.Empty) + m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; + if (m_inventoryFileNameSerial < m_inventorySerial) + { + m_inventoryFileName = "inventory_" + UUID.Random().ToString() + ".tmp"; + } + return m_inventoryFileName; + } + + /// + /// Return the name with which a client can request a xfer of this prim's inventory metadata + /// + /// + /// + public bool GetInventoryFileName(IClientAPI client, uint localID) + { +// m_log.DebugFormat( +// "[PRIM INVENTORY]: Received request from client {0} for inventory file name of {1}, {2}", +// client.AgentId, Name, UUID); + + if (m_inventorySerial > 0) + { + client.SendTaskInventory(m_part.UUID, (short)m_inventorySerial, + Utils.StringToBytes(GetInventoryFileName())); + return true; + } + else + { + client.SendTaskInventory(m_part.UUID, 0, new byte[0]); + return false; + } + } + + /// + /// Serialize all the metadata for the items in this prim's inventory ready for sending to the client + /// + /// + public void RequestInventoryFile(IClientAPI client, IXfer xferManager) + { + byte[] fileData = new byte[0]; + + // Confusingly, the folder item has to be the object id, while the 'parent id' has to be zero. This matches + // what appears to happen in the Second Life protocol. If this isn't the case. then various functionality + // isn't available (such as drag from prim inventory to agent inventory) + InventoryStringBuilder invString = new InventoryStringBuilder(m_part.UUID, UUID.Zero); + + lock (m_items) + { + foreach (TaskInventoryItem item in m_items.Values) + { + UUID ownerID = item.OwnerID; + uint everyoneMask = 0; + uint baseMask = item.BasePermissions; + uint ownerMask = item.CurrentPermissions; + + invString.AddItemStart(); + invString.AddNameValueLine("item_id", item.ItemID.ToString()); + invString.AddNameValueLine("parent_id", m_part.UUID.ToString()); + + invString.AddPermissionsStart(); + + invString.AddNameValueLine("base_mask", Utils.UIntToHexString(baseMask)); + invString.AddNameValueLine("owner_mask", Utils.UIntToHexString(ownerMask)); + invString.AddNameValueLine("group_mask", Utils.UIntToHexString(0)); + invString.AddNameValueLine("everyone_mask", Utils.UIntToHexString(everyoneMask)); + invString.AddNameValueLine("next_owner_mask", Utils.UIntToHexString(item.NextPermissions)); + + invString.AddNameValueLine("creator_id", item.CreatorID.ToString()); + invString.AddNameValueLine("owner_id", ownerID.ToString()); + + invString.AddNameValueLine("last_owner_id", item.LastOwnerID.ToString()); + + invString.AddNameValueLine("group_id", item.GroupID.ToString()); + invString.AddSectionEnd(); + + invString.AddNameValueLine("asset_id", item.AssetID.ToString()); + invString.AddNameValueLine("type", TaskInventoryItem.Types[item.Type]); + invString.AddNameValueLine("inv_type", TaskInventoryItem.InvTypes[item.InvType]); + invString.AddNameValueLine("flags", Utils.UIntToHexString(item.Flags)); + + invString.AddSaleStart(); + invString.AddNameValueLine("sale_type", "not"); + invString.AddNameValueLine("sale_price", "0"); + invString.AddSectionEnd(); + + invString.AddNameValueLine("name", item.Name + "|"); + invString.AddNameValueLine("desc", item.Description + "|"); + + invString.AddNameValueLine("creation_date", item.CreationDate.ToString()); + invString.AddSectionEnd(); + } + } + + fileData = Utils.StringToBytes(invString.BuildString); + + //Console.WriteLine(Utils.BytesToString(fileData)); + //m_log.Debug("[PRIM INVENTORY]: RequestInventoryFile fileData: " + Utils.BytesToString(fileData)); + + if (fileData.Length > 2) + { + xferManager.AddNewFile(m_inventoryFileName, fileData); + } + } + + /// + /// Process inventory backup + /// + /// + public void ProcessInventoryBackup(IRegionDataStore datastore) + { + if (HasInventoryChanged) + { + lock (Items) + { + datastore.StorePrimInventory(m_part.UUID, Items.Values); + } + + HasInventoryChanged = false; + } + } + + public class InventoryStringBuilder + { + public string BuildString = String.Empty; + + public InventoryStringBuilder(UUID folderID, UUID parentID) + { + BuildString += "\tinv_object\t0\n\t{\n"; + AddNameValueLine("obj_id", folderID.ToString()); + AddNameValueLine("parent_id", parentID.ToString()); + AddNameValueLine("type", "category"); + AddNameValueLine("name", "Contents|"); + AddSectionEnd(); + } + + public void AddItemStart() + { + BuildString += "\tinv_item\t0\n"; + AddSectionStart(); + } + + public void AddPermissionsStart() + { + BuildString += "\tpermissions 0\n"; + AddSectionStart(); + } + + public void AddSaleStart() + { + BuildString += "\tsale_info\t0\n"; + AddSectionStart(); + } + + protected void AddSectionStart() + { + BuildString += "\t{\n"; + } + + public void AddSectionEnd() + { + BuildString += "\t}\n"; + } + + public void AddLine(string addLine) + { + BuildString += addLine; + } + + public void AddNameValueLine(string name, string value) + { + BuildString += "\t\t"; + BuildString += name + "\t"; + BuildString += value + "\n"; + } + + public void Close() + { + } + } + + public uint MaskEffectivePermissions() + { + uint mask=0x7fffffff; + + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.InvType != 6) + { + if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Copy) == 0) + mask &= ~((uint)PermissionMask.Copy >> 13); + if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Transfer) == 0) + mask &= ~((uint)PermissionMask.Transfer >> 13); + if ((item.CurrentPermissions & item.NextPermissions & (uint)PermissionMask.Modify) == 0) + mask &= ~((uint)PermissionMask.Modify >> 13); + } + else + { + if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) + mask &= ~((uint)PermissionMask.Copy >> 13); + if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) + mask &= ~((uint)PermissionMask.Transfer >> 13); + if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) + mask &= ~((uint)PermissionMask.Modify >> 13); + } + + if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) + mask &= ~(uint)PermissionMask.Copy; + if ((item.CurrentPermissions & (uint)PermissionMask.Transfer) == 0) + mask &= ~(uint)PermissionMask.Transfer; + if ((item.CurrentPermissions & (uint)PermissionMask.Modify) == 0) + mask &= ~(uint)PermissionMask.Modify; + } + return mask; + } + + public void ApplyNextOwnerPermissions() + { + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.InvType == 6 && (item.CurrentPermissions & 7) != 0) + { + if ((item.CurrentPermissions & ((uint)PermissionMask.Copy >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Copy; + if ((item.CurrentPermissions & ((uint)PermissionMask.Transfer >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; + if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) + item.CurrentPermissions &= ~(uint)PermissionMask.Modify; + } + item.CurrentPermissions &= item.NextPermissions; + item.BasePermissions &= item.NextPermissions; + item.EveryonePermissions &= item.NextPermissions; + } + + m_part.TriggerScriptChangedEvent(Changed.OWNER); + } + + public void ApplyGodPermissions(uint perms) + { + foreach (TaskInventoryItem item in m_items.Values) + { + item.CurrentPermissions = perms; + item.BasePermissions = perms; + } + } + + public bool ContainsScripts() + { + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.InvType == 10) + { + return true; + } + } + return false; + } + + public List GetInventoryList() + { + List ret = new List(); + + foreach (TaskInventoryItem item in m_items.Values) + ret.Add(item.ItemID); + + return ret; + } + + public string[] GetScriptAssemblies() + { + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + + List ret = new List(); + + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.InvType == 10) + { + foreach (IScriptModule e in engines) + { + string n = e.GetAssemblyName(item.ItemID); + if (n != "") + { + if (!ret.Contains(n)) + ret.Add(n); + break; + } + } + } + } + return ret.ToArray(); + } + + public Dictionary GetScriptStates() + { + IScriptModule[] engines = m_part.ParentGroup.Scene.RequestModuleInterfaces(); + Dictionary ret = new Dictionary(); + + foreach (TaskInventoryItem item in m_items.Values) + { + if (item.InvType == 10) + { + foreach (IScriptModule e in engines) + { + string n = e.GetXMLState(item.ItemID); + if (n != "") + { + if (!ret.ContainsKey(item.ItemID)) + ret[item.ItemID] = n; + break; + } + } + } + } + return ret; + } + } +} diff --git a/OpenSim/Region/Environment/Scenes/ScenePresence.cs b/OpenSim/Region/Environment/Scenes/ScenePresence.cs index 61fa83d..b293f9e 100644 --- a/OpenSim/Region/Environment/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Environment/Scenes/ScenePresence.cs @@ -2558,7 +2558,7 @@ namespace OpenSim.Region.Environment.Scenes { if (gobj != null) { - if (gobj.RootPart.ContainsScripts()) + if (gobj.RootPart.Inventory.ContainsScripts()) return true; } } -- cgit v1.1