aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region/Framework
diff options
context:
space:
mode:
Diffstat (limited to 'OpenSim/Region/Framework')
-rw-r--r--OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs264
-rw-r--r--OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs175
-rw-r--r--OpenSim/Region/Framework/Scenes/Hypergrid/HGUuidGatherer.cs56
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs519
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs40
6 files changed, 40 insertions, 1019 deletions
diff --git a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
index 9a7863b..c08b961 100644
--- a/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
+++ b/OpenSim/Region/Framework/Scenes/AsyncSceneObjectGroupDeleter.cs
@@ -32,6 +32,7 @@ using System.Timers;
32using log4net; 32using log4net;
33using OpenMetaverse; 33using OpenMetaverse;
34using OpenSim.Framework; 34using OpenSim.Framework;
35using OpenSim.Region.Framework.Interfaces;
35 36
36namespace OpenSim.Region.Framework.Scenes 37namespace OpenSim.Region.Framework.Scenes
37{ 38{
@@ -137,7 +138,9 @@ namespace OpenSim.Region.Framework.Scenes
137 138
138 try 139 try
139 { 140 {
140 m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); 141 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
142 if (invAccess != null)
143 invAccess.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient);
141 if (x.permissionToDelete) 144 if (x.permissionToDelete)
142 m_scene.DeleteSceneObject(x.objectGroup, false); 145 m_scene.DeleteSceneObject(x.objectGroup, false);
143 } 146 }
diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs
deleted file mode 100644
index fdda150..0000000
--- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGAssetMapper.cs
+++ /dev/null
@@ -1,264 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using System.Threading;
32using log4net;
33using OpenMetaverse;
34using OpenSim.Framework;
35
36using OpenSim.Region.Framework.Scenes.Serialization;
37using OpenSim.Region.Framework.Interfaces;
38using OpenSim.Services.Interfaces;
39
40//using HyperGrid.Framework;
41//using OpenSim.Region.Communications.Hypergrid;
42
43namespace OpenSim.Region.Framework.Scenes.Hypergrid
44{
45 public class HGAssetMapper
46 {
47 #region Fields
48 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
49
50 // This maps between inventory server urls and inventory server clients
51// private Dictionary<string, InventoryClient> m_inventoryServers = new Dictionary<string, InventoryClient>();
52
53 private Scene m_scene;
54
55 private IHyperAssetService m_hyper;
56 IHyperAssetService HyperlinkAssets
57 {
58 get
59 {
60 if (m_hyper == null)
61 m_hyper = m_scene.RequestModuleInterface<IHyperAssetService>();
62 return m_hyper;
63 }
64 }
65
66 #endregion
67
68 #region Constructor
69
70 public HGAssetMapper(Scene scene)
71 {
72 m_scene = scene;
73 }
74
75 #endregion
76
77 #region Internal functions
78
79// private string UserAssetURL(UUID userID)
80// {
81// CachedUserInfo uinfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
82// if (uinfo != null)
83// return (uinfo.UserProfile.UserAssetURI == "") ? null : uinfo.UserProfile.UserAssetURI;
84// return null;
85// }
86
87// private string UserInventoryURL(UUID userID)
88// {
89// CachedUserInfo uinfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(userID);
90// if (uinfo != null)
91// return (uinfo.UserProfile.UserInventoryURI == "") ? null : uinfo.UserProfile.UserInventoryURI;
92// return null;
93// }
94
95
96 public AssetBase FetchAsset(string url, UUID assetID)
97 {
98 AssetBase asset = m_scene.AssetService.Get(url + "/" + assetID.ToString());
99
100 if (asset != null)
101 {
102 m_log.DebugFormat("[HGScene]: Copied asset {0} from {1} to local asset server. ", asset.ID, url);
103 return asset;
104 }
105 return null;
106 }
107
108 public bool PostAsset(string url, AssetBase asset)
109 {
110 if (asset != null)
111 {
112 // See long comment in AssetCache.AddAsset
113 if (!asset.Temporary || asset.Local)
114 {
115 // We need to copy the asset into a new asset, because
116 // we need to set its ID to be URL+UUID, so that the
117 // HGAssetService dispatches it to the remote grid.
118 // It's not pretty, but the best that can be done while
119 // not having a global naming infrastructure
120 AssetBase asset1 = new AssetBase(asset.FullID, asset.Name, asset.Type);
121 Copy(asset, asset1);
122 try
123 {
124 asset1.ID = url + "/" + asset.ID;
125 }
126 catch
127 {
128 m_log.Warn("[HGScene]: Oops.");
129 }
130
131 m_scene.AssetService.Store(asset1);
132 m_log.DebugFormat("[HGScene]: Posted copy of asset {0} from local asset server to {1}", asset1.ID, url);
133 }
134 return true;
135 }
136 else
137 m_log.Warn("[HGScene]: Tried to post asset to remote server, but asset not in local cache.");
138
139 return false;
140 }
141
142 private void Copy(AssetBase from, AssetBase to)
143 {
144 to.Data = from.Data;
145 to.Description = from.Description;
146 to.FullID = from.FullID;
147 to.ID = from.ID;
148 to.Local = from.Local;
149 to.Name = from.Name;
150 to.Temporary = from.Temporary;
151 to.Type = from.Type;
152
153 }
154
155 // TODO: unused
156 // private void Dump(Dictionary<UUID, bool> lst)
157 // {
158 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
159 // foreach (KeyValuePair<UUID, bool> kvp in lst)
160 // m_log.Debug(" >> " + kvp.Key + " (texture? " + kvp.Value + ")");
161 // m_log.Debug("XXX -------- UUID DUMP ------- XXX");
162 // }
163
164 #endregion
165
166
167 #region Public interface
168
169 public void Get(UUID assetID, UUID ownerID)
170 {
171 // Get the item from the remote asset server onto the local AssetCache
172 // and place an entry in m_assetMap
173
174 string userAssetURL = HyperlinkAssets.GetUserAssetServer(ownerID);
175 if ((userAssetURL != string.Empty) && (userAssetURL != HyperlinkAssets.GetSimAssetServer()))
176 {
177 m_log.Debug("[HGScene]: Fetching object " + assetID + " from asset server " + userAssetURL);
178 AssetBase asset = FetchAsset(userAssetURL, assetID);
179
180 if (asset != null)
181 {
182 // OK, now fetch the inside.
183 Dictionary<UUID, int> ids = new Dictionary<UUID, int>();
184 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL);
185 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
186 foreach (UUID uuid in ids.Keys)
187 FetchAsset(userAssetURL, uuid);
188
189 m_log.DebugFormat("[HGScene]: Successfully fetched asset {0} from asset server {1}", asset.ID, userAssetURL);
190
191 }
192 else
193 m_log.Warn("[HGScene]: Could not fetch asset from remote asset server " + userAssetURL);
194 }
195 else
196 m_log.Debug("[HGScene]: user's asset server is the local region's asset server");
197 }
198
199 //public InventoryItemBase Get(InventoryItemBase item, UUID rootFolder, CachedUserInfo userInfo)
200 //{
201 // InventoryClient invCli = null;
202 // string inventoryURL = UserInventoryURL(item.Owner);
203 // if (!m_inventoryServers.TryGetValue(inventoryURL, out invCli))
204 // {
205 // m_log.Debug("[HGScene]: Starting new InventorytClient for " + inventoryURL);
206 // invCli = new InventoryClient(inventoryURL);
207 // m_inventoryServers.Add(inventoryURL, invCli);
208 // }
209
210 // item = invCli.GetInventoryItem(item);
211 // if (item != null)
212 // {
213 // // Change the folder, stick it in root folder, all items flattened out here in this region cache
214 // item.Folder = rootFolder;
215 // //userInfo.AddItem(item); don't use this, it calls back to the inventory server
216 // lock (userInfo.RootFolder.Items)
217 // {
218 // userInfo.RootFolder.Items[item.ID] = item;
219 // }
220
221 // }
222 // return item;
223 //}
224
225 public void Post(UUID assetID, UUID ownerID)
226 {
227 // Post the item from the local AssetCache onto the remote asset server
228 // and place an entry in m_assetMap
229
230 string userAssetURL = HyperlinkAssets.GetUserAssetServer(ownerID);
231 if ((userAssetURL != string.Empty) && (userAssetURL != HyperlinkAssets.GetSimAssetServer()))
232 {
233 m_log.Debug("[HGScene]: Posting object " + assetID + " to asset server " + userAssetURL);
234 AssetBase asset = m_scene.AssetService.Get(assetID.ToString());
235 if (asset != null)
236 {
237 Dictionary<UUID, int> ids = new Dictionary<UUID, int>();
238 HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, string.Empty);
239 uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids);
240 foreach (UUID uuid in ids.Keys)
241 {
242 asset = m_scene.AssetService.Get(uuid.ToString());
243 if (asset == null)
244 m_log.DebugFormat("[HGScene]: Could not find asset {0}", uuid);
245 else
246 PostAsset(userAssetURL, asset);
247 }
248
249 // maybe all pieces got there...
250 m_log.DebugFormat("[HGScene]: Successfully posted item {0} to asset server {1}", assetID, userAssetURL);
251
252 }
253 else
254 m_log.DebugFormat("[HGScene]: Something wrong with asset {0}, it could not be found", assetID);
255 }
256 else
257 m_log.Debug("[HGScene]: user's asset server is local region's asset server");
258
259 }
260
261 #endregion
262
263 }
264}
diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs
deleted file mode 100644
index c5f8921..0000000
--- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGScene.Inventory.cs
+++ /dev/null
@@ -1,175 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System.Reflection;
29using log4net;
30using Nini.Config;
31using OpenMetaverse;
32using OpenSim.Framework;
33using OpenSim.Framework.Communications;
34
35using OpenSim.Region.Framework.Interfaces;
36using OpenSim.Services.Interfaces;
37
38namespace OpenSim.Region.Framework.Scenes.Hypergrid
39{
40 public partial class HGScene : Scene
41 {
42 #region Fields
43 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
44
45 private HGAssetMapper m_assMapper;
46 public HGAssetMapper AssetMapper
47 {
48 get { return m_assMapper; }
49 }
50
51 private IHyperAssetService m_hyper;
52 private IHyperAssetService HyperAssets
53 {
54 get
55 {
56 if (m_hyper == null)
57 m_hyper = RequestModuleInterface<IHyperAssetService>();
58 return m_hyper;
59 }
60 }
61
62 #endregion
63
64 #region Constructors
65
66 public HGScene(RegionInfo regInfo, AgentCircuitManager authen,
67 SceneCommunicationService sceneGridService,
68 StorageManager storeManager,
69 ModuleLoader moduleLoader, bool dumpAssetsToFile, bool physicalPrim,
70 bool SeeIntoRegionFromNeighbor, IConfigSource config, string simulatorVersion)
71 : base(regInfo, authen, sceneGridService, storeManager, moduleLoader,
72 dumpAssetsToFile, physicalPrim, SeeIntoRegionFromNeighbor, config, simulatorVersion)
73 {
74 m_log.Info("[HGScene]: Starting HGScene.");
75 m_assMapper = new HGAssetMapper(this);
76
77 EventManager.OnNewInventoryItemUploadComplete += UploadInventoryItem;
78 }
79
80 #endregion
81
82 #region Event handlers
83
84 public void UploadInventoryItem(UUID avatarID, UUID assetID, string name, int userlevel)
85 {
86 UserAccount userInfo = UserAccountService.GetUserAccount(RegionInfo.ScopeID, avatarID);
87 if (userInfo != null)
88 {
89 m_assMapper.Post(assetID, avatarID);
90 }
91 }
92
93 #endregion
94
95 #region Overrides of Scene.Inventory methods
96
97 ///
98 /// CapsUpdateInventoryItemAsset
99 ///
100 public override UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
101 {
102 UUID newAssetID = base.CapsUpdateInventoryItemAsset(remoteClient, itemID, data);
103
104 UploadInventoryItem(remoteClient.AgentId, newAssetID, "", 0);
105
106 return newAssetID;
107 }
108
109 ///
110 /// DeleteToInventory
111 ///
112 public override UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient)
113 {
114 UUID assetID = base.DeleteToInventory(action, folderID, objectGroup, remoteClient);
115
116 if (!assetID.Equals(UUID.Zero))
117 {
118 UploadInventoryItem(remoteClient.AgentId, assetID, "", 0);
119 }
120 else
121 m_log.Debug("[HGScene]: Scene.Inventory did not create asset");
122
123 return assetID;
124 }
125
126 ///
127 /// RezObject
128 ///
129 public override SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
130 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
131 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
132 {
133 m_log.DebugFormat("[HGScene] RezObject itemID={0} fromTaskID={1}", itemID, fromTaskID);
134
135 //if (fromTaskID.Equals(UUID.Zero))
136 //{
137 InventoryItemBase item = new InventoryItemBase(itemID);
138 item.Owner = remoteClient.AgentId;
139 item = InventoryService.GetItem(item);
140 //if (item == null)
141 //{ // Fetch the item
142 // item = new InventoryItemBase();
143 // item.Owner = remoteClient.AgentId;
144 // item.ID = itemID;
145 // item = m_assMapper.Get(item, userInfo.RootFolder.ID, userInfo);
146 //}
147 if (item != null)
148 {
149 m_assMapper.Get(item.AssetID, remoteClient.AgentId);
150
151 }
152 //}
153
154 // OK, we're done fetching. Pass it up to the default RezObject
155 return base.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
156 RezSelected, RemoveItem, fromTaskID, attachment);
157
158 }
159
160 protected override void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
161 {
162 string userAssetServer = HyperAssets.GetUserAssetServer(sender);
163 if ((userAssetServer != string.Empty) && (userAssetServer != HyperAssets.GetSimAssetServer()))
164 m_assMapper.Get(item.AssetID, sender);
165
166 userAssetServer = HyperAssets.GetUserAssetServer(receiver);
167 if ((userAssetServer != string.Empty) && (userAssetServer != HyperAssets.GetSimAssetServer()))
168 m_assMapper.Post(item.AssetID, receiver);
169 }
170
171 #endregion
172
173 }
174
175}
diff --git a/OpenSim/Region/Framework/Scenes/Hypergrid/HGUuidGatherer.cs b/OpenSim/Region/Framework/Scenes/Hypergrid/HGUuidGatherer.cs
deleted file mode 100644
index 5d4e7ac..0000000
--- a/OpenSim/Region/Framework/Scenes/Hypergrid/HGUuidGatherer.cs
+++ /dev/null
@@ -1,56 +0,0 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30
31using OpenSim.Framework;
32using OpenSim.Services.Interfaces;
33using OpenMetaverse;
34
35namespace OpenSim.Region.Framework.Scenes.Hypergrid
36{
37 public class HGUuidGatherer : UuidGatherer
38 {
39 protected string m_assetServerURL;
40 protected HGAssetMapper m_assetMapper;
41
42 public HGUuidGatherer(HGAssetMapper assMap, IAssetService assetCache, string assetServerURL) : base(assetCache)
43 {
44 m_assetMapper = assMap;
45 m_assetServerURL = assetServerURL;
46 }
47
48 protected override AssetBase GetAsset(UUID uuid)
49 {
50 if (string.Empty == m_assetServerURL)
51 return m_assetCache.Get(uuid.ToString());
52 else
53 return m_assetMapper.FetchAsset(m_assetServerURL, uuid);
54 }
55 }
56}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 62a831e..45806dd 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -126,61 +126,6 @@ namespace OpenSim.Region.Framework.Scenes
126 } 126 }
127 127
128 /// <summary> 128 /// <summary>
129 /// Capability originating call to update the asset of an item in an agent's inventory
130 /// </summary>
131 /// <param name="remoteClient"></param>
132 /// <param name="itemID"></param>
133 /// <param name="data"></param>
134 /// <returns></returns>
135 public virtual UUID CapsUpdateInventoryItemAsset(IClientAPI remoteClient, UUID itemID, byte[] data)
136 {
137 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
138 item = InventoryService.GetItem(item);
139
140 if (item != null)
141 {
142 if ((InventoryType)item.InvType == InventoryType.Notecard)
143 {
144 if (!Permissions.CanEditNotecard(itemID, UUID.Zero, remoteClient.AgentId))
145 {
146 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit notecard", false);
147 return UUID.Zero;
148 }
149
150 remoteClient.SendAgentAlertMessage("Notecard saved", false);
151 }
152 else if ((InventoryType)item.InvType == InventoryType.LSL)
153 {
154 if (!Permissions.CanEditScript(itemID, UUID.Zero, remoteClient.AgentId))
155 {
156 remoteClient.SendAgentAlertMessage("Insufficient permissions to edit script", false);
157 return UUID.Zero;
158 }
159
160 remoteClient.SendAgentAlertMessage("Script saved", false);
161 }
162
163 AssetBase asset =
164 CreateAsset(item.Name, item.Description, (sbyte)item.AssetType, data);
165 item.AssetID = asset.FullID;
166 AssetService.Store(asset);
167
168 InventoryService.UpdateItem(item);
169
170 // remoteClient.SendInventoryItemCreateUpdate(item);
171 return (asset.FullID);
172 }
173 else
174 {
175 m_log.ErrorFormat(
176 "[AGENT INVENTORY]: Could not find item {0} for caps inventory update",
177 itemID);
178 }
179
180 return UUID.Zero;
181 }
182
183 /// <summary>
184 /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see> 129 /// <see>CapsUpdatedInventoryItemAsset(IClientAPI, UUID, byte[])</see>
185 /// </summary> 130 /// </summary>
186 public UUID CapsUpdateInventoryItemAsset(UUID avatarId, UUID itemID, byte[] data) 131 public UUID CapsUpdateInventoryItemAsset(UUID avatarId, UUID itemID, byte[] data)
@@ -189,7 +134,9 @@ namespace OpenSim.Region.Framework.Scenes
189 134
190 if (TryGetAvatar(avatarId, out avatar)) 135 if (TryGetAvatar(avatarId, out avatar))
191 { 136 {
192 return CapsUpdateInventoryItemAsset(avatar.ControllingClient, itemID, data); 137 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
138 if (invAccess != null)
139 return invAccess.CapsUpdateInventoryItemAsset(avatar.ControllingClient, itemID, data);
193 } 140 }
194 else 141 else
195 { 142 {
@@ -472,7 +419,11 @@ namespace OpenSim.Region.Framework.Scenes
472 itemCopy.SaleType = item.SaleType; 419 itemCopy.SaleType = item.SaleType;
473 420
474 if (InventoryService.AddItem(itemCopy)) 421 if (InventoryService.AddItem(itemCopy))
475 TransferInventoryAssets(itemCopy, senderId, recipient); 422 {
423 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
424 if (invAccess != null)
425 invAccess.TransferInventoryAssets(itemCopy, senderId, recipient);
426 }
476 427
477 if (!Permissions.BypassPermissions()) 428 if (!Permissions.BypassPermissions())
478 { 429 {
@@ -494,10 +445,6 @@ namespace OpenSim.Region.Framework.Scenes
494 445
495 } 446 }
496 447
497 protected virtual void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver)
498 {
499 }
500
501 /// <summary> 448 /// <summary>
502 /// Give an entire inventory folder from one user to another. The entire contents (including all descendent 449 /// Give an entire inventory folder from one user to another. The entire contents (including all descendent
503 /// folders) is given. 450 /// folders) is given.
@@ -1605,232 +1552,6 @@ namespace OpenSim.Region.Framework.Scenes
1605 } 1552 }
1606 } 1553 }
1607 1554
1608 /// <summary>
1609 /// Delete a scene object from a scene and place in the given avatar's inventory.
1610 /// Returns the UUID of the newly created asset.
1611 /// </summary>
1612 /// <param name="action"></param>
1613 /// <param name="folderID"></param>
1614 /// <param name="objectGroup"></param>
1615 /// <param name="remoteClient"> </param>
1616 public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID,
1617 SceneObjectGroup objectGroup, IClientAPI remoteClient)
1618 {
1619 UUID assetID = UUID.Zero;
1620
1621 Vector3 inventoryStoredPosition = new Vector3
1622 (((objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
1623 ? 250
1624 : objectGroup.AbsolutePosition.X)
1625 ,
1626 (objectGroup.AbsolutePosition.X > (int)Constants.RegionSize)
1627 ? 250
1628 : objectGroup.AbsolutePosition.X,
1629 objectGroup.AbsolutePosition.Z);
1630
1631 Vector3 originalPosition = objectGroup.AbsolutePosition;
1632
1633 objectGroup.AbsolutePosition = inventoryStoredPosition;
1634
1635 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(objectGroup);
1636
1637 objectGroup.AbsolutePosition = originalPosition;
1638
1639 // Get the user info of the item destination
1640 //
1641 UUID userID = UUID.Zero;
1642
1643 if (action == DeRezAction.Take || action == DeRezAction.TakeCopy ||
1644 action == DeRezAction.SaveToExistingUserInventoryItem)
1645 {
1646 // Take or take copy require a taker
1647 // Saving changes requires a local user
1648 //
1649 if (remoteClient == null)
1650 return UUID.Zero;
1651
1652 userID = remoteClient.AgentId;
1653 }
1654 else
1655 {
1656 // All returns / deletes go to the object owner
1657 //
1658
1659 userID = objectGroup.RootPart.OwnerID;
1660 }
1661
1662 if (userID == UUID.Zero) // Can't proceed
1663 {
1664 return UUID.Zero;
1665 }
1666
1667 // If we're returning someone's item, it goes back to the
1668 // owner's Lost And Found folder.
1669 // Delete is treated like return in this case
1670 // Deleting your own items makes them go to trash
1671 //
1672
1673 InventoryFolderBase folder = null;
1674 InventoryItemBase item = null;
1675
1676 if (DeRezAction.SaveToExistingUserInventoryItem == action)
1677 {
1678 item = new InventoryItemBase(objectGroup.RootPart.FromUserInventoryItemID, userID);
1679 item = InventoryService.GetItem(item);
1680
1681 //item = userInfo.RootFolder.FindItem(
1682 // objectGroup.RootPart.FromUserInventoryItemID);
1683
1684 if (null == item)
1685 {
1686 m_log.DebugFormat(
1687 "[AGENT INVENTORY]: Object {0} {1} scheduled for save to inventory has already been deleted.",
1688 objectGroup.Name, objectGroup.UUID);
1689 return UUID.Zero;
1690 }
1691 }
1692 else
1693 {
1694 // Folder magic
1695 //
1696 if (action == DeRezAction.Delete)
1697 {
1698 // Deleting someone else's item
1699 //
1700
1701
1702 if (remoteClient == null ||
1703 objectGroup.OwnerID != remoteClient.AgentId)
1704 {
1705 // Folder skeleton may not be loaded and we
1706 // have to wait for the inventory to find
1707 // the destination folder
1708 //
1709 folder = InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
1710 }
1711 else
1712 {
1713 // Assume inventory skeleton was loaded during login
1714 // and all folders can be found
1715 //
1716 folder = InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
1717 }
1718 }
1719 else if (action == DeRezAction.Return)
1720 {
1721
1722 // Dump to lost + found unconditionally
1723 //
1724 folder = InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
1725 }
1726
1727 if (folderID == UUID.Zero && folder == null)
1728 {
1729 if (action == DeRezAction.Delete)
1730 {
1731 // Deletes go to trash by default
1732 //
1733 folder = InventoryService.GetFolderForType(userID, AssetType.TrashFolder);
1734 }
1735 else
1736 {
1737 // Catch all. Use lost & found
1738 //
1739
1740 folder = InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder);
1741 }
1742 }
1743
1744 if (folder == null) // None of the above
1745 {
1746 //folder = userInfo.RootFolder.FindFolder(folderID);
1747 folder = new InventoryFolderBase(folderID);
1748
1749 if (folder == null) // Nowhere to put it
1750 {
1751 return UUID.Zero;
1752 }
1753 }
1754
1755 item = new InventoryItemBase();
1756 item.CreatorId = objectGroup.RootPart.CreatorID.ToString();
1757 item.ID = UUID.Random();
1758 item.InvType = (int)InventoryType.Object;
1759 item.Folder = folder.ID;
1760 item.Owner = userID;
1761 }
1762
1763 AssetBase asset = CreateAsset(
1764 objectGroup.GetPartName(objectGroup.RootPart.LocalId),
1765 objectGroup.GetPartDescription(objectGroup.RootPart.LocalId),
1766 (sbyte)AssetType.Object,
1767 Utils.StringToBytes(sceneObjectXml));
1768 AssetService.Store(asset);
1769 assetID = asset.FullID;
1770
1771 if (DeRezAction.SaveToExistingUserInventoryItem == action)
1772 {
1773 item.AssetID = asset.FullID;
1774 InventoryService.UpdateItem(item);
1775 }
1776 else
1777 {
1778 item.AssetID = asset.FullID;
1779
1780 if (remoteClient != null && (remoteClient.AgentId != objectGroup.RootPart.OwnerID) && Permissions.PropagatePermissions())
1781 {
1782 uint perms=objectGroup.GetEffectivePermissions();
1783 uint nextPerms=(perms & 7) << 13;
1784 if ((nextPerms & (uint)PermissionMask.Copy) == 0)
1785 perms &= ~(uint)PermissionMask.Copy;
1786 if ((nextPerms & (uint)PermissionMask.Transfer) == 0)
1787 perms &= ~(uint)PermissionMask.Transfer;
1788 if ((nextPerms & (uint)PermissionMask.Modify) == 0)
1789 perms &= ~(uint)PermissionMask.Modify;
1790
1791 item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask;
1792 item.CurrentPermissions = item.BasePermissions;
1793 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
1794 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask;
1795 item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask;
1796 item.CurrentPermissions |= 8; // Slam!
1797 }
1798 else
1799 {
1800 item.BasePermissions = objectGroup.GetEffectivePermissions();
1801 item.CurrentPermissions = objectGroup.GetEffectivePermissions();
1802 item.NextPermissions = objectGroup.RootPart.NextOwnerMask;
1803 item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask;
1804 item.GroupPermissions = objectGroup.RootPart.GroupMask;
1805
1806 item.CurrentPermissions |= 8; // Slam!
1807 }
1808
1809 // TODO: add the new fields (Flags, Sale info, etc)
1810 item.CreationDate = Util.UnixTimeSinceEpoch();
1811 item.Description = asset.Description;
1812 item.Name = asset.Name;
1813 item.AssetType = asset.Type;
1814
1815 InventoryService.AddItem(item);
1816
1817 if (remoteClient != null && item.Owner == remoteClient.AgentId)
1818 {
1819 remoteClient.SendInventoryItemCreateUpdate(item, 0);
1820 }
1821 else
1822 {
1823 ScenePresence notifyUser = GetScenePresence(item.Owner);
1824 if (notifyUser != null)
1825 {
1826 notifyUser.ControllingClient.SendInventoryItemCreateUpdate(item, 0);
1827 }
1828 }
1829 }
1830
1831 return assetID;
1832 }
1833
1834 public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) 1555 public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID)
1835 { 1556 {
1836 SceneObjectGroup objectGroup = grp; 1557 SceneObjectGroup objectGroup = grp;
@@ -1971,225 +1692,11 @@ namespace OpenSim.Region.Framework.Scenes
1971 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, 1692 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
1972 bool RezSelected, bool RemoveItem, UUID fromTaskID) 1693 bool RezSelected, bool RemoveItem, UUID fromTaskID)
1973 { 1694 {
1974 RezObject( 1695 IInventoryAccessModule invAccess = RequestModuleInterface<IInventoryAccessModule>();
1975 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection, 1696 if (invAccess != null)
1976 RezSelected, RemoveItem, fromTaskID, false); 1697 invAccess.RezObject(
1977 } 1698 remoteClient, itemID, RayEnd, RayStart, RayTargetID, BypassRayCast, RayEndIsIntersection,
1978 1699 RezSelected, RemoveItem, fromTaskID, false);
1979 /// <summary>
1980 /// Rez an object into the scene from the user's inventory
1981 /// </summary>
1982 /// <param name="remoteClient"></param>
1983 /// <param name="itemID"></param>
1984 /// <param name="RayEnd"></param>
1985 /// <param name="RayStart"></param>
1986 /// <param name="RayTargetID"></param>
1987 /// <param name="BypassRayCast"></param>
1988 /// <param name="RayEndIsIntersection"></param>
1989 /// <param name="RezSelected"></param>
1990 /// <param name="RemoveItem"></param>
1991 /// <param name="fromTaskID"></param>
1992 /// <param name="attachment"></param>
1993 /// <returns>The SceneObjectGroup rezzed or null if rez was unsuccessful.</returns>
1994 public virtual SceneObjectGroup RezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart,
1995 UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection,
1996 bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment)
1997 {
1998 // Work out position details
1999 byte bRayEndIsIntersection = (byte)0;
2000
2001 if (RayEndIsIntersection)
2002 {
2003 bRayEndIsIntersection = (byte)1;
2004 }
2005 else
2006 {
2007 bRayEndIsIntersection = (byte)0;
2008 }
2009
2010 Vector3 scale = new Vector3(0.5f, 0.5f, 0.5f);
2011
2012
2013 Vector3 pos = GetNewRezLocation(
2014 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2015 BypassRayCast, bRayEndIsIntersection,true,scale, false);
2016
2017 // Rez object
2018 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
2019 item = InventoryService.GetItem(item);
2020
2021 if (item != null)
2022 {
2023 AssetBase rezAsset = AssetService.Get(item.AssetID.ToString());
2024
2025 if (rezAsset != null)
2026 {
2027 UUID itemId = UUID.Zero;
2028
2029 // If we have permission to copy then link the rezzed object back to the user inventory
2030 // item that it came from. This allows us to enable 'save object to inventory'
2031 if (!Permissions.BypassPermissions())
2032 {
2033 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == (uint)PermissionMask.Copy)
2034 {
2035 itemId = item.ID;
2036 }
2037 }
2038 else
2039 {
2040 // Brave new fullperm world
2041 //
2042 itemId = item.ID;
2043 }
2044
2045 string xmlData = Utils.BytesToString(rezAsset.Data);
2046 SceneObjectGroup group
2047 = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData);
2048
2049 if (!Permissions.CanRezObject(
2050 group.Children.Count, remoteClient.AgentId, pos)
2051 && !attachment)
2052 {
2053 // The client operates in no fail mode. It will
2054 // have already removed the item from the folder
2055 // if it's no copy.
2056 // Put it back if it's not an attachment
2057 //
2058 if (((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0) && (!attachment))
2059 remoteClient.SendBulkUpdateInventory(item);
2060 return null;
2061 }
2062
2063 group.ResetIDs();
2064
2065 if (attachment)
2066 {
2067 group.RootPart.ObjectFlags |= (uint)PrimFlags.Phantom;
2068 group.RootPart.IsAttachment = true;
2069 }
2070
2071 AddNewSceneObject(group, true);
2072
2073 // m_log.InfoFormat("ray end point for inventory rezz is {0} {1} {2} ", RayEnd.X, RayEnd.Y, RayEnd.Z);
2074 // if attachment we set it's asset id so object updates can reflect that
2075 // if not, we set it's position in world.
2076 if (!attachment)
2077 {
2078 float offsetHeight = 0;
2079 pos = GetNewRezLocation(
2080 RayStart, RayEnd, RayTargetID, Quaternion.Identity,
2081 BypassRayCast, bRayEndIsIntersection, true, group.GetAxisAlignedBoundingBox(out offsetHeight), false);
2082 pos.Z += offsetHeight;
2083 group.AbsolutePosition = pos;
2084 // m_log.InfoFormat("rezx point for inventory rezz is {0} {1} {2} and offsetheight was {3}", pos.X, pos.Y, pos.Z, offsetHeight);
2085
2086 }
2087 else
2088 {
2089 group.SetFromItemID(itemID);
2090 }
2091
2092 SceneObjectPart rootPart = null;
2093 try
2094 {
2095 rootPart = group.GetChildPart(group.UUID);
2096 }
2097 catch (NullReferenceException)
2098 {
2099 string isAttachment = "";
2100
2101 if (attachment)
2102 isAttachment = " Object was an attachment";
2103
2104 m_log.Error("[AGENT INVENTORY]: Error rezzing ItemID: " + itemID + " object has no rootpart." + isAttachment);
2105 }
2106
2107 // Since renaming the item in the inventory does not affect the name stored
2108 // in the serialization, transfer the correct name from the inventory to the
2109 // object itself before we rez.
2110 rootPart.Name = item.Name;
2111 rootPart.Description = item.Description;
2112
2113 List<SceneObjectPart> partList = new List<SceneObjectPart>(group.Children.Values);
2114
2115 group.SetGroup(remoteClient.ActiveGroupId, remoteClient);
2116 if (rootPart.OwnerID != item.Owner)
2117 {
2118 //Need to kill the for sale here
2119 rootPart.ObjectSaleType = 0;
2120 rootPart.SalePrice = 10;
2121
2122 if (Permissions.PropagatePermissions())
2123 {
2124 if ((item.CurrentPermissions & 8) != 0)
2125 {
2126 foreach (SceneObjectPart part in partList)
2127 {
2128 part.EveryoneMask = item.EveryOnePermissions;
2129 part.NextOwnerMask = item.NextPermissions;
2130 part.GroupMask = 0; // DO NOT propagate here
2131 }
2132 }
2133 group.ApplyNextOwnerPermissions();
2134 }
2135 }
2136
2137 foreach (SceneObjectPart part in partList)
2138 {
2139 if (part.OwnerID != item.Owner)
2140 {
2141 part.LastOwnerID = part.OwnerID;
2142 part.OwnerID = item.Owner;
2143 part.Inventory.ChangeInventoryOwner(item.Owner);
2144 }
2145 else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam!
2146 {
2147 part.EveryoneMask = item.EveryOnePermissions;
2148 part.NextOwnerMask = item.NextPermissions;
2149
2150 part.GroupMask = 0; // DO NOT propagate here
2151 }
2152 }
2153
2154 rootPart.TrimPermissions();
2155
2156 if (!attachment)
2157 {
2158 if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
2159 {
2160 group.ClearPartAttachmentData();
2161 }
2162 }
2163
2164 if (!attachment)
2165 {
2166 // Fire on_rez
2167 group.CreateScriptInstances(0, true, DefaultScriptEngine, 0);
2168
2169 rootPart.ScheduleFullUpdate();
2170 }
2171
2172 if (!Permissions.BypassPermissions())
2173 {
2174 if ((item.CurrentPermissions & (uint)PermissionMask.Copy) == 0)
2175 {
2176 // If this is done on attachments, no
2177 // copy ones will be lost, so avoid it
2178 //
2179 if (!attachment)
2180 {
2181 List<UUID> uuids = new List<UUID>();
2182 uuids.Add(item.ID);
2183 InventoryService.DeleteItems(item.Owner, uuids);
2184 }
2185 }
2186 }
2187
2188 return rootPart.ParentGroup;
2189 }
2190 }
2191
2192 return null;
2193 } 1700 }
2194 1701
2195 /// <summary> 1702 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index f74fd5d..fbd11c6 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -35,6 +35,7 @@ using log4net;
35using OpenSim.Framework; 35using OpenSim.Framework;
36using OpenSim.Region.Framework.Scenes.Types; 36using OpenSim.Region.Framework.Scenes.Types;
37using OpenSim.Region.Physics.Manager; 37using OpenSim.Region.Physics.Manager;
38using OpenSim.Region.Framework.Interfaces;
38 39
39namespace OpenSim.Region.Framework.Scenes 40namespace OpenSim.Region.Framework.Scenes
40{ 41{
@@ -498,27 +499,32 @@ namespace OpenSim.Region.Framework.Scenes
498 public SceneObjectGroup RezSingleAttachment( 499 public SceneObjectGroup RezSingleAttachment(
499 IClientAPI remoteClient, UUID itemID, uint AttachmentPt) 500 IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
500 { 501 {
501 SceneObjectGroup objatt = m_parentScene.RezObject(remoteClient, 502 IInventoryAccessModule invAccess = m_parentScene.RequestModuleInterface<IInventoryAccessModule>();
502 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, 503 if (invAccess != null)
503 false, false, remoteClient.AgentId, true);
504
505
506 if (objatt != null)
507 { 504 {
508 bool tainted = false; 505 SceneObjectGroup objatt = invAccess.RezObject(remoteClient,
509 if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) 506 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
510 tainted = true; 507 false, false, remoteClient.AgentId, true);
511 508
512 AttachObject(remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false);
513 objatt.ScheduleGroupForFullUpdate();
514 if (tainted)
515 objatt.HasGroupChanged = true;
516 509
517 // Fire after attach, so we don't get messy perms dialogs 510 if (objatt != null)
518 // 3 == AttachedRez 511 {
519 objatt.CreateScriptInstances(0, true, m_parentScene.DefaultScriptEngine, 3); 512 bool tainted = false;
513 if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint())
514 tainted = true;
515
516 AttachObject(remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false);
517 objatt.ScheduleGroupForFullUpdate();
518 if (tainted)
519 objatt.HasGroupChanged = true;
520
521 // Fire after attach, so we don't get messy perms dialogs
522 // 3 == AttachedRez
523 objatt.CreateScriptInstances(0, true, m_parentScene.DefaultScriptEngine, 3);
524 }
525 return objatt;
520 } 526 }
521 return objatt; 527 return null;
522 } 528 }
523 529
524 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. 530 // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.