Annotation of /branches/os-0.6.9-post-fixes/ModularRex/RexParts/RexObjRez.cs
Parent Directory
|
Revision Log
Revision 341 - (view) (download)
| 1 : | mikkopa | 137 | using System; |
| 2 : | using System.Collections.Generic; | ||
| 3 : | using System.Text; | ||
| 4 : | using OpenSim.Region.Framework.Interfaces; | ||
| 5 : | using OpenSim.Region.Framework.Scenes; | ||
| 6 : | using OpenSim.Framework; | ||
| 7 : | using OpenMetaverse; | ||
| 8 : | using log4net; | ||
| 9 : | using System.Reflection; | ||
| 10 : | using OpenSim.Framework.Communications.Cache; | ||
| 11 : | using ModularRex.RexFramework; | ||
| 12 : | mikkopa | 142 | using System.Timers; |
| 13 : | mikkopa | 137 | |
| 14 : | namespace ModularRex.RexParts | ||
| 15 : | { | ||
| 16 : | public class RexObjectRezModule : IRegionModule | ||
| 17 : | { | ||
| 18 : | private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); | ||
| 19 : | |||
| 20 : | private Scene m_scene; | ||
| 21 : | private ModrexObjects m_rexObjects; | ||
| 22 : | |||
| 23 : | mikkopa | 142 | /// <value> |
| 24 : | /// Is the deleter currently enabled? | ||
| 25 : | /// </value> | ||
| 26 : | public bool DeleterEnabled; | ||
| 27 : | |||
| 28 : | private Timer m_inventoryTicker = new Timer(2000); | ||
| 29 : | private readonly Queue<DeleteToInventoryHolder> m_inventoryDeletes = new Queue<DeleteToInventoryHolder>(); | ||
| 30 : | |||
| 31 : | mikkopa | 137 | #region IRegionModule Members |
| 32 : | |||
| 33 : | public void Close() | ||
| 34 : | { | ||
| 35 : | } | ||
| 36 : | |||
| 37 : | public void Initialise(Scene scene, Nini.Config.IConfigSource source) | ||
| 38 : | { | ||
| 39 : | m_scene = scene; | ||
| 40 : | } | ||
| 41 : | |||
| 42 : | public bool IsSharedModule | ||
| 43 : | { | ||
| 44 : | get { return false; } | ||
| 45 : | } | ||
| 46 : | |||
| 47 : | public string Name | ||
| 48 : | { | ||
| 49 : | get { return "RexObjectRezModule"; } | ||
| 50 : | } | ||
| 51 : | |||
| 52 : | public void PostInitialise() | ||
| 53 : | { | ||
| 54 : | mikkopa | 142 | m_inventoryTicker.AutoReset = false; |
| 55 : | m_inventoryTicker.Elapsed += InventoryRunDeleteTimer; | ||
| 56 : | |||
| 57 : | mikkopa | 137 | m_scene.EventManager.OnNewClient += HandleNewClient; |
| 58 : | |||
| 59 : | OpenSim.Region.Framework.Interfaces.IRegionModule module = m_scene.Modules["RexObjectsModule"]; | ||
| 60 : | if (module != null && module is ModrexObjects) | ||
| 61 : | { | ||
| 62 : | m_rexObjects = (ModrexObjects)module; | ||
| 63 : | } | ||
| 64 : | mikkopa | 142 | DeleterEnabled = true; |
| 65 : | mikkopa | 137 | } |
| 66 : | |||
| 67 : | mikkopa | 142 | #endregion |
| 68 : | |||
| 69 : | #region Event Handlers | ||
| 70 : | |||
| 71 : | mikkopa | 137 | private void HandleNewClient(IClientAPI client) |
| 72 : | { | ||
| 73 : | //Do these to all clients | ||
| 74 : | //Other clients might accidentially take object with rex properties | ||
| 75 : | //They also might rez in back again | ||
| 76 : | |||
| 77 : | ScenePresence avatar = m_scene.GetScenePresence(client.AgentId); | ||
| 78 : | if (avatar != null) | ||
| 79 : | { | ||
| 80 : | avatar.ControllingClient.OnRezObject -= avatar.Scene.RezObject; | ||
| 81 : | avatar.ControllingClient.OnDeRezObject -= avatar.Scene.DeRezObject; | ||
| 82 : | avatar.ControllingClient.OnRezObject += ClientRezObject; | ||
| 83 : | mikkopa | 201 | avatar.ControllingClient.OnDeRezObject += DeRezObj; |
| 84 : | mikkopa | 137 | } |
| 85 : | } | ||
| 86 : | |||
| 87 : | mikkopa | 201 | private void DeRezObj(IClientAPI remoteClient, List<uint> localIDs, UUID groupID, DeRezAction action, UUID destinationID) |
| 88 : | { | ||
| 89 : | foreach (uint id in localIDs) | ||
| 90 : | { | ||
| 91 : | ClientDeRezObject(remoteClient, id, groupID, action, destinationID); | ||
| 92 : | } | ||
| 93 : | } | ||
| 94 : | |||
| 95 : | mikkopa | 137 | private void ClientDeRezObject(IClientAPI remoteClient, uint localID, UUID groupID, DeRezAction action, UUID destinationID) |
| 96 : | { | ||
| 97 : | SceneObjectPart part = m_scene.GetSceneObjectPart(localID); | ||
| 98 : | if (part == null) | ||
| 99 : | return; | ||
| 100 : | |||
| 101 : | if (part.ParentGroup == null || part.ParentGroup.IsDeleted) | ||
| 102 : | return; | ||
| 103 : | |||
| 104 : | // Can't delete child prims | ||
| 105 : | if (part != part.ParentGroup.RootPart) | ||
| 106 : | return; | ||
| 107 : | |||
| 108 : | SceneObjectGroup grp = part.ParentGroup; | ||
| 109 : | |||
| 110 : | //force a database backup/update on this SceneObjectGroup | ||
| 111 : | //So that we know the database is upto date, for when deleting the object from it | ||
| 112 : | m_scene.ForceSceneObjectBackup(grp); | ||
| 113 : | |||
| 114 : | bool permissionToTake = false; | ||
| 115 : | bool permissionToDelete = false; | ||
| 116 : | |||
| 117 : | if (action == DeRezAction.SaveToExistingUserInventoryItem) | ||
| 118 : | { | ||
| 119 : | if (grp.OwnerID == remoteClient.AgentId && grp.RootPart.FromUserInventoryItemID != UUID.Zero) | ||
| 120 : | { | ||
| 121 : | permissionToTake = true; | ||
| 122 : | permissionToDelete = false; | ||
| 123 : | } | ||
| 124 : | } | ||
| 125 : | else if (action == DeRezAction.TakeCopy) | ||
| 126 : | { | ||
| 127 : | permissionToTake = | ||
| 128 : | m_scene.Permissions.CanTakeCopyObject( | ||
| 129 : | grp.UUID, | ||
| 130 : | remoteClient.AgentId); | ||
| 131 : | } | ||
| 132 : | else if (action == DeRezAction.GodTakeCopy) | ||
| 133 : | { | ||
| 134 : | permissionToTake = | ||
| 135 : | m_scene.Permissions.IsGod( | ||
| 136 : | remoteClient.AgentId); | ||
| 137 : | } | ||
| 138 : | else if (action == DeRezAction.Take) | ||
| 139 : | { | ||
| 140 : | permissionToTake = | ||
| 141 : | m_scene.Permissions.CanTakeObject( | ||
| 142 : | grp.UUID, | ||
| 143 : | remoteClient.AgentId); | ||
| 144 : | |||
| 145 : | //If they can take, they can delete! | ||
| 146 : | permissionToDelete = permissionToTake; | ||
| 147 : | } | ||
| 148 : | else if (action == DeRezAction.Delete) | ||
| 149 : | { | ||
| 150 : | permissionToTake = | ||
| 151 : | m_scene.Permissions.CanDeleteObject( | ||
| 152 : | grp.UUID, | ||
| 153 : | remoteClient.AgentId); | ||
| 154 : | permissionToDelete = permissionToTake; | ||
| 155 : | } | ||
| 156 : | else if (action == DeRezAction.Return) | ||
| 157 : | { | ||
| 158 : | if (remoteClient != null) | ||
| 159 : | { | ||
| 160 : | permissionToTake = | ||
| 161 : | m_scene.Permissions.CanReturnObject( | ||
| 162 : | grp.UUID, | ||
| 163 : | remoteClient.AgentId); | ||
| 164 : | permissionToDelete = permissionToTake; | ||
| 165 : | |||
| 166 : | if (permissionToDelete) | ||
| 167 : | { | ||
| 168 : | m_scene.AddReturn(grp.OwnerID, grp.Name, grp.AbsolutePosition, "parcel owner return"); | ||
| 169 : | } | ||
| 170 : | } | ||
| 171 : | else // Auto return passes through here with null agent | ||
| 172 : | { | ||
| 173 : | permissionToTake = true; | ||
| 174 : | permissionToDelete = true; | ||
| 175 : | } | ||
| 176 : | } | ||
| 177 : | else | ||
| 178 : | { | ||
| 179 : | m_log.DebugFormat( | ||
| 180 : | "[AGENT INVENTORY]: Ignoring unexpected derez action {0} for {1}", action, remoteClient.Name); | ||
| 181 : | return; | ||
| 182 : | } | ||
| 183 : | |||
| 184 : | if (permissionToTake) | ||
| 185 : | { | ||
| 186 : | mikkopa | 142 | |
| 187 : | DeleteToInventory(action, destinationID, grp, remoteClient, permissionToDelete); | ||
| 188 : | |||
| 189 : | ////TODO: Change this to some kind of async queue | ||
| 190 : | ////The queue was orginally introduced in OpenSim revision 5346: | ||
| 191 : | //// * Moves sending items to inventory via a delete into a seperate thread (this thread | ||
| 192 : | //// can be expanded to support all sends to inventory from inworld easily enough). | ||
| 193 : | //// Thread is temporary and only exists while items are being returned. | ||
| 194 : | //// * This should remove the "lag" caused by deleting many objects. | ||
| 195 : | //// * Patch brought to you by Joshua Nightshade's bitching at me to fix it. | ||
| 196 : | //UUID assetId = m_scene.DeleteToInventory(action, destinationID, grp, remoteClient); | ||
| 197 : | mikkopa | 137 | |
| 198 : | mikkopa | 142 | ////Get the item id of the asset so the RexObjectProperties can be changed to that id |
| 199 : | //CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(remoteClient.AgentId); | ||
| 200 : | //InventoryItemBase item = userInfo.RootFolder.FindAsset(assetId); | ||
| 201 : | mikkopa | 137 | |
| 202 : | mikkopa | 142 | ////Clone the old properties |
| 203 : | //if (m_rexObjects != null) | ||
| 204 : | //{ | ||
| 205 : | // RexObjectProperties origprops = m_rexObjects.GetObject(part.UUID); | ||
| 206 : | // RexObjectProperties cloneprops = m_rexObjects.GetObject(item.ID); | ||
| 207 : | mikkopa | 137 | |
| 208 : | mikkopa | 142 | // cloneprops.SetRexPrimDataFromObject(origprops); |
| 209 : | //} | ||
| 210 : | mikkopa | 137 | |
| 211 : | mikkopa | 142 | //if (permissionToDelete) |
| 212 : | //{ | ||
| 213 : | // grp.DeleteGroup(false); | ||
| 214 : | //} | ||
| 215 : | mikkopa | 137 | |
| 216 : | } | ||
| 217 : | else if (permissionToDelete) | ||
| 218 : | { | ||
| 219 : | m_scene.DeleteSceneObject(grp, false); | ||
| 220 : | } | ||
| 221 : | } | ||
| 222 : | |||
| 223 : | private void ClientRezObject(IClientAPI remoteClient, UUID itemID, Vector3 RayEnd, Vector3 RayStart, UUID RayTargetID, | ||
| 224 : | byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID) | ||
| 225 : | { | ||
| 226 : | SceneObjectGroup group = m_scene.RezObject(remoteClient, itemID, RayEnd, RayStart, RayTargetID, | ||
| 227 : | BypassRayCast, RayEndIsIntersection, RezSelected, RemoveItem, fromTaskID, false); | ||
| 228 : | |||
| 229 : | RexObjectProperties robj = m_rexObjects.GetObject(group.RootPart.FromUserInventoryItemID); | ||
| 230 : | RexObjectProperties newprops = m_rexObjects.GetObject(group.RootPart.UUID); | ||
| 231 : | newprops.SetRexPrimDataFromObject(robj); | ||
| 232 : | } | ||
| 233 : | |||
| 234 : | #endregion | ||
| 235 : | mikkopa | 142 | |
| 236 : | #region AsyncSceneObjectGroupDeleter | ||
| 237 : | |||
| 238 : | /// <summary> | ||
| 239 : | /// Delete the given object from the scene | ||
| 240 : | /// </summary> | ||
| 241 : | public void DeleteToInventory(DeRezAction action, UUID folderID, | ||
| 242 : | SceneObjectGroup objectGroup, IClientAPI remoteClient, | ||
| 243 : | bool permissionToDelete) | ||
| 244 : | { | ||
| 245 : | if (DeleterEnabled) | ||
| 246 : | m_inventoryTicker.Stop(); | ||
| 247 : | |||
| 248 : | lock (m_inventoryDeletes) | ||
| 249 : | { | ||
| 250 : | DeleteToInventoryHolder dtis = new DeleteToInventoryHolder(); | ||
| 251 : | dtis.action = action; | ||
| 252 : | dtis.folderID = folderID; | ||
| 253 : | dtis.objectGroup = objectGroup; | ||
| 254 : | dtis.remoteClient = remoteClient; | ||
| 255 : | dtis.permissionToDelete = permissionToDelete; | ||
| 256 : | |||
| 257 : | m_inventoryDeletes.Enqueue(dtis); | ||
| 258 : | } | ||
| 259 : | |||
| 260 : | if (DeleterEnabled) | ||
| 261 : | m_inventoryTicker.Start(); | ||
| 262 : | |||
| 263 : | // Visually remove it, even if it isnt really gone yet. This means that if we crash before the object | ||
| 264 : | // has gone to inventory, it will reappear in the region again on restart instead of being lost. | ||
| 265 : | // This is not ideal since the object will still be available for manipulation when it should be, but it's | ||
| 266 : | // better than losing the object for now. | ||
| 267 : | if (permissionToDelete) | ||
| 268 : | objectGroup.DeleteGroup(false); | ||
| 269 : | } | ||
| 270 : | |||
| 271 : | private void InventoryRunDeleteTimer(object sender, ElapsedEventArgs e) | ||
| 272 : | { | ||
| 273 : | m_log.Debug("[SCENE]: Starting send to inventory loop"); | ||
| 274 : | |||
| 275 : | while (InventoryDeQueueAndDelete()) | ||
| 276 : | { | ||
| 277 : | m_log.Debug("[SCENE]: Sent item successfully to inventory, continuing..."); | ||
| 278 : | } | ||
| 279 : | } | ||
| 280 : | |||
| 281 : | /// <summary> | ||
| 282 : | /// Move the next object in the queue to inventory. Then delete it properly from the scene. | ||
| 283 : | /// </summary> | ||
| 284 : | /// <returns></returns> | ||
| 285 : | public bool InventoryDeQueueAndDelete() | ||
| 286 : | { | ||
| 287 : | DeleteToInventoryHolder x = null; | ||
| 288 : | |||
| 289 : | try | ||
| 290 : | { | ||
| 291 : | lock (m_inventoryDeletes) | ||
| 292 : | { | ||
| 293 : | int left = m_inventoryDeletes.Count; | ||
| 294 : | if (left > 0) | ||
| 295 : | { | ||
| 296 : | m_log.DebugFormat( | ||
| 297 : | "[SCENE]: Sending object to user's inventory, {0} item(s) remaining.", left); | ||
| 298 : | |||
| 299 : | x = m_inventoryDeletes.Dequeue(); | ||
| 300 : | |||
| 301 : | try | ||
| 302 : | { | ||
| 303 : | //m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); | ||
| 304 : | //if (x.permissionToDelete) | ||
| 305 : | // m_scene.DeleteSceneObject(x.objectGroup, false); | ||
| 306 : | |||
| 307 : | UUID assetId = m_scene.DeleteToInventory(x.action, x.folderID, x.objectGroup, x.remoteClient); | ||
| 308 : | |||
| 309 : | //Get the item id of the asset so the RexObjectProperties can be changed to that id | ||
| 310 : | CachedUserInfo userInfo = m_scene.CommsManager.UserProfileCacheService.GetUserDetails(x.remoteClient.AgentId); | ||
| 311 : | mikkopa | 226 | if (userInfo.RootFolder != null) |
| 312 : | mikkopa | 142 | { |
| 313 : | mikkopa | 226 | InventoryItemBase item = userInfo.RootFolder.FindAsset(assetId); |
| 314 : | mikkopa | 142 | |
| 315 : | mikkopa | 226 | //Clone the old properties |
| 316 : | if (m_rexObjects != null) | ||
| 317 : | { | ||
| 318 : | RexObjectProperties origprops = m_rexObjects.GetObject(x.objectGroup.RootPart.UUID); | ||
| 319 : | RexObjectProperties cloneprops = m_rexObjects.GetObject(item.ID); | ||
| 320 : | |||
| 321 : | cloneprops.SetRexPrimDataFromObject(origprops); | ||
| 322 : | } | ||
| 323 : | mikkopa | 142 | } |
| 324 : | mikkopa | 226 | else |
| 325 : | m_log.Warn("[REXOBJECTS]: Could not find users root folder from cache. Did not clone rex object"); | ||
| 326 : | mikkopa | 142 | if (x.permissionToDelete) |
| 327 : | { | ||
| 328 : | m_scene.DeleteSceneObject(x.objectGroup, false); | ||
| 329 : | mikkopa | 334 | //m_rexObjects.DeleteObject(x.objectGroup.RootPart.UUID); |
| 330 : | mikkopa | 142 | } |
| 331 : | } | ||
| 332 : | catch (Exception e) | ||
| 333 : | { | ||
| 334 : | m_log.DebugFormat("Exception background sending object: " + e); | ||
| 335 : | } | ||
| 336 : | |||
| 337 : | return true; | ||
| 338 : | } | ||
| 339 : | } | ||
| 340 : | } | ||
| 341 : | catch (Exception e) | ||
| 342 : | { | ||
| 343 : | // We can't put the object group details in here since the root part may have disappeared (which is where these sit). | ||
| 344 : | // FIXME: This needs to be fixed. | ||
| 345 : | m_log.ErrorFormat( | ||
| 346 : | "[SCENE]: Queued sending of scene object to agent {0} {1} failed: {2}", | ||
| 347 : | (x != null ? x.remoteClient.Name : "unavailable"), (x != null ? x.remoteClient.AgentId.ToString() : "unavailable"), e.ToString()); | ||
| 348 : | } | ||
| 349 : | |||
| 350 : | m_log.Debug("[SCENE]: No objects left in inventory send queue."); | ||
| 351 : | return false; | ||
| 352 : | } | ||
| 353 : | |||
| 354 : | #endregion | ||
| 355 : | mikkopa | 137 | } |
| 356 : | mikkopa | 142 | |
| 357 : | class DeleteToInventoryHolder | ||
| 358 : | { | ||
| 359 : | public DeRezAction action; | ||
| 360 : | public IClientAPI remoteClient; | ||
| 361 : | public SceneObjectGroup objectGroup; | ||
| 362 : | public UUID folderID; | ||
| 363 : | public bool permissionToDelete; | ||
| 364 : | } | ||
| 365 : | mikkopa | 137 | } |
| ViewVC Help | |
| Powered by ViewVC 1.0.0 |

