diff options
Diffstat (limited to 'OpenSim/Region/CoreModules')
20 files changed, 789 insertions, 375 deletions
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index 9d8082b..eed7cd5 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs | |||
@@ -41,14 +41,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
41 | /// </summary> | 41 | /// </summary> |
42 | public class AgentAssetTransactions | 42 | public class AgentAssetTransactions |
43 | { | 43 | { |
44 | // private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | 45 | ||
46 | // Fields | 46 | // Fields |
47 | private bool m_dumpAssetsToFile; | 47 | private bool m_dumpAssetsToFile; |
48 | private Scene m_Scene; | 48 | private Scene m_Scene; |
49 | public UUID UserID; | 49 | private UUID UserID; |
50 | public Dictionary<UUID, AssetXferUploader> XferUploaders = | 50 | private Dictionary<UUID, AssetXferUploader> XferUploaders = new Dictionary<UUID, AssetXferUploader>(); |
51 | new Dictionary<UUID, AssetXferUploader>(); | ||
52 | 51 | ||
53 | // Methods | 52 | // Methods |
54 | public AgentAssetTransactions(UUID agentID, Scene scene, | 53 | public AgentAssetTransactions(UUID agentID, Scene scene, |
@@ -59,36 +58,94 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
59 | m_dumpAssetsToFile = dumpAssetsToFile; | 58 | m_dumpAssetsToFile = dumpAssetsToFile; |
60 | } | 59 | } |
61 | 60 | ||
62 | public AssetXferUploader RequestXferUploader(UUID transactionID) | 61 | /// <summary> |
62 | /// Return a xfer uploader if one does not already exist. | ||
63 | /// </summary> | ||
64 | /// <param name="transactionID"></param> | ||
65 | /// <param name="assetID"> | ||
66 | /// We must transfer the new asset ID into the uploader on creation, otherwise | ||
67 | /// we can see race conditions with other threads which can retrieve an item before it is updated with the new | ||
68 | /// asset id. | ||
69 | /// </param> | ||
70 | /// <returns> | ||
71 | /// The xfer uploader requested. Null if one is already in existence. | ||
72 | /// FIXME: This is a bizarre thing to do, and is probably meant to signal an error condition if multiple | ||
73 | /// transfers are made. Needs to be corrected. | ||
74 | /// </returns> | ||
75 | public AssetXferUploader RequestXferUploader(UUID transactionID, UUID assetID) | ||
63 | { | 76 | { |
64 | if (!XferUploaders.ContainsKey(transactionID)) | 77 | lock (XferUploaders) |
65 | { | 78 | { |
66 | AssetXferUploader uploader = new AssetXferUploader(m_Scene, | 79 | if (!XferUploaders.ContainsKey(transactionID)) |
67 | m_dumpAssetsToFile); | ||
68 | |||
69 | lock (XferUploaders) | ||
70 | { | 80 | { |
81 | AssetXferUploader uploader = new AssetXferUploader(this, m_Scene, assetID, m_dumpAssetsToFile); | ||
82 | |||
83 | // m_log.DebugFormat( | ||
84 | // "[AGENT ASSETS TRANSACTIONS]: Adding asset xfer uploader {0} since it didn't previously exist", transactionID); | ||
85 | |||
71 | XferUploaders.Add(transactionID, uploader); | 86 | XferUploaders.Add(transactionID, uploader); |
72 | } | ||
73 | 87 | ||
74 | return uploader; | 88 | return uploader; |
89 | } | ||
75 | } | 90 | } |
91 | |||
92 | m_log.WarnFormat("[AGENT ASSETS TRANSACTIONS]: Ignoring request for asset xfer uploader {0} since it already exists", transactionID); | ||
93 | |||
76 | return null; | 94 | return null; |
77 | } | 95 | } |
78 | 96 | ||
79 | public void HandleXfer(ulong xferID, uint packetID, byte[] data) | 97 | public void HandleXfer(ulong xferID, uint packetID, byte[] data) |
80 | { | 98 | { |
99 | AssetXferUploader foundUploader = null; | ||
100 | |||
81 | lock (XferUploaders) | 101 | lock (XferUploaders) |
82 | { | 102 | { |
83 | foreach (AssetXferUploader uploader in XferUploaders.Values) | 103 | foreach (AssetXferUploader uploader in XferUploaders.Values) |
84 | { | 104 | { |
105 | // m_log.DebugFormat( | ||
106 | // "[AGENT ASSETS TRANSACTIONS]: In HandleXfer, inspect xfer upload with xfer id {0}", | ||
107 | // uploader.XferID); | ||
108 | |||
85 | if (uploader.XferID == xferID) | 109 | if (uploader.XferID == xferID) |
86 | { | 110 | { |
87 | uploader.HandleXferPacket(xferID, packetID, data); | 111 | foundUploader = uploader; |
88 | break; | 112 | break; |
89 | } | 113 | } |
90 | } | 114 | } |
91 | } | 115 | } |
116 | |||
117 | if (foundUploader != null) | ||
118 | { | ||
119 | // m_log.DebugFormat( | ||
120 | // "[AGENT ASSETS TRANSACTIONS]: Found xfer uploader for xfer id {0}, packet id {1}, data length {2}", | ||
121 | // xferID, packetID, data.Length); | ||
122 | |||
123 | foundUploader.HandleXferPacket(xferID, packetID, data); | ||
124 | } | ||
125 | else | ||
126 | { | ||
127 | m_log.ErrorFormat( | ||
128 | "[AGENT ASSET TRANSACTIONS]: Could not find uploader for xfer id {0}, packet id {1}, data length {2}", | ||
129 | xferID, packetID, data.Length); | ||
130 | } | ||
131 | } | ||
132 | |||
133 | public bool RemoveXferUploader(UUID transactionID) | ||
134 | { | ||
135 | lock (XferUploaders) | ||
136 | { | ||
137 | bool removed = XferUploaders.Remove(transactionID); | ||
138 | |||
139 | if (!removed) | ||
140 | m_log.WarnFormat( | ||
141 | "[AGENT ASSET TRANSACTIONS]: Received request to remove xfer uploader with transaction ID {0} but none found", | ||
142 | transactionID); | ||
143 | // else | ||
144 | // m_log.DebugFormat( | ||
145 | // "[AGENT ASSET TRANSACTIONS]: Removed xfer uploader with transaction ID {0}", transactionID); | ||
146 | |||
147 | return removed; | ||
148 | } | ||
92 | } | 149 | } |
93 | 150 | ||
94 | public void RequestCreateInventoryItem(IClientAPI remoteClient, | 151 | public void RequestCreateInventoryItem(IClientAPI remoteClient, |
@@ -96,16 +153,24 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
96 | string description, string name, sbyte invType, | 153 | string description, string name, sbyte invType, |
97 | sbyte type, byte wearableType, uint nextOwnerMask) | 154 | sbyte type, byte wearableType, uint nextOwnerMask) |
98 | { | 155 | { |
99 | if (XferUploaders.ContainsKey(transactionID)) | 156 | AssetXferUploader uploader = null; |
157 | |||
158 | lock (XferUploaders) | ||
100 | { | 159 | { |
101 | XferUploaders[transactionID].RequestCreateInventoryItem( | 160 | if (XferUploaders.ContainsKey(transactionID)) |
102 | remoteClient, transactionID, folderID, | 161 | uploader = XferUploaders[transactionID]; |
103 | callbackID, description, name, invType, type, | ||
104 | wearableType, nextOwnerMask); | ||
105 | } | 162 | } |
106 | } | ||
107 | |||
108 | 163 | ||
164 | if (uploader != null) | ||
165 | uploader.RequestCreateInventoryItem( | ||
166 | remoteClient, transactionID, folderID, | ||
167 | callbackID, description, name, invType, type, | ||
168 | wearableType, nextOwnerMask); | ||
169 | else | ||
170 | m_log.ErrorFormat( | ||
171 | "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to create inventory item {1} from {2}", | ||
172 | transactionID, name, remoteClient.Name); | ||
173 | } | ||
109 | 174 | ||
110 | /// <summary> | 175 | /// <summary> |
111 | /// Get an uploaded asset. If the data is successfully retrieved, | 176 | /// Get an uploaded asset. If the data is successfully retrieved, |
@@ -113,19 +178,18 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
113 | /// </summary> | 178 | /// </summary> |
114 | /// <param name="transactionID"></param> | 179 | /// <param name="transactionID"></param> |
115 | /// <returns>The asset if the upload has completed, null if it has not.</returns> | 180 | /// <returns>The asset if the upload has completed, null if it has not.</returns> |
116 | public AssetBase GetTransactionAsset(UUID transactionID) | 181 | private AssetBase GetTransactionAsset(UUID transactionID) |
117 | { | 182 | { |
118 | if (XferUploaders.ContainsKey(transactionID)) | 183 | lock (XferUploaders) |
119 | { | 184 | { |
120 | AssetXferUploader uploader = XferUploaders[transactionID]; | 185 | if (XferUploaders.ContainsKey(transactionID)) |
121 | AssetBase asset = uploader.GetAssetData(); | ||
122 | |||
123 | lock (XferUploaders) | ||
124 | { | 186 | { |
125 | XferUploaders.Remove(transactionID); | 187 | AssetXferUploader uploader = XferUploaders[transactionID]; |
126 | } | 188 | AssetBase asset = uploader.GetAssetData(); |
189 | RemoveXferUploader(transactionID); | ||
127 | 190 | ||
128 | return asset; | 191 | return asset; |
192 | } | ||
129 | } | 193 | } |
130 | 194 | ||
131 | return null; | 195 | return null; |
@@ -135,7 +199,15 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
135 | SceneObjectPart part, UUID transactionID, | 199 | SceneObjectPart part, UUID transactionID, |
136 | TaskInventoryItem item) | 200 | TaskInventoryItem item) |
137 | { | 201 | { |
138 | if (XferUploaders.ContainsKey(transactionID)) | 202 | AssetXferUploader uploader = null; |
203 | |||
204 | lock (XferUploaders) | ||
205 | { | ||
206 | if (XferUploaders.ContainsKey(transactionID)) | ||
207 | uploader = XferUploaders[transactionID]; | ||
208 | } | ||
209 | |||
210 | if (uploader != null) | ||
139 | { | 211 | { |
140 | AssetBase asset = GetTransactionAsset(transactionID); | 212 | AssetBase asset = GetTransactionAsset(transactionID); |
141 | 213 | ||
@@ -161,28 +233,34 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
161 | m_Scene.AssetService.Store(asset); | 233 | m_Scene.AssetService.Store(asset); |
162 | } | 234 | } |
163 | } | 235 | } |
236 | else | ||
237 | { | ||
238 | m_log.ErrorFormat( | ||
239 | "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update task inventory item {1} in {2}", | ||
240 | transactionID, item.Name, part.Name); | ||
241 | } | ||
164 | } | 242 | } |
165 | 243 | ||
166 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, | 244 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, |
167 | UUID transactionID, InventoryItemBase item) | 245 | UUID transactionID, InventoryItemBase item) |
168 | { | 246 | { |
169 | if (XferUploaders.ContainsKey(transactionID)) | 247 | AssetXferUploader uploader = null; |
170 | { | ||
171 | AssetBase asset = GetTransactionAsset(transactionID); | ||
172 | 248 | ||
173 | if (asset != null) | 249 | lock (XferUploaders) |
174 | { | 250 | { |
175 | asset.FullID = UUID.Random(); | 251 | if (XferUploaders.ContainsKey(transactionID)) |
176 | asset.Name = item.Name; | 252 | uploader = XferUploaders[transactionID]; |
177 | asset.Description = item.Description; | 253 | } |
178 | asset.Type = (sbyte)item.AssetType; | ||
179 | item.AssetID = asset.FullID; | ||
180 | |||
181 | m_Scene.AssetService.Store(asset); | ||
182 | 254 | ||
183 | IInventoryService invService = m_Scene.InventoryService; | 255 | if (uploader != null) |
184 | invService.UpdateItem(item); | 256 | { |
185 | } | 257 | uploader.RequestUpdateInventoryItem(remoteClient, transactionID, item); |
258 | } | ||
259 | else | ||
260 | { | ||
261 | m_log.ErrorFormat( | ||
262 | "[AGENT ASSET TRANSACTIONS]: Could not find uploader with transaction ID {0} when handling request to update inventory item {1} for {2}", | ||
263 | transactionID, item.Name, remoteClient.Name); | ||
186 | } | 264 | } |
187 | } | 265 | } |
188 | } | 266 | } |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 82558de..a28d5d7 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs | |||
@@ -172,11 +172,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
172 | /// <summary> | 172 | /// <summary> |
173 | /// Update an inventory item with data that has been received through a | 173 | /// Update an inventory item with data that has been received through a |
174 | /// transaction. | 174 | /// transaction. |
175 | /// | 175 | /// </summary> |
176 | /// <remarks> | ||
176 | /// This is called when clothing or body parts are updated (for | 177 | /// This is called when clothing or body parts are updated (for |
177 | /// instance, with new textures or colours). It may also be called in | 178 | /// instance, with new textures or colours). It may also be called in |
178 | /// other situations. | 179 | /// other situations. |
179 | /// </summary> | 180 | /// </remarks> |
180 | /// <param name="remoteClient"></param> | 181 | /// <param name="remoteClient"></param> |
181 | /// <param name="transactionID"></param> | 182 | /// <param name="transactionID"></param> |
182 | /// <param name="item"></param> | 183 | /// <param name="item"></param> |
@@ -184,14 +185,12 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
184 | UUID transactionID, InventoryItemBase item) | 185 | UUID transactionID, InventoryItemBase item) |
185 | { | 186 | { |
186 | // m_log.DebugFormat( | 187 | // m_log.DebugFormat( |
187 | // "[TRANSACTIONS MANAGER] Called HandleItemUpdateFromTransaction with item {0}", | 188 | // "[ASSET TRANSACTION MODULE]: Called HandleItemUpdateFromTransaction with item {0}", |
188 | // item.Name); | 189 | // item.Name); |
189 | 190 | ||
190 | AgentAssetTransactions transactions = | 191 | AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); |
191 | GetUserTransactions(remoteClient.AgentId); | ||
192 | 192 | ||
193 | transactions.RequestUpdateInventoryItem(remoteClient, | 193 | transactions.RequestUpdateInventoryItem(remoteClient, transactionID, item); |
194 | transactionID, item); | ||
195 | } | 194 | } |
196 | 195 | ||
197 | /// <summary> | 196 | /// <summary> |
@@ -255,11 +254,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
255 | } | 254 | } |
256 | } | 255 | } |
257 | 256 | ||
258 | AgentAssetTransactions transactions = | 257 | AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); |
259 | GetUserTransactions(remoteClient.AgentId); | 258 | AssetXferUploader uploader = transactions.RequestXferUploader(transaction, assetID); |
260 | |||
261 | AssetXferUploader uploader = | ||
262 | transactions.RequestXferUploader(transaction); | ||
263 | 259 | ||
264 | if (uploader != null) | 260 | if (uploader != null) |
265 | { | 261 | { |
@@ -279,9 +275,8 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
279 | public void HandleXfer(IClientAPI remoteClient, ulong xferID, | 275 | public void HandleXfer(IClientAPI remoteClient, ulong xferID, |
280 | uint packetID, byte[] data) | 276 | uint packetID, byte[] data) |
281 | { | 277 | { |
282 | //m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data!"); | 278 | // m_log.Debug("xferID: " + xferID + " packetID: " + packetID + " data length " + data.Length); |
283 | AgentAssetTransactions transactions = | 279 | AgentAssetTransactions transactions = GetUserTransactions(remoteClient.AgentId); |
284 | GetUserTransactions(remoteClient.AgentId); | ||
285 | 280 | ||
286 | transactions.HandleXfer(xferID, packetID, data); | 281 | transactions.HandleXfer(xferID, packetID, data); |
287 | } | 282 | } |
diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs index a7929ba..ec4dfd0 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetXferUploader.cs | |||
@@ -40,11 +40,21 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
40 | { | 40 | { |
41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 41 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
42 | 42 | ||
43 | /// <summary> | ||
44 | /// Reference to the object that holds this uploader. Used to remove ourselves from it's list if we | ||
45 | /// are performing a delayed update. | ||
46 | /// </summary> | ||
47 | AgentAssetTransactions m_transactions; | ||
48 | |||
43 | private AssetBase m_asset; | 49 | private AssetBase m_asset; |
44 | private UUID InventFolder = UUID.Zero; | 50 | private UUID InventFolder = UUID.Zero; |
45 | private sbyte invType = 0; | 51 | private sbyte invType = 0; |
52 | |||
46 | private bool m_createItem = false; | 53 | private bool m_createItem = false; |
47 | private uint m_createItemCallback = 0; | 54 | private uint m_createItemCallback = 0; |
55 | private bool m_updateItem = false; | ||
56 | private InventoryItemBase m_updateItemData; | ||
57 | |||
48 | private string m_description = String.Empty; | 58 | private string m_description = String.Empty; |
49 | private bool m_dumpAssetToFile; | 59 | private bool m_dumpAssetToFile; |
50 | private bool m_finished = false; | 60 | private bool m_finished = false; |
@@ -58,9 +68,11 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
58 | public ulong XferID; | 68 | public ulong XferID; |
59 | private Scene m_Scene; | 69 | private Scene m_Scene; |
60 | 70 | ||
61 | public AssetXferUploader(Scene scene, bool dumpAssetToFile) | 71 | public AssetXferUploader(AgentAssetTransactions transactions, Scene scene, UUID assetID, bool dumpAssetToFile) |
62 | { | 72 | { |
73 | m_transactions = transactions; | ||
63 | m_Scene = scene; | 74 | m_Scene = scene; |
75 | m_asset = new AssetBase() { FullID = assetID }; | ||
64 | m_dumpAssetToFile = dumpAssetToFile; | 76 | m_dumpAssetToFile = dumpAssetToFile; |
65 | } | 77 | } |
66 | 78 | ||
@@ -73,6 +85,10 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
73 | /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> | 85 | /// <returns>True if the transfer is complete, false otherwise or if the xferID was not valid</returns> |
74 | public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) | 86 | public bool HandleXferPacket(ulong xferID, uint packetID, byte[] data) |
75 | { | 87 | { |
88 | // m_log.DebugFormat( | ||
89 | // "[ASSET XFER UPLOADER]: Received packet {0} for xfer {1} (data length {2})", | ||
90 | // packetID, xferID, data.Length); | ||
91 | |||
76 | if (XferID == xferID) | 92 | if (XferID == xferID) |
77 | { | 93 | { |
78 | if (m_asset.Data.Length > 1) | 94 | if (m_asset.Data.Length > 1) |
@@ -107,16 +123,20 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
107 | /// <param name="xferID"></param> | 123 | /// <param name="xferID"></param> |
108 | /// <param name="packetID"></param> | 124 | /// <param name="packetID"></param> |
109 | /// <param name="data"></param> | 125 | /// <param name="data"></param> |
110 | /// <returns>True if the transfer is complete, false otherwise</returns> | 126 | public void Initialise(IClientAPI remoteClient, UUID assetID, |
111 | public bool Initialise(IClientAPI remoteClient, UUID assetID, | ||
112 | UUID transaction, sbyte type, byte[] data, bool storeLocal, | 127 | UUID transaction, sbyte type, byte[] data, bool storeLocal, |
113 | bool tempFile) | 128 | bool tempFile) |
114 | { | 129 | { |
130 | // m_log.DebugFormat( | ||
131 | // "[ASSET XFER UPLOADER]: Initialised xfer from {0}, asset {1}, transaction {2}, type {3}, storeLocal {4}, tempFile {5}, already received data length {6}", | ||
132 | // remoteClient.Name, assetID, transaction, type, storeLocal, tempFile, data.Length); | ||
133 | |||
115 | ourClient = remoteClient; | 134 | ourClient = remoteClient; |
116 | m_asset = new AssetBase(assetID, "blank", type, | 135 | m_asset.Name = "blank"; |
117 | remoteClient.AgentId.ToString()); | ||
118 | m_asset.Data = data; | ||
119 | m_asset.Description = "empty"; | 136 | m_asset.Description = "empty"; |
137 | m_asset.Type = type; | ||
138 | m_asset.CreatorID = remoteClient.AgentId.ToString(); | ||
139 | m_asset.Data = data; | ||
120 | m_asset.Local = storeLocal; | 140 | m_asset.Local = storeLocal; |
121 | m_asset.Temporary = tempFile; | 141 | m_asset.Temporary = tempFile; |
122 | 142 | ||
@@ -126,21 +146,22 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
126 | if (m_asset.Data.Length > 2) | 146 | if (m_asset.Data.Length > 2) |
127 | { | 147 | { |
128 | SendCompleteMessage(); | 148 | SendCompleteMessage(); |
129 | return true; | ||
130 | } | 149 | } |
131 | else | 150 | else |
132 | { | 151 | { |
133 | RequestStartXfer(); | 152 | RequestStartXfer(); |
134 | } | 153 | } |
135 | |||
136 | return false; | ||
137 | } | 154 | } |
138 | 155 | ||
139 | protected void RequestStartXfer() | 156 | protected void RequestStartXfer() |
140 | { | 157 | { |
141 | XferID = Util.GetNextXferID(); | 158 | XferID = Util.GetNextXferID(); |
142 | ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, | 159 | |
143 | 0, new byte[0]); | 160 | // m_log.DebugFormat( |
161 | // "[ASSET XFER UPLOADER]: Requesting Xfer of asset {0}, type {1}, transfer id {2} from {3}", | ||
162 | // m_asset.FullID, m_asset.Type, XferID, ourClient.Name); | ||
163 | |||
164 | ourClient.SendXferRequest(XferID, m_asset.Type, m_asset.FullID, 0, new byte[0]); | ||
144 | } | 165 | } |
145 | 166 | ||
146 | protected void SendCompleteMessage() | 167 | protected void SendCompleteMessage() |
@@ -148,18 +169,32 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
148 | ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, | 169 | ourClient.SendAssetUploadCompleteMessage(m_asset.Type, true, |
149 | m_asset.FullID); | 170 | m_asset.FullID); |
150 | 171 | ||
151 | m_finished = true; | 172 | // We must lock in order to avoid a race with a separate thread dealing with an inventory item or create |
152 | if (m_createItem) | 173 | // message from other client UDP. |
153 | { | 174 | lock (this) |
154 | DoCreateItem(m_createItemCallback); | ||
155 | } | ||
156 | else if (m_storeLocal) | ||
157 | { | 175 | { |
158 | m_Scene.AssetService.Store(m_asset); | 176 | m_finished = true; |
177 | if (m_createItem) | ||
178 | { | ||
179 | DoCreateItem(m_createItemCallback); | ||
180 | } | ||
181 | else if (m_updateItem) | ||
182 | { | ||
183 | StoreAssetForItemUpdate(m_updateItemData); | ||
184 | |||
185 | // Remove ourselves from the list of transactions if completion was delayed until the transaction | ||
186 | // was complete. | ||
187 | // TODO: Should probably do the same for create item. | ||
188 | m_transactions.RemoveXferUploader(TransactionID); | ||
189 | } | ||
190 | else if (m_storeLocal) | ||
191 | { | ||
192 | m_Scene.AssetService.Store(m_asset); | ||
193 | } | ||
159 | } | 194 | } |
160 | 195 | ||
161 | m_log.DebugFormat( | 196 | m_log.DebugFormat( |
162 | "[ASSET TRANSACTIONS]: Uploaded asset {0} for transaction {1}", | 197 | "[ASSET XFER UPLOADER]: Uploaded asset {0} for transaction {1}", |
163 | m_asset.FullID, TransactionID); | 198 | m_asset.FullID, TransactionID); |
164 | 199 | ||
165 | if (m_dumpAssetToFile) | 200 | if (m_dumpAssetToFile) |
@@ -205,18 +240,66 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction | |||
205 | m_asset.Description = description; | 240 | m_asset.Description = description; |
206 | m_asset.Type = type; | 241 | m_asset.Type = type; |
207 | 242 | ||
243 | // We must lock to avoid a race with a separate thread uploading the asset. | ||
244 | lock (this) | ||
245 | { | ||
246 | if (m_finished) | ||
247 | { | ||
248 | DoCreateItem(callbackID); | ||
249 | } | ||
250 | else | ||
251 | { | ||
252 | m_createItem = true; //set flag so the inventory item is created when upload is complete | ||
253 | m_createItemCallback = callbackID; | ||
254 | } | ||
255 | } | ||
256 | } | ||
257 | } | ||
258 | |||
259 | public void RequestUpdateInventoryItem(IClientAPI remoteClient, UUID transactionID, InventoryItemBase item) | ||
260 | { | ||
261 | // We must lock to avoid a race with a separate thread uploading the asset. | ||
262 | lock (this) | ||
263 | { | ||
264 | m_asset.Name = item.Name; | ||
265 | m_asset.Description = item.Description; | ||
266 | m_asset.Type = (sbyte)item.AssetType; | ||
267 | |||
268 | // We must always store the item at this point even if the asset hasn't finished uploading, in order | ||
269 | // to avoid a race condition when the appearance module retrieves the item to set the asset id in | ||
270 | // the AvatarAppearance structure. | ||
271 | item.AssetID = m_asset.FullID; | ||
272 | m_Scene.InventoryService.UpdateItem(item); | ||
273 | |||
208 | if (m_finished) | 274 | if (m_finished) |
209 | { | 275 | { |
210 | DoCreateItem(callbackID); | 276 | StoreAssetForItemUpdate(item); |
211 | } | 277 | } |
212 | else | 278 | else |
213 | { | 279 | { |
214 | m_createItem = true; //set flag so the inventory item is created when upload is complete | 280 | // m_log.DebugFormat( |
215 | m_createItemCallback = callbackID; | 281 | // "[ASSET XFER UPLOADER]: Holding update inventory item request {0} for {1} pending completion of asset xfer for transaction {2}", |
282 | // item.Name, remoteClient.Name, transactionID); | ||
283 | |||
284 | m_updateItem = true; | ||
285 | m_updateItemData = item; | ||
216 | } | 286 | } |
217 | } | 287 | } |
218 | } | 288 | } |
219 | 289 | ||
290 | /// <summary> | ||
291 | /// Store the asset for the given item. | ||
292 | /// </summary> | ||
293 | /// <param name="item"></param> | ||
294 | private void StoreAssetForItemUpdate(InventoryItemBase item) | ||
295 | { | ||
296 | // m_log.DebugFormat( | ||
297 | // "[ASSET XFER UPLOADER]: Storing asset {0} for earlier item update for {1} for {2}", | ||
298 | // m_asset.FullID, item.Name, ourClient.Name); | ||
299 | |||
300 | m_Scene.AssetService.Store(m_asset); | ||
301 | } | ||
302 | |||
220 | private void DoCreateItem(uint callbackID) | 303 | private void DoCreateItem(uint callbackID) |
221 | { | 304 | { |
222 | m_Scene.AssetService.Store(m_asset); | 305 | m_Scene.AssetService.Store(m_asset); |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index 996e2ab..b965d75 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs | |||
@@ -143,20 +143,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
143 | 143 | ||
144 | public void SaveChangedAttachments(IScenePresence sp) | 144 | public void SaveChangedAttachments(IScenePresence sp) |
145 | { | 145 | { |
146 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name); | ||
147 | |||
146 | foreach (SceneObjectGroup grp in sp.GetAttachments()) | 148 | foreach (SceneObjectGroup grp in sp.GetAttachments()) |
147 | { | 149 | { |
148 | if (grp.HasGroupChanged) // Resizer scripts? | 150 | // if (grp.HasGroupChanged) // Resizer scripts? |
149 | { | 151 | // { |
150 | grp.IsAttachment = false; | 152 | grp.IsAttachment = false; |
151 | grp.AbsolutePosition = grp.RootPart.AttachedPos; | 153 | grp.AbsolutePosition = grp.RootPart.AttachedPos; |
152 | UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); | 154 | UpdateKnownItem(sp.ControllingClient, grp); |
153 | grp.IsAttachment = true; | 155 | grp.IsAttachment = true; |
154 | } | 156 | // } |
155 | } | 157 | } |
156 | } | 158 | } |
157 | 159 | ||
158 | public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) | 160 | public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) |
159 | { | 161 | { |
162 | // m_log.DebugFormat( | ||
163 | // "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}", | ||
164 | // m_scene.RegionInfo.RegionName, sp.Name, silent); | ||
165 | |||
160 | foreach (SceneObjectGroup sop in sp.GetAttachments()) | 166 | foreach (SceneObjectGroup sop in sp.GetAttachments()) |
161 | { | 167 | { |
162 | sop.Scene.DeleteSceneObject(sop, silent); | 168 | sop.Scene.DeleteSceneObject(sop, silent); |
@@ -212,7 +218,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
212 | m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); | 218 | m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); |
213 | 219 | ||
214 | // Save avatar attachment information | 220 | // Save avatar attachment information |
215 | m_log.Info( | 221 | m_log.Debug( |
216 | "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId | 222 | "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId |
217 | + ", AttachmentPoint: " + AttachmentPt); | 223 | + ", AttachmentPoint: " + AttachmentPt); |
218 | 224 | ||
@@ -240,80 +246,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
240 | 246 | ||
241 | private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) | 247 | private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) |
242 | { | 248 | { |
243 | // m_log.DebugFormat( | 249 | lock (sp.AttachmentsSyncLock) |
244 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", | ||
245 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); | ||
246 | |||
247 | if (sp.GetAttachments(attachmentPt).Contains(group)) | ||
248 | { | ||
249 | // m_log.WarnFormat( | ||
250 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | ||
251 | // group.Name, group.LocalId, sp.Name, AttachmentPt); | ||
252 | |||
253 | return false; | ||
254 | } | ||
255 | |||
256 | Vector3 attachPos = group.AbsolutePosition; | ||
257 | |||
258 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | ||
259 | // be removed when that functionality is implemented in opensim | ||
260 | attachmentPt &= 0x7f; | ||
261 | |||
262 | // If the attachment point isn't the same as the one previously used | ||
263 | // set it's offset position = 0 so that it appears on the attachment point | ||
264 | // and not in a weird location somewhere unknown. | ||
265 | if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) | ||
266 | { | ||
267 | attachPos = Vector3.Zero; | ||
268 | } | ||
269 | |||
270 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | ||
271 | if (attachmentPt == 0) | ||
272 | { | ||
273 | // Check object for stored attachment point | ||
274 | attachmentPt = group.AttachmentPoint; | ||
275 | } | ||
276 | |||
277 | // if we still didn't find a suitable attachment point....... | ||
278 | if (attachmentPt == 0) | ||
279 | { | ||
280 | // Stick it on left hand with Zero Offset from the attachment point. | ||
281 | attachmentPt = (uint)AttachmentPoint.LeftHand; | ||
282 | attachPos = Vector3.Zero; | ||
283 | } | ||
284 | |||
285 | group.AttachmentPoint = attachmentPt; | ||
286 | group.AbsolutePosition = attachPos; | ||
287 | |||
288 | // We also don't want to do any of the inventory operations for an NPC. | ||
289 | if (sp.PresenceType != PresenceType.Npc) | ||
290 | { | 250 | { |
291 | // Remove any previous attachments | 251 | // m_log.DebugFormat( |
292 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | 252 | // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})", |
293 | 253 | // group.Name, group.LocalId, sp.Name, attachmentPt, silent); | |
294 | // At the moment we can only deal with a single attachment | 254 | |
295 | if (attachments.Count != 0) | 255 | if (sp.GetAttachments(attachmentPt).Contains(group)) |
296 | { | 256 | { |
297 | UUID oldAttachmentItemID = attachments[0].GetFromItemID(); | 257 | // m_log.WarnFormat( |
258 | // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", | ||
259 | // group.Name, group.LocalId, sp.Name, AttachmentPt); | ||
298 | 260 | ||
299 | if (oldAttachmentItemID != UUID.Zero) | 261 | return false; |
300 | DetachSingleAttachmentToInv(oldAttachmentItemID, sp); | ||
301 | else | ||
302 | m_log.WarnFormat( | ||
303 | "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", | ||
304 | attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); | ||
305 | } | 262 | } |
306 | |||
307 | // Add the new attachment to inventory if we don't already have it. | ||
308 | UUID newAttachmentItemID = group.GetFromItemID(); | ||
309 | if (newAttachmentItemID == UUID.Zero) | ||
310 | newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID; | ||
311 | 263 | ||
312 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); | 264 | Vector3 attachPos = group.AbsolutePosition; |
265 | |||
266 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | ||
267 | // be removed when that functionality is implemented in opensim | ||
268 | attachmentPt &= 0x7f; | ||
269 | |||
270 | // If the attachment point isn't the same as the one previously used | ||
271 | // set it's offset position = 0 so that it appears on the attachment point | ||
272 | // and not in a weird location somewhere unknown. | ||
273 | if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint) | ||
274 | { | ||
275 | attachPos = Vector3.Zero; | ||
276 | } | ||
277 | |||
278 | // AttachmentPt 0 means the client chose to 'wear' the attachment. | ||
279 | if (attachmentPt == 0) | ||
280 | { | ||
281 | // Check object for stored attachment point | ||
282 | attachmentPt = group.AttachmentPoint; | ||
283 | } | ||
284 | |||
285 | // if we still didn't find a suitable attachment point....... | ||
286 | if (attachmentPt == 0) | ||
287 | { | ||
288 | // Stick it on left hand with Zero Offset from the attachment point. | ||
289 | attachmentPt = (uint)AttachmentPoint.LeftHand; | ||
290 | attachPos = Vector3.Zero; | ||
291 | } | ||
292 | |||
293 | group.AttachmentPoint = attachmentPt; | ||
294 | group.AbsolutePosition = attachPos; | ||
295 | |||
296 | // We also don't want to do any of the inventory operations for an NPC. | ||
297 | if (sp.PresenceType != PresenceType.Npc) | ||
298 | { | ||
299 | // Remove any previous attachments | ||
300 | List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); | ||
301 | |||
302 | // At the moment we can only deal with a single attachment | ||
303 | if (attachments.Count != 0) | ||
304 | { | ||
305 | UUID oldAttachmentItemID = attachments[0].GetFromItemID(); | ||
306 | |||
307 | if (oldAttachmentItemID != UUID.Zero) | ||
308 | DetachSingleAttachmentToInv(oldAttachmentItemID, sp); | ||
309 | else | ||
310 | m_log.WarnFormat( | ||
311 | "[ATTACHMENTS MODULE]: When detaching existing attachment {0} {1} at point {2} to make way for {3} {4} for {5}, couldn't find the associated item ID to adjust inventory attachment record!", | ||
312 | attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name); | ||
313 | } | ||
314 | |||
315 | // Add the new attachment to inventory if we don't already have it. | ||
316 | UUID newAttachmentItemID = group.GetFromItemID(); | ||
317 | if (newAttachmentItemID == UUID.Zero) | ||
318 | newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID; | ||
319 | |||
320 | ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group); | ||
321 | } | ||
322 | |||
323 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); | ||
313 | } | 324 | } |
314 | 325 | ||
315 | AttachToAgent(sp, group, attachmentPt, attachPos, silent); | ||
316 | |||
317 | return true; | 326 | return true; |
318 | } | 327 | } |
319 | 328 | ||
@@ -322,17 +331,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
322 | RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, | 331 | RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, |
323 | RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) | 332 | RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) |
324 | { | 333 | { |
325 | foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) | 334 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
335 | |||
336 | if (sp == null) | ||
326 | { | 337 | { |
327 | RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); | 338 | m_log.ErrorFormat( |
339 | "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()", | ||
340 | remoteClient.Name, remoteClient.AgentId); | ||
341 | return; | ||
342 | } | ||
343 | |||
344 | lock (sp.AttachmentsSyncLock) | ||
345 | { | ||
346 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name); | ||
347 | |||
348 | foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) | ||
349 | { | ||
350 | RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt); | ||
351 | } | ||
328 | } | 352 | } |
329 | } | 353 | } |
330 | 354 | ||
331 | public ISceneEntity RezSingleAttachmentFromInventory( | 355 | public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt) |
332 | IClientAPI remoteClient, UUID itemID, uint AttachmentPt) | ||
333 | { | 356 | { |
334 | // m_log.DebugFormat( | 357 | // m_log.DebugFormat( |
335 | // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", | 358 | // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", |
336 | // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); | 359 | // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); |
337 | 360 | ||
338 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); | 361 | ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); |
@@ -344,11 +367,46 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
344 | remoteClient.Name, remoteClient.AgentId); | 367 | remoteClient.Name, remoteClient.AgentId); |
345 | return null; | 368 | return null; |
346 | } | 369 | } |
347 | 370 | ||
371 | return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt); | ||
372 | } | ||
373 | |||
374 | public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt) | ||
375 | { | ||
376 | // m_log.DebugFormat( | ||
377 | // "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}", | ||
378 | // (AttachmentPoint)AttachmentPt, itemID, sp.Name); | ||
379 | |||
348 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should | 380 | // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should |
349 | // be removed when that functionality is implemented in opensim | 381 | // be removed when that functionality is implemented in opensim |
350 | AttachmentPt &= 0x7f; | 382 | AttachmentPt &= 0x7f; |
351 | 383 | ||
384 | // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such). | ||
385 | // This often happens during login - not sure the exact reason. | ||
386 | // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the | ||
387 | // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login | ||
388 | // before anything has actually been attached. | ||
389 | bool alreadyOn = false; | ||
390 | List<SceneObjectGroup> existingAttachments = sp.GetAttachments(); | ||
391 | foreach (SceneObjectGroup so in existingAttachments) | ||
392 | { | ||
393 | if (so.GetFromItemID() == itemID) | ||
394 | { | ||
395 | alreadyOn = true; | ||
396 | break; | ||
397 | } | ||
398 | } | ||
399 | |||
400 | // if (sp.Appearance.GetAttachmentForItem(itemID) != null) | ||
401 | if (alreadyOn) | ||
402 | { | ||
403 | // m_log.WarnFormat( | ||
404 | // "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn", | ||
405 | // sp.Name, itemID, AttachmentPt); | ||
406 | |||
407 | return null; | ||
408 | } | ||
409 | |||
352 | SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); | 410 | SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt); |
353 | 411 | ||
354 | if (att == null) | 412 | if (att == null) |
@@ -363,65 +421,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
363 | IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); | 421 | IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); |
364 | if (invAccess != null) | 422 | if (invAccess != null) |
365 | { | 423 | { |
366 | SceneObjectGroup objatt; | 424 | lock (sp.AttachmentsSyncLock) |
367 | |||
368 | if (itemID != UUID.Zero) | ||
369 | objatt = invAccess.RezObject(sp.ControllingClient, | ||
370 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
371 | false, false, sp.UUID, true); | ||
372 | else | ||
373 | objatt = invAccess.RezObject(sp.ControllingClient, | ||
374 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
375 | false, false, sp.UUID, true); | ||
376 | |||
377 | // m_log.DebugFormat( | ||
378 | // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", | ||
379 | // objatt.Name, remoteClient.Name, AttachmentPt); | ||
380 | |||
381 | if (objatt != null) | ||
382 | { | 425 | { |
383 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. | 426 | SceneObjectGroup objatt; |
384 | objatt.HasGroupChanged = false; | 427 | |
385 | bool tainted = false; | 428 | if (itemID != UUID.Zero) |
386 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) | 429 | objatt = invAccess.RezObject(sp.ControllingClient, |
387 | tainted = true; | 430 | itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, |
388 | 431 | false, false, sp.UUID, true); | |
389 | // This will throw if the attachment fails | 432 | else |
390 | try | 433 | objatt = invAccess.RezObject(sp.ControllingClient, |
434 | null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, | ||
435 | false, false, sp.UUID, true); | ||
436 | |||
437 | // m_log.DebugFormat( | ||
438 | // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", | ||
439 | // objatt.Name, remoteClient.Name, AttachmentPt); | ||
440 | |||
441 | if (objatt != null) | ||
391 | { | 442 | { |
392 | AttachObject(sp, objatt, attachmentPt, false); | 443 | // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller. |
444 | objatt.HasGroupChanged = false; | ||
445 | bool tainted = false; | ||
446 | if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) | ||
447 | tainted = true; | ||
448 | |||
449 | // This will throw if the attachment fails | ||
450 | try | ||
451 | { | ||
452 | AttachObject(sp, objatt, attachmentPt, false); | ||
453 | } | ||
454 | catch (Exception e) | ||
455 | { | ||
456 | m_log.ErrorFormat( | ||
457 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", | ||
458 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); | ||
459 | |||
460 | // Make sure the object doesn't stick around and bail | ||
461 | sp.RemoveAttachment(objatt); | ||
462 | m_scene.DeleteSceneObject(objatt, false); | ||
463 | return null; | ||
464 | } | ||
465 | |||
466 | if (tainted) | ||
467 | objatt.HasGroupChanged = true; | ||
468 | |||
469 | // Fire after attach, so we don't get messy perms dialogs | ||
470 | // 4 == AttachedRez | ||
471 | objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | ||
472 | objatt.ResumeScripts(); | ||
473 | |||
474 | // Do this last so that event listeners have access to all the effects of the attachment | ||
475 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); | ||
476 | |||
477 | return objatt; | ||
393 | } | 478 | } |
394 | catch (Exception e) | 479 | else |
395 | { | 480 | { |
396 | m_log.ErrorFormat( | 481 | m_log.WarnFormat( |
397 | "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", | 482 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", |
398 | objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); | 483 | itemID, sp.Name, attachmentPt); |
399 | |||
400 | // Make sure the object doesn't stick around and bail | ||
401 | sp.RemoveAttachment(objatt); | ||
402 | m_scene.DeleteSceneObject(objatt, false); | ||
403 | return null; | ||
404 | } | 484 | } |
405 | |||
406 | if (tainted) | ||
407 | objatt.HasGroupChanged = true; | ||
408 | |||
409 | // Fire after attach, so we don't get messy perms dialogs | ||
410 | // 4 == AttachedRez | ||
411 | objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4); | ||
412 | objatt.ResumeScripts(); | ||
413 | |||
414 | // Do this last so that event listeners have access to all the effects of the attachment | ||
415 | m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); | ||
416 | } | ||
417 | else | ||
418 | { | ||
419 | m_log.WarnFormat( | ||
420 | "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", | ||
421 | itemID, sp.Name, attachmentPt); | ||
422 | } | 485 | } |
423 | |||
424 | return objatt; | ||
425 | } | 486 | } |
426 | 487 | ||
427 | return null; | 488 | return null; |
@@ -438,8 +499,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
438 | IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) | 499 | IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) |
439 | { | 500 | { |
440 | // m_log.DebugFormat( | 501 | // m_log.DebugFormat( |
441 | // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", | 502 | // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", |
442 | // att.Name, remoteClient.Name, AttachmentPt, itemID); | 503 | // att.Name, sp.Name, AttachmentPt, itemID); |
443 | 504 | ||
444 | if (UUID.Zero == itemID) | 505 | if (UUID.Zero == itemID) |
445 | { | 506 | { |
@@ -462,6 +523,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
462 | 523 | ||
463 | public void DetachObject(uint objectLocalID, IClientAPI remoteClient) | 524 | public void DetachObject(uint objectLocalID, IClientAPI remoteClient) |
464 | { | 525 | { |
526 | // m_log.DebugFormat( | ||
527 | // "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name); | ||
528 | |||
465 | SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); | 529 | SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); |
466 | if (group != null) | 530 | if (group != null) |
467 | { | 531 | { |
@@ -474,14 +538,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
474 | ScenePresence presence; | 538 | ScenePresence presence; |
475 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) | 539 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) |
476 | { | 540 | { |
477 | // Save avatar attachment information | 541 | lock (presence.AttachmentsSyncLock) |
478 | m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); | 542 | { |
479 | 543 | // Save avatar attachment information | |
480 | bool changed = presence.Appearance.DetachAttachment(itemID); | 544 | m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); |
481 | if (changed && m_scene.AvatarFactory != null) | ||
482 | m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); | ||
483 | 545 | ||
484 | DetachSingleAttachmentToInv(itemID, presence); | 546 | bool changed = presence.Appearance.DetachAttachment(itemID); |
547 | if (changed && m_scene.AvatarFactory != null) | ||
548 | m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); | ||
549 | |||
550 | DetachSingleAttachmentToInv(itemID, presence); | ||
551 | } | ||
485 | } | 552 | } |
486 | } | 553 | } |
487 | 554 | ||
@@ -489,7 +556,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
489 | { | 556 | { |
490 | // m_log.DebugFormat( | 557 | // m_log.DebugFormat( |
491 | // "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", | 558 | // "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", |
492 | // remoteClient.Name, sceneObjectID); | 559 | // remoteClient.Name, soLocalId); |
493 | 560 | ||
494 | SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); | 561 | SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); |
495 | 562 | ||
@@ -508,24 +575,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
508 | ScenePresence presence; | 575 | ScenePresence presence; |
509 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) | 576 | if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) |
510 | { | 577 | { |
511 | if (!m_scene.Permissions.CanRezObject( | 578 | lock (presence.AttachmentsSyncLock) |
512 | so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) | 579 | { |
513 | return; | 580 | if (!m_scene.Permissions.CanRezObject( |
581 | so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) | ||
582 | return; | ||
514 | 583 | ||
515 | bool changed = presence.Appearance.DetachAttachment(inventoryID); | 584 | bool changed = presence.Appearance.DetachAttachment(inventoryID); |
516 | if (changed && m_scene.AvatarFactory != null) | 585 | if (changed && m_scene.AvatarFactory != null) |
517 | m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); | 586 | m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); |
518 | 587 | ||
519 | presence.RemoveAttachment(so); | 588 | presence.RemoveAttachment(so); |
520 | DetachSceneObjectToGround(so, presence); | 589 | DetachSceneObjectToGround(so, presence); |
521 | 590 | ||
522 | List<UUID> uuids = new List<UUID>(); | 591 | List<UUID> uuids = new List<UUID>(); |
523 | uuids.Add(inventoryID); | 592 | uuids.Add(inventoryID); |
524 | m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); | 593 | m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); |
525 | remoteClient.SendRemoveInventoryItem(inventoryID); | 594 | remoteClient.SendRemoveInventoryItem(inventoryID); |
526 | } | 595 | } |
527 | 596 | ||
528 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); | 597 | m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); |
598 | } | ||
529 | } | 599 | } |
530 | 600 | ||
531 | /// <summary> | 601 | /// <summary> |
@@ -559,6 +629,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
559 | // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? | 629 | // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? |
560 | private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) | 630 | private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) |
561 | { | 631 | { |
632 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name); | ||
633 | |||
562 | if (itemID == UUID.Zero) // If this happened, someone made a mistake.... | 634 | if (itemID == UUID.Zero) // If this happened, someone made a mistake.... |
563 | return; | 635 | return; |
564 | 636 | ||
@@ -567,37 +639,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
567 | EntityBase[] detachEntities = m_scene.GetEntities(); | 639 | EntityBase[] detachEntities = m_scene.GetEntities(); |
568 | SceneObjectGroup group; | 640 | SceneObjectGroup group; |
569 | 641 | ||
570 | foreach (EntityBase entity in detachEntities) | 642 | lock (sp.AttachmentsSyncLock) |
571 | { | 643 | { |
572 | if (entity is SceneObjectGroup) | 644 | foreach (EntityBase entity in detachEntities) |
573 | { | 645 | { |
574 | group = (SceneObjectGroup)entity; | 646 | if (entity is SceneObjectGroup) |
575 | if (group.GetFromItemID() == itemID) | ||
576 | { | 647 | { |
577 | m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); | 648 | group = (SceneObjectGroup)entity; |
578 | sp.RemoveAttachment(group); | 649 | if (group.GetFromItemID() == itemID) |
579 | 650 | { | |
580 | // Prepare sog for storage | 651 | m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); |
581 | group.AttachedAvatar = UUID.Zero; | 652 | sp.RemoveAttachment(group); |
582 | 653 | ||
583 | group.ForEachPart( | 654 | // Prepare sog for storage |
584 | delegate(SceneObjectPart part) | 655 | group.AttachedAvatar = UUID.Zero; |
585 | { | 656 | group.RootPart.SetParentLocalId(0); |
586 | // If there are any scripts, | 657 | group.IsAttachment = false; |
587 | // then always trigger a new object and state persistence in UpdateKnownItem() | 658 | group.AbsolutePosition = group.RootPart.AttachedPos; |
588 | if (part.Inventory.ContainsScripts()) | 659 | |
589 | group.HasGroupChanged = true; | 660 | UpdateKnownItem(sp.ControllingClient, group); |
590 | } | 661 | m_scene.DeleteSceneObject(group, false); |
591 | ); | 662 | |
592 | 663 | return; | |
593 | group.RootPart.SetParentLocalId(0); | 664 | } |
594 | group.IsAttachment = false; | ||
595 | group.AbsolutePosition = group.RootPart.AttachedPos; | ||
596 | |||
597 | UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID); | ||
598 | m_scene.DeleteSceneObject(group, false); | ||
599 | |||
600 | return; | ||
601 | } | 665 | } |
602 | } | 666 | } |
603 | } | 667 | } |
@@ -628,28 +692,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
628 | /// </remarks> | 692 | /// </remarks> |
629 | /// <param name="remoteClient"></param> | 693 | /// <param name="remoteClient"></param> |
630 | /// <param name="grp"></param> | 694 | /// <param name="grp"></param> |
631 | /// <param name="itemID"></param> | 695 | private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp) |
632 | /// <param name="agentID"></param> | ||
633 | public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID) | ||
634 | { | 696 | { |
635 | if (grp != null) | 697 | if (grp.HasGroupChanged || grp.ContainsScripts()) |
636 | { | 698 | { |
637 | if (!grp.HasGroupChanged) | ||
638 | { | ||
639 | m_log.DebugFormat( | ||
640 | "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", | ||
641 | grp.UUID, grp.AttachmentPoint); | ||
642 | |||
643 | return; | ||
644 | } | ||
645 | |||
646 | m_log.DebugFormat( | 699 | m_log.DebugFormat( |
647 | "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", | 700 | "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", |
648 | grp.UUID, grp.AttachmentPoint); | 701 | grp.UUID, grp.AttachmentPoint); |
649 | 702 | ||
650 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); | 703 | string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); |
651 | 704 | ||
652 | InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); | 705 | InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId); |
653 | item = m_scene.InventoryService.GetItem(item); | 706 | item = m_scene.InventoryService.GetItem(item); |
654 | 707 | ||
655 | if (item != null) | 708 | if (item != null) |
@@ -675,6 +728,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
675 | remoteClient.SendInventoryItemCreateUpdate(item, 0); | 728 | remoteClient.SendInventoryItemCreateUpdate(item, 0); |
676 | } | 729 | } |
677 | } | 730 | } |
731 | else | ||
732 | { | ||
733 | m_log.DebugFormat( | ||
734 | "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}", | ||
735 | grp.UUID, grp.AttachmentPoint); | ||
736 | } | ||
678 | } | 737 | } |
679 | 738 | ||
680 | /// <summary> | 739 | /// <summary> |
@@ -692,7 +751,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
692 | private void AttachToAgent( | 751 | private void AttachToAgent( |
693 | IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) | 752 | IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) |
694 | { | 753 | { |
695 | // m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", | 754 | // m_log.DebugFormat( |
755 | // "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", | ||
696 | // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); | 756 | // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); |
697 | 757 | ||
698 | so.DetachFromBackup(); | 758 | so.DetachFromBackup(); |
@@ -745,7 +805,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
745 | /// <returns>The user inventory item created that holds the attachment.</returns> | 805 | /// <returns>The user inventory item created that holds the attachment.</returns> |
746 | private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) | 806 | private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp) |
747 | { | 807 | { |
748 | // m_log.DebugFormat("[SCENE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId); | 808 | // m_log.DebugFormat( |
809 | // "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}", | ||
810 | // grp.Name, grp.LocalId, remoteClient.Name); | ||
749 | 811 | ||
750 | Vector3 inventoryStoredPosition = new Vector3 | 812 | Vector3 inventoryStoredPosition = new Vector3 |
751 | (((grp.AbsolutePosition.X > (int)Constants.RegionSize) | 813 | (((grp.AbsolutePosition.X > (int)Constants.RegionSize) |
@@ -829,4 +891,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments | |||
829 | return item; | 891 | return item; |
830 | } | 892 | } |
831 | } | 893 | } |
832 | } | 894 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs index 35183b3..ff3358f 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs | |||
@@ -220,6 +220,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests | |||
220 | Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); | 220 | Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); |
221 | } | 221 | } |
222 | 222 | ||
223 | /// <summary> | ||
224 | /// Test that attachments don't hang about in the scene when the agent is closed | ||
225 | /// </summary> | ||
226 | [Test] | ||
227 | public void TestRemoveAttachmentsOnAvatarExit() | ||
228 | { | ||
229 | TestHelpers.InMethod(); | ||
230 | // log4net.Config.XmlConfigurator.Configure(); | ||
231 | |||
232 | UUID userId = TestHelpers.ParseTail(0x1); | ||
233 | UUID attItemId = TestHelpers.ParseTail(0x2); | ||
234 | UUID attAssetId = TestHelpers.ParseTail(0x3); | ||
235 | string attName = "att"; | ||
236 | |||
237 | UserAccountHelpers.CreateUserWithInventory(scene, userId); | ||
238 | InventoryItemBase attItem | ||
239 | = UserInventoryHelpers.CreateInventoryItem( | ||
240 | scene, attName, attItemId, attAssetId, userId, InventoryType.Object); | ||
241 | |||
242 | AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId); | ||
243 | acd.Appearance = new AvatarAppearance(); | ||
244 | acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID); | ||
245 | ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd); | ||
246 | |||
247 | SceneObjectGroup rezzedAtt = presence.GetAttachments()[0]; | ||
248 | |||
249 | scene.IncomingCloseAgent(presence.UUID); | ||
250 | |||
251 | // Check that we can't retrieve this attachment from the scene. | ||
252 | Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null); | ||
253 | } | ||
254 | |||
223 | [Test] | 255 | [Test] |
224 | public void TestRezAttachmentsOnAvatarEntrance() | 256 | public void TestRezAttachmentsOnAvatarEntrance() |
225 | { | 257 | { |
diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index b6a1564..0cadd83 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs | |||
@@ -211,8 +211,17 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
211 | // Process the visual params, this may change height as well | 211 | // Process the visual params, this may change height as well |
212 | if (visualParams != null) | 212 | if (visualParams != null) |
213 | { | 213 | { |
214 | // string[] visualParamsStrings = new string[visualParams.Length]; | ||
215 | // for (int i = 0; i < visualParams.Length; i++) | ||
216 | // visualParamsStrings[i] = visualParams[i].ToString(); | ||
217 | // m_log.DebugFormat( | ||
218 | // "[AVFACTORY]: Setting visual params for {0} to {1}", | ||
219 | // client.Name, string.Join(", ", visualParamsStrings)); | ||
220 | |||
221 | float oldHeight = sp.Appearance.AvatarHeight; | ||
214 | changed = sp.Appearance.SetVisualParams(visualParams); | 222 | changed = sp.Appearance.SetVisualParams(visualParams); |
215 | if (sp.Appearance.AvatarHeight > 0) | 223 | |
224 | if (sp.Appearance.AvatarHeight != oldHeight && sp.Appearance.AvatarHeight > 0) | ||
216 | sp.SetHeight(sp.Appearance.AvatarHeight); | 225 | sp.SetHeight(sp.Appearance.AvatarHeight); |
217 | } | 226 | } |
218 | 227 | ||
@@ -416,6 +425,13 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
416 | 425 | ||
417 | // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); | 426 | // m_log.WarnFormat("[AVFACTORY] avatar {0} save appearance",agentid); |
418 | 427 | ||
428 | // This could take awhile since it needs to pull inventory | ||
429 | // We need to do it at the point of save so that there is a sufficient delay for any upload of new body part/shape | ||
430 | // assets and item asset id changes to complete. | ||
431 | // I don't think we need to worry about doing this within m_setAppearanceLock since the queueing avoids | ||
432 | // multiple save requests. | ||
433 | SetAppearanceAssets(sp.UUID, sp.Appearance); | ||
434 | |||
419 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); | 435 | m_scene.AvatarService.SetAppearance(agentid, sp.Appearance); |
420 | } | 436 | } |
421 | 437 | ||
@@ -467,7 +483,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
467 | return; | 483 | return; |
468 | } | 484 | } |
469 | 485 | ||
470 | // m_log.WarnFormat("[AVFACTORY]: Received request for wearables of {0}", client.AgentId); | 486 | // m_log.DebugFormat("[AVFACTORY]: Received request for wearables of {0}", client.Name); |
471 | 487 | ||
472 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); | 488 | client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial++); |
473 | } | 489 | } |
@@ -502,9 +518,6 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
502 | 518 | ||
503 | avatAppearance.GetAssetsFrom(sp.Appearance); | 519 | avatAppearance.GetAssetsFrom(sp.Appearance); |
504 | 520 | ||
505 | // This could take awhile since it needs to pull inventory | ||
506 | SetAppearanceAssets(sp.UUID, ref avatAppearance); | ||
507 | |||
508 | lock (m_setAppearanceLock) | 521 | lock (m_setAppearanceLock) |
509 | { | 522 | { |
510 | // Update only those fields that we have changed. This is important because the viewer | 523 | // Update only those fields that we have changed. This is important because the viewer |
@@ -538,7 +551,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory | |||
538 | return true; | 551 | return true; |
539 | } | 552 | } |
540 | 553 | ||
541 | private void SetAppearanceAssets(UUID userID, ref AvatarAppearance appearance) | 554 | private void SetAppearanceAssets(UUID userID, AvatarAppearance appearance) |
542 | { | 555 | { |
543 | IInventoryService invService = m_scene.InventoryService; | 556 | IInventoryService invService = m_scene.InventoryService; |
544 | 557 | ||
diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs index 7753c25..d294692 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/HGMessageTransferModule.cs | |||
@@ -24,6 +24,7 @@ | |||
24 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS | 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. | 25 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
26 | */ | 26 | */ |
27 | |||
27 | using System; | 28 | using System; |
28 | using System.Collections; | 29 | using System.Collections; |
29 | using System.Collections.Generic; | 30 | using System.Collections.Generic; |
@@ -145,14 +146,14 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
145 | scene.Entities[toAgentID] is ScenePresence) | 146 | scene.Entities[toAgentID] is ScenePresence) |
146 | { | 147 | { |
147 | // m_log.DebugFormat( | 148 | // m_log.DebugFormat( |
148 | // "[INSTANT MESSAGE]: Looking for root agent {0} in {1}", | 149 | // "[HG INSTANT MESSAGE]: Looking for root agent {0} in {1}", |
149 | // toAgentID.ToString(), scene.RegionInfo.RegionName); | 150 | // toAgentID.ToString(), scene.RegionInfo.RegionName); |
150 | 151 | ||
151 | ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; | 152 | ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; |
152 | if (!user.IsChildAgent) | 153 | if (!user.IsChildAgent) |
153 | { | 154 | { |
154 | // Local message | 155 | // Local message |
155 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); | 156 | // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to root agent {0} {1}", user.Name, toAgentID); |
156 | user.ControllingClient.SendInstantMessage(im); | 157 | user.ControllingClient.SendInstantMessage(im); |
157 | 158 | ||
158 | // Message sent | 159 | // Message sent |
@@ -166,7 +167,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
166 | foreach (Scene scene in m_Scenes) | 167 | foreach (Scene scene in m_Scenes) |
167 | { | 168 | { |
168 | // m_log.DebugFormat( | 169 | // m_log.DebugFormat( |
169 | // "[INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); | 170 | // "[HG INSTANT MESSAGE]: Looking for child of {0} in {1}", toAgentID, scene.RegionInfo.RegionName); |
170 | 171 | ||
171 | if (scene.Entities.ContainsKey(toAgentID) && | 172 | if (scene.Entities.ContainsKey(toAgentID) && |
172 | scene.Entities[toAgentID] is ScenePresence) | 173 | scene.Entities[toAgentID] is ScenePresence) |
@@ -174,7 +175,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
174 | // Local message | 175 | // Local message |
175 | ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; | 176 | ScenePresence user = (ScenePresence) scene.Entities[toAgentID]; |
176 | 177 | ||
177 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); | 178 | // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to child agent {0} {1}", user.Name, toAgentID); |
178 | user.ControllingClient.SendInstantMessage(im); | 179 | user.ControllingClient.SendInstantMessage(im); |
179 | 180 | ||
180 | // Message sent | 181 | // Message sent |
@@ -183,7 +184,7 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage | |||
183 | } | 184 | } |
184 | } | 185 | } |
185 | 186 | ||
186 | // m_log.DebugFormat("[INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); | 187 | // m_log.DebugFormat("[HG INSTANT MESSAGE]: Delivering IM to {0} via XMLRPC", im.toAgentID); |
187 | // Is the user a local user? | 188 | // Is the user a local user? |
188 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); | 189 | UserAccount account = m_Scenes[0].UserAccountService.GetUserAccount(m_Scenes[0].RegionInfo.ScopeID, toAgentID); |
189 | string url = string.Empty; | 190 | string url = string.Empty; |
diff --git a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs index d687e6a..bc5c1ff 100644 --- a/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Lure/HGLureModule.cs | |||
@@ -154,14 +154,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
154 | if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) | 154 | if (im.dialog == (byte)InstantMessageDialog.RequestTeleport) |
155 | { | 155 | { |
156 | UUID sessionID = new UUID(im.imSessionID); | 156 | UUID sessionID = new UUID(im.imSessionID); |
157 | m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); | 157 | |
158 | m_PendingLures.Add(sessionID, im, 7200); // 2 hours | 158 | if (!m_PendingLures.Contains(sessionID)) |
159 | { | ||
160 | m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", im.imSessionID, im.RegionID, im.message); | ||
161 | m_PendingLures.Add(sessionID, im, 7200); // 2 hours | ||
162 | } | ||
159 | 163 | ||
160 | // Forward. We do this, because the IM module explicitly rejects | 164 | // Forward. We do this, because the IM module explicitly rejects |
161 | // IMs of this type | 165 | // IMs of this type |
162 | if (m_TransferModule != null) | 166 | if (m_TransferModule != null) |
163 | m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); | 167 | m_TransferModule.SendInstantMessage(im, delegate(bool success) { }); |
164 | |||
165 | } | 168 | } |
166 | } | 169 | } |
167 | 170 | ||
@@ -177,12 +180,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Lure | |||
177 | 180 | ||
178 | m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); | 181 | m_log.DebugFormat("[HG LURE MODULE]: TP invite with message {0}", message); |
179 | 182 | ||
183 | UUID sessionID = UUID.Random(); | ||
184 | |||
180 | GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, | 185 | GridInstantMessage m = new GridInstantMessage(scene, client.AgentId, |
181 | client.FirstName+" "+client.LastName, targetid, | 186 | client.FirstName+" "+client.LastName, targetid, |
182 | (byte)InstantMessageDialog.RequestTeleport, false, | 187 | (byte)InstantMessageDialog.RequestTeleport, false, |
183 | message, UUID.Random(), false, presence.AbsolutePosition, | 188 | message, sessionID, false, presence.AbsolutePosition, |
184 | new Byte[0]); | 189 | new Byte[0]); |
185 | m.RegionID = client.Scene.RegionInfo.RegionID.Guid; | 190 | m.RegionID = client.Scene.RegionInfo.RegionID.Guid; |
191 | |||
192 | m_log.DebugFormat("[HG LURE MODULE]: RequestTeleport sessionID={0}, regionID={1}, message={2}", m.imSessionID, m.RegionID, m.message); | ||
193 | m_PendingLures.Add(sessionID, m, 7200); // 2 hours | ||
186 | 194 | ||
187 | if (m_TransferModule != null) | 195 | if (m_TransferModule != null) |
188 | { | 196 | { |
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ac13d5e..8924c0a 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs | |||
@@ -59,7 +59,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
59 | get { return m_MaxTransferDistance; } | 59 | get { return m_MaxTransferDistance; } |
60 | set { m_MaxTransferDistance = value; } | 60 | set { m_MaxTransferDistance = value; } |
61 | } | 61 | } |
62 | |||
63 | 62 | ||
64 | protected bool m_Enabled = false; | 63 | protected bool m_Enabled = false; |
65 | protected Scene m_aScene; | 64 | protected Scene m_aScene; |
@@ -68,7 +67,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
68 | private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = | 67 | private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = |
69 | new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); | 68 | new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); |
70 | 69 | ||
71 | |||
72 | #region ISharedRegionModule | 70 | #region ISharedRegionModule |
73 | 71 | ||
74 | public Type ReplaceableInterface | 72 | public Type ReplaceableInterface |
@@ -329,6 +327,11 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
329 | if (sp.ParentID != (uint)0) | 327 | if (sp.ParentID != (uint)0) |
330 | sp.StandUp(); | 328 | sp.StandUp(); |
331 | 329 | ||
330 | if (!sp.ValidateAttachments()) | ||
331 | m_log.DebugFormat( | ||
332 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.", | ||
333 | sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName); | ||
334 | |||
332 | // if (!sp.ValidateAttachments()) | 335 | // if (!sp.ValidateAttachments()) |
333 | // { | 336 | // { |
334 | // sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); | 337 | // sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); |
@@ -939,7 +942,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
939 | /// This Closes child agents on neighbouring regions | 942 | /// This Closes child agents on neighbouring regions |
940 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. | 943 | /// Calls an asynchronous method to do so.. so it doesn't lag the sim. |
941 | /// </summary> | 944 | /// </summary> |
942 | protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) | 945 | protected ScenePresence CrossAgentToNewRegionAsync( |
946 | ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, | ||
947 | bool isFlying, string version) | ||
943 | { | 948 | { |
944 | ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); | 949 | ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); |
945 | 950 | ||
@@ -949,7 +954,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer | |||
949 | 954 | ||
950 | if (neighbourRegion != null) | 955 | if (neighbourRegion != null) |
951 | { | 956 | { |
952 | agent.ValidateAttachments(); | 957 | if (!agent.ValidateAttachments()) |
958 | m_log.DebugFormat( | ||
959 | "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.", | ||
960 | agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName); | ||
953 | 961 | ||
954 | pos = pos + (agent.Velocity); | 962 | pos = pos + (agent.Velocity); |
955 | 963 | ||
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs index f7003db..bef0d69 100644 --- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs +++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs | |||
@@ -363,9 +363,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement | |||
363 | lock (m_UserCache) | 363 | lock (m_UserCache) |
364 | m_UserCache[user.Id] = user; | 364 | m_UserCache[user.Id] = user; |
365 | 365 | ||
366 | m_log.DebugFormat( | 366 | // m_log.DebugFormat( |
367 | "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", | 367 | // "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", |
368 | user.Id, user.FirstName, user.LastName, user.HomeURL); | 368 | // user.Id, user.FirstName, user.LastName, user.HomeURL); |
369 | } | 369 | } |
370 | 370 | ||
371 | //public void AddUser(UUID uuid, string userData) | 371 | //public void AddUser(UUID uuid, string userData) |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs index 1c83f8e..097ff1a 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs | |||
@@ -185,15 +185,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
185 | public InventoryCollection GetFolderContent(UUID userID, UUID folderID) | 185 | public InventoryCollection GetFolderContent(UUID userID, UUID folderID) |
186 | { | 186 | { |
187 | InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID); | 187 | InventoryCollection invCol = m_InventoryService.GetFolderContent(userID, folderID); |
188 | Util.FireAndForget(delegate | 188 | |
189 | if (UserManager != null) | ||
189 | { | 190 | { |
190 | if (UserManager != null) | 191 | // Protect ourselves against the caller subsequently modifying the items list |
192 | List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items); | ||
193 | |||
194 | Util.FireAndForget(delegate | ||
191 | { | 195 | { |
192 | // Protect ourselves against the caller subsequently modifying the items list | 196 | foreach (InventoryItemBase item in items) |
193 | foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items)) | ||
194 | UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); | 197 | UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); |
195 | } | 198 | }); |
196 | }); | 199 | } |
197 | 200 | ||
198 | return invCol; | 201 | return invCol; |
199 | } | 202 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs index c9c716c..73ab4e3 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs | |||
@@ -193,15 +193,18 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory | |||
193 | public InventoryCollection GetFolderContent(UUID userID, UUID folderID) | 193 | public InventoryCollection GetFolderContent(UUID userID, UUID folderID) |
194 | { | 194 | { |
195 | InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); | 195 | InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); |
196 | Util.FireAndForget(delegate | 196 | |
197 | if (UserManager != null) | ||
197 | { | 198 | { |
198 | if (UserManager != null) | 199 | // Protect ourselves against the caller subsequently modifying the items list |
200 | List<InventoryItemBase> items = new List<InventoryItemBase>(invCol.Items); | ||
201 | |||
202 | Util.FireAndForget(delegate | ||
199 | { | 203 | { |
200 | // Protect ourselves against the caller subsequently modifying the items list | 204 | foreach (InventoryItemBase item in items) |
201 | foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items)) | ||
202 | UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); | 205 | UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); |
203 | } | 206 | }); |
204 | }); | 207 | } |
205 | 208 | ||
206 | return invCol; | 209 | return invCol; |
207 | } | 210 | } |
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs index 30ebb21..0a0ce3c 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/LocalUserAccountServiceConnector.cs | |||
@@ -45,7 +45,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts | |||
45 | LogManager.GetLogger( | 45 | LogManager.GetLogger( |
46 | MethodBase.GetCurrentMethod().DeclaringType); | 46 | MethodBase.GetCurrentMethod().DeclaringType); |
47 | 47 | ||
48 | private IUserAccountService m_UserService; | 48 | /// <summary> |
49 | /// This is not on the IUserAccountService. It's only being used so that standalone scenes can punch through | ||
50 | /// to a local UserAccountService when setting up an estate manager. | ||
51 | /// </summary> | ||
52 | public IUserAccountService UserAccountService { get; private set; } | ||
53 | |||
49 | private UserAccountCache m_Cache; | 54 | private UserAccountCache m_Cache; |
50 | 55 | ||
51 | private bool m_Enabled = false; | 56 | private bool m_Enabled = false; |
@@ -86,9 +91,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts | |||
86 | } | 91 | } |
87 | 92 | ||
88 | Object[] args = new Object[] { source }; | 93 | Object[] args = new Object[] { source }; |
89 | m_UserService = ServerUtils.LoadPlugin<IUserAccountService>(serviceDll, args); | 94 | UserAccountService = ServerUtils.LoadPlugin<IUserAccountService>(serviceDll, args); |
90 | 95 | ||
91 | if (m_UserService == null) | 96 | if (UserAccountService == null) |
92 | { | 97 | { |
93 | m_log.ErrorFormat( | 98 | m_log.ErrorFormat( |
94 | "[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll); | 99 | "[LOCAL USER ACCOUNT SERVICE CONNECTOR]: Cannot load user account service specified as {0}", serviceDll); |
@@ -119,7 +124,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts | |||
119 | if (!m_Enabled) | 124 | if (!m_Enabled) |
120 | return; | 125 | return; |
121 | 126 | ||
122 | scene.RegisterModuleInterface<IUserAccountService>(m_UserService); | 127 | // FIXME: Why do we bother setting this module and caching up if we just end up registering the inner |
128 | // user account service?! | ||
129 | scene.RegisterModuleInterface<IUserAccountService>(UserAccountService); | ||
123 | } | 130 | } |
124 | 131 | ||
125 | public void RemoveRegion(Scene scene) | 132 | public void RemoveRegion(Scene scene) |
@@ -147,7 +154,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts | |||
147 | if (inCache) | 154 | if (inCache) |
148 | return account; | 155 | return account; |
149 | 156 | ||
150 | account = m_UserService.GetUserAccount(scopeID, userID); | 157 | account = UserAccountService.GetUserAccount(scopeID, userID); |
151 | m_Cache.Cache(userID, account); | 158 | m_Cache.Cache(userID, account); |
152 | 159 | ||
153 | return account; | 160 | return account; |
@@ -160,7 +167,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts | |||
160 | if (inCache) | 167 | if (inCache) |
161 | return account; | 168 | return account; |
162 | 169 | ||
163 | account = m_UserService.GetUserAccount(scopeID, firstName, lastName); | 170 | account = UserAccountService.GetUserAccount(scopeID, firstName, lastName); |
164 | if (account != null) | 171 | if (account != null) |
165 | m_Cache.Cache(account.PrincipalID, account); | 172 | m_Cache.Cache(account.PrincipalID, account); |
166 | 173 | ||
@@ -169,22 +176,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts | |||
169 | 176 | ||
170 | public UserAccount GetUserAccount(UUID scopeID, string Email) | 177 | public UserAccount GetUserAccount(UUID scopeID, string Email) |
171 | { | 178 | { |
172 | return m_UserService.GetUserAccount(scopeID, Email); | 179 | return UserAccountService.GetUserAccount(scopeID, Email); |
173 | } | 180 | } |
174 | 181 | ||
175 | public List<UserAccount> GetUserAccounts(UUID scopeID, string query) | 182 | public List<UserAccount> GetUserAccounts(UUID scopeID, string query) |
176 | { | 183 | { |
177 | return m_UserService.GetUserAccounts(scopeID, query); | 184 | return UserAccountService.GetUserAccounts(scopeID, query); |
178 | } | 185 | } |
179 | 186 | ||
180 | // Update all updatable fields | 187 | // Update all updatable fields |
181 | // | 188 | // |
182 | public bool StoreUserAccount(UserAccount data) | 189 | public bool StoreUserAccount(UserAccount data) |
183 | { | 190 | { |
184 | return m_UserService.StoreUserAccount(data); | 191 | return UserAccountService.StoreUserAccount(data); |
185 | } | 192 | } |
186 | 193 | ||
187 | #endregion | 194 | #endregion |
188 | |||
189 | } | 195 | } |
190 | } | 196 | } \ No newline at end of file |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs index 48130e7..587d260 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs | |||
@@ -284,8 +284,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
284 | part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; | 284 | part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; |
285 | 285 | ||
286 | // And zap any troublesome sit target information | 286 | // And zap any troublesome sit target information |
287 | part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); | 287 | // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); |
288 | part.SitTargetPosition = new Vector3(0, 0, 0); | 288 | // part.SitTargetPosition = new Vector3(0, 0, 0); |
289 | 289 | ||
290 | // Fix ownership/creator of inventory items | 290 | // Fix ownership/creator of inventory items |
291 | // Not doing so results in inventory items | 291 | // Not doing so results in inventory items |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs index 10a83ee..b895afe 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs | |||
@@ -127,6 +127,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
127 | 127 | ||
128 | EntityBase[] entities = m_scene.GetEntities(); | 128 | EntityBase[] entities = m_scene.GetEntities(); |
129 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); | 129 | List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); |
130 | |||
131 | string checkPermissions = null; | ||
132 | int numObjectsSkippedPermissions = 0; | ||
133 | Object temp; | ||
134 | if (options.TryGetValue("checkPermissions", out temp)) | ||
135 | checkPermissions = (string)temp; | ||
130 | 136 | ||
131 | // Filter entities so that we only have scene objects. | 137 | // Filter entities so that we only have scene objects. |
132 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods | 138 | // FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods |
@@ -136,9 +142,19 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
136 | if (entity is SceneObjectGroup) | 142 | if (entity is SceneObjectGroup) |
137 | { | 143 | { |
138 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; | 144 | SceneObjectGroup sceneObject = (SceneObjectGroup)entity; |
139 | 145 | ||
140 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) | 146 | if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) |
141 | sceneObjects.Add((SceneObjectGroup)entity); | 147 | { |
148 | if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions)) | ||
149 | { | ||
150 | // The user isn't allowed to copy/transfer this object, so it will not be included in the OAR. | ||
151 | ++numObjectsSkippedPermissions; | ||
152 | } | ||
153 | else | ||
154 | { | ||
155 | sceneObjects.Add(sceneObject); | ||
156 | } | ||
157 | } | ||
142 | } | 158 | } |
143 | } | 159 | } |
144 | 160 | ||
@@ -159,7 +175,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
159 | { | 175 | { |
160 | m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); | 176 | m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); |
161 | } | 177 | } |
162 | 178 | ||
179 | if (numObjectsSkippedPermissions > 0) | ||
180 | { | ||
181 | m_log.DebugFormat( | ||
182 | "[ARCHIVER]: {0} scene objects skipped due to lack of permissions", | ||
183 | numObjectsSkippedPermissions); | ||
184 | } | ||
185 | |||
163 | // Make sure that we also request terrain texture assets | 186 | // Make sure that we also request terrain texture assets |
164 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; | 187 | RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; |
165 | 188 | ||
@@ -211,6 +234,83 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
211 | } | 234 | } |
212 | 235 | ||
213 | /// <summary> | 236 | /// <summary> |
237 | /// Checks whether the user has permission to export an object group to an OAR. | ||
238 | /// </summary> | ||
239 | /// <param name="user">The user</param> | ||
240 | /// <param name="objGroup">The object group</param> | ||
241 | /// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param> | ||
242 | /// <returns>Whether the user is allowed to export the object to an OAR</returns> | ||
243 | private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions) | ||
244 | { | ||
245 | if (checkPermissions == null) | ||
246 | return true; | ||
247 | |||
248 | IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>(); | ||
249 | if (module == null) | ||
250 | return true; // this shouldn't happen | ||
251 | |||
252 | // Check whether the user is permitted to export all of the parts in the SOG. If any | ||
253 | // part can't be exported then the entire SOG can't be exported. | ||
254 | |||
255 | bool permitted = true; | ||
256 | //int primNumber = 1; | ||
257 | |||
258 | foreach (SceneObjectPart obj in objGroup.Parts) | ||
259 | { | ||
260 | uint perm; | ||
261 | PermissionClass permissionClass = module.GetPermissionClass(user, obj); | ||
262 | switch (permissionClass) | ||
263 | { | ||
264 | case PermissionClass.Owner: | ||
265 | perm = obj.BaseMask; | ||
266 | break; | ||
267 | case PermissionClass.Group: | ||
268 | perm = obj.GroupMask | obj.EveryoneMask; | ||
269 | break; | ||
270 | case PermissionClass.Everyone: | ||
271 | default: | ||
272 | perm = obj.EveryoneMask; | ||
273 | break; | ||
274 | } | ||
275 | |||
276 | bool canCopy = (perm & (uint)PermissionMask.Copy) != 0; | ||
277 | bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0; | ||
278 | |||
279 | // Special case: if Everyone can copy the object then this implies it can also be | ||
280 | // Transferred. | ||
281 | // However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask | ||
282 | // always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer | ||
283 | // does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied. | ||
284 | if (permissionClass != PermissionClass.Owner) | ||
285 | { | ||
286 | canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0; | ||
287 | } | ||
288 | |||
289 | |||
290 | bool partPermitted = true; | ||
291 | if (checkPermissions.Contains("C") && !canCopy) | ||
292 | partPermitted = false; | ||
293 | if (checkPermissions.Contains("T") && !canTransfer) | ||
294 | partPermitted = false; | ||
295 | |||
296 | //string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount); | ||
297 | //m_log.DebugFormat("[ARCHIVER]: Object permissions: {0}: Base={1:X4}, Owner={2:X4}, Everyone={3:X4}, permissionClass={4}, checkPermissions={5}, canCopy={6}, canTransfer={7}, permitted={8}", | ||
298 | // name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask, | ||
299 | // permissionClass, checkPermissions, canCopy, canTransfer, permitted); | ||
300 | |||
301 | if (!partPermitted) | ||
302 | { | ||
303 | permitted = false; | ||
304 | break; | ||
305 | } | ||
306 | |||
307 | //++primNumber; | ||
308 | } | ||
309 | |||
310 | return permitted; | ||
311 | } | ||
312 | |||
313 | /// <summary> | ||
214 | /// Create the control file for the most up to date archive | 314 | /// Create the control file for the most up to date archive |
215 | /// </summary> | 315 | /// </summary> |
216 | /// <returns></returns> | 316 | /// <returns></returns> |
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs index 08eb80c..f44a3ba 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs | |||
@@ -128,6 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver | |||
128 | // ops.Add("v|version=", delegate(string v) { options["version"] = v; }); | 128 | // ops.Add("v|version=", delegate(string v) { options["version"] = v; }); |
129 | ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); | 129 | ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); |
130 | ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); | 130 | ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); |
131 | ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; }); | ||
131 | 132 | ||
132 | List<string> mainParams = ops.Parse(cmdparams); | 133 | List<string> mainParams = ops.Parse(cmdparams); |
133 | 134 | ||
diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index b185d9b..e798e5e 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs | |||
@@ -318,6 +318,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
318 | new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); | 318 | new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); |
319 | 319 | ||
320 | SceneObjectPart part1 = CreateSceneObjectPart1(); | 320 | SceneObjectPart part1 = CreateSceneObjectPart1(); |
321 | |||
322 | part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f); | ||
323 | part1.SitTargetPosition = new Vector3(1, 2, 3); | ||
324 | |||
321 | SceneObjectGroup object1 = new SceneObjectGroup(part1); | 325 | SceneObjectGroup object1 = new SceneObjectGroup(part1); |
322 | 326 | ||
323 | // Let's put some inventory items into our object | 327 | // Let's put some inventory items into our object |
@@ -390,6 +394,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests | |||
390 | object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); | 394 | object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); |
391 | Assert.That( | 395 | Assert.That( |
392 | object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); | 396 | object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); |
397 | Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation)); | ||
398 | Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition)); | ||
393 | 399 | ||
394 | TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; | 400 | TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; |
395 | Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); | 401 | Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); |
diff --git a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs index 94c1417..c199a77 100644 --- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs +++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs | |||
@@ -968,10 +968,10 @@ namespace OpenSim.Region.CoreModules.World.Estate | |||
968 | args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; | 968 | args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; |
969 | args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; | 969 | args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; |
970 | 970 | ||
971 | m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); | 971 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName); |
972 | m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); | 972 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName); |
973 | m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); | 973 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName); |
974 | m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); | 974 | // m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName); |
975 | 975 | ||
976 | remoteClient.SendRegionHandshake(Scene.RegionInfo,args); | 976 | remoteClient.SendRegionHandshake(Scene.RegionInfo,args); |
977 | } | 977 | } |
diff --git a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs index 8b78701..1e4f0a4 100644 --- a/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs +++ b/OpenSim/Region/CoreModules/World/Objects/BuySell/BuySellModule.cs | |||
@@ -101,7 +101,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell | |||
101 | 101 | ||
102 | part.ParentGroup.HasGroupChanged = true; | 102 | part.ParentGroup.HasGroupChanged = true; |
103 | 103 | ||
104 | part.GetProperties(client); | 104 | part.SendPropertiesToClient(client); |
105 | } | 105 | } |
106 | 106 | ||
107 | public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice) | 107 | public bool BuyObject(IClientAPI remoteClient, UUID categoryID, uint localID, byte saleType, int salePrice) |
@@ -142,7 +142,7 @@ namespace OpenSim.Region.CoreModules.World.Objects.BuySell | |||
142 | part.SalePrice = 10; | 142 | part.SalePrice = 10; |
143 | 143 | ||
144 | group.HasGroupChanged = true; | 144 | group.HasGroupChanged = true; |
145 | part.GetProperties(remoteClient); | 145 | part.SendPropertiesToClient(remoteClient); |
146 | part.TriggerScriptChangedEvent(Changed.OWNER); | 146 | part.TriggerScriptChangedEvent(Changed.OWNER); |
147 | group.ResumeScripts(); | 147 | group.ResumeScripts(); |
148 | part.ScheduleFullUpdate(); | 148 | part.ScheduleFullUpdate(); |
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs index b9bd9a4..3b661ed 100644 --- a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs +++ b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs | |||
@@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces; | |||
39 | 39 | ||
40 | namespace OpenSim.Region.CoreModules.World.Permissions | 40 | namespace OpenSim.Region.CoreModules.World.Permissions |
41 | { | 41 | { |
42 | public class PermissionsModule : IRegionModule | 42 | public class PermissionsModule : IRegionModule, IPermissionsModule |
43 | { | 43 | { |
44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | 44 | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); |
45 | 45 | ||
@@ -150,6 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
150 | else | 150 | else |
151 | m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); | 151 | m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); |
152 | 152 | ||
153 | scene.RegisterModuleInterface<IPermissionsModule>(this); | ||
154 | |||
153 | //Register functions with Scene External Checks! | 155 | //Register functions with Scene External Checks! |
154 | m_scene.Permissions.OnBypassPermissions += BypassPermissions; | 156 | m_scene.Permissions.OnBypassPermissions += BypassPermissions; |
155 | m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; | 157 | m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; |
@@ -574,46 +576,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
574 | if (objectOwner != UUID.Zero) | 576 | if (objectOwner != UUID.Zero) |
575 | objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; | 577 | objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; |
576 | 578 | ||
577 | if (m_bypassPermissions) | 579 | PermissionClass permissionClass = GetPermissionClass(user, task); |
578 | return objectOwnerMask; | ||
579 | |||
580 | // Object owners should be able to edit their own content | ||
581 | if (user == objectOwner) | ||
582 | return objectOwnerMask; | ||
583 | |||
584 | if (IsFriendWithPerms(user, objectOwner)) | ||
585 | { | ||
586 | return objectOwnerMask; | ||
587 | } | ||
588 | // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set | ||
589 | if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) | ||
590 | { | ||
591 | return objectOwnerMask; | ||
592 | } | ||
593 | |||
594 | // Admin should be able to edit anything in the sim (including admin objects) | ||
595 | if (IsAdministrator(user)) | ||
596 | { | ||
597 | return objectOwnerMask; | ||
598 | } | ||
599 | 580 | ||
600 | // Users should be able to edit what is over their land. | 581 | switch (permissionClass) |
601 | Vector3 taskPos = task.AbsolutePosition; | ||
602 | ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); | ||
603 | if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod) | ||
604 | { | 582 | { |
605 | // Admin objects should not be editable by the above | 583 | case PermissionClass.Owner: |
606 | if (!IsAdministrator(objectOwner)) | ||
607 | { | ||
608 | return objectOwnerMask; | 584 | return objectOwnerMask; |
609 | } | 585 | case PermissionClass.Group: |
586 | return objectGroupMask | objectEveryoneMask; | ||
587 | case PermissionClass.Everyone: | ||
588 | default: | ||
589 | return objectEveryoneMask; | ||
610 | } | 590 | } |
611 | |||
612 | // Group permissions | ||
613 | if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0)) | ||
614 | return objectGroupMask | objectEveryoneMask; | ||
615 | |||
616 | return objectEveryoneMask; | ||
617 | } | 591 | } |
618 | 592 | ||
619 | private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) | 593 | private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) |
@@ -644,6 +618,47 @@ namespace OpenSim.Region.CoreModules.World.Permissions | |||
644 | return objectFlagsMask; | 618 | return objectFlagsMask; |
645 | } | 619 | } |
646 | 620 | ||
621 | public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj) | ||
622 | { | ||
623 | if (obj == null) | ||
624 | return PermissionClass.Everyone; | ||
625 | |||
626 | if (m_bypassPermissions) | ||
627 | return PermissionClass.Owner; | ||
628 | |||
629 | // Object owners should be able to edit their own content | ||
630 | UUID objectOwner = obj.OwnerID; | ||
631 | if (user == objectOwner) | ||
632 | return PermissionClass.Owner; | ||
633 | |||
634 | if (IsFriendWithPerms(user, objectOwner)) | ||
635 | return PermissionClass.Owner; | ||
636 | |||
637 | // Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set | ||
638 | if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner)) | ||
639 | return PermissionClass.Owner; | ||
640 | |||
641 | // Admin should be able to edit anything in the sim (including admin objects) | ||
642 | if (IsAdministrator(user)) | ||
643 | return PermissionClass.Owner; | ||
644 | |||
645 | // Users should be able to edit what is over their land. | ||
646 | Vector3 taskPos = obj.AbsolutePosition; | ||
647 | ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y); | ||
648 | if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod) | ||
649 | { | ||
650 | // Admin objects should not be editable by the above | ||
651 | if (!IsAdministrator(objectOwner)) | ||
652 | return PermissionClass.Owner; | ||
653 | } | ||
654 | |||
655 | // Group permissions | ||
656 | if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0)) | ||
657 | return PermissionClass.Group; | ||
658 | |||
659 | return PermissionClass.Everyone; | ||
660 | } | ||
661 | |||
647 | /// <summary> | 662 | /// <summary> |
648 | /// General permissions checks for any operation involving an object. These supplement more specific checks | 663 | /// General permissions checks for any operation involving an object. These supplement more specific checks |
649 | /// implemented by callers. | 664 | /// implemented by callers. |