aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--OpenSim/Region/Application/OpenSim.cs10
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs2
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs494
-rw-r--r--OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs51
-rw-r--r--OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs43
-rw-r--r--OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs15
-rw-r--r--OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs8
-rw-r--r--OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs3
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs72
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs18
-rw-r--r--OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs30
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiveWriteRequestPreparation.cs106
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/ArchiverModule.cs1
-rw-r--r--OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs6
-rw-r--r--OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs5
-rw-r--r--OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs89
-rw-r--r--OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs24
-rw-r--r--OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs54
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScenePresence.cs8
-rw-r--r--OpenSim/Region/Framework/Interfaces/ISceneViewer.cs13
-rw-r--r--OpenSim/Region/Framework/Interfaces/IScriptModule.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.Inventory.cs24
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs65
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs54
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs13
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/ScenePresence.cs133
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneViewer.cs87
-rw-r--r--OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs58
-rw-r--r--OpenSim/Region/Framework/Scenes/UuidGatherer.cs11
-rw-r--r--OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs94
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs76
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs19
-rw-r--r--OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs58
-rw-r--r--OpenSim/Region/ScriptEngine/XEngine/XEngine.cs5
36 files changed, 1181 insertions, 582 deletions
diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs
index fae8be7..92ccb06 100644
--- a/OpenSim/Region/Application/OpenSim.cs
+++ b/OpenSim/Region/Application/OpenSim.cs
@@ -269,13 +269,15 @@ namespace OpenSim
269 269
270 m_console.Commands.AddCommand("region", false, "save oar", 270 m_console.Commands.AddCommand("region", false, "save oar",
271 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", 271 //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
272 "save oar [-p|--profile=<url>] [--noassets] [<OAR path>]", 272 "save oar [-p|--profile=<url>] [--noassets] [--perm=<permissions>] [<OAR path>]",
273 "Save a region's data to an OAR archive.", 273 "Save a region's data to an OAR archive.",
274// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine 274// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
275 "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine 275 "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine
276 + " The OAR path must be a filesystem path." 276 + "--noassets stops assets being saved to the OAR." + Environment.NewLine
277 + " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine 277 + "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine
278 + "--noassets stops assets being saved to the OAR.", 278 + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine
279 + "The OAR path must be a filesystem path."
280 + " If this is not given then the oar is saved to region.oar in the current directory.",
279 SaveOar); 281 SaveOar);
280 282
281 m_console.Commands.AddCommand("region", false, "edit scale", 283 m_console.Commands.AddCommand("region", false, "edit scale",
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index dbfd0f2..dd0ea67 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -489,6 +489,8 @@ namespace OpenSim
489 scene.StartTimer(); 489 scene.StartTimer();
490 scene.StartTimerWatchdog(); 490 scene.StartTimerWatchdog();
491 491
492 scene.StartScripts();
493
492 return clientServer; 494 return clientServer;
493 } 495 }
494 496
diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
index 218b7b8..2bf418d 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs
@@ -144,20 +144,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
144 144
145 public void SaveChangedAttachments(IScenePresence sp) 145 public void SaveChangedAttachments(IScenePresence sp)
146 { 146 {
147// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
148
147 foreach (SceneObjectGroup grp in sp.GetAttachments()) 149 foreach (SceneObjectGroup grp in sp.GetAttachments())
148 { 150 {
149 if (grp.HasGroupChanged) // Resizer scripts? 151// if (grp.HasGroupChanged) // Resizer scripts?
150 { 152// {
151 grp.IsAttachment = false; 153 grp.IsAttachment = false;
152 grp.AbsolutePosition = grp.RootPart.AttachedPos; 154 grp.AbsolutePosition = grp.RootPart.AttachedPos;
153 UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); 155 UpdateKnownItem(sp.ControllingClient, grp);
154 grp.IsAttachment = true; 156 grp.IsAttachment = true;
155 } 157// }
156 } 158 }
157 } 159 }
158 160
159 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) 161 public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
160 { 162 {
163// m_log.DebugFormat(
164// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
165// m_scene.RegionInfo.RegionName, sp.Name, silent);
166
161 foreach (SceneObjectGroup sop in sp.GetAttachments()) 167 foreach (SceneObjectGroup sop in sp.GetAttachments())
162 { 168 {
163 sop.Scene.DeleteSceneObject(sop, silent); 169 sop.Scene.DeleteSceneObject(sop, silent);
@@ -220,7 +226,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
220 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); 226 m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
221 227
222 // Save avatar attachment information 228 // Save avatar attachment information
223 m_log.Info( 229 m_log.Debug(
224 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId 230 "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
225 + ", AttachmentPoint: " + AttachmentPt); 231 + ", AttachmentPoint: " + AttachmentPt);
226 232
@@ -248,75 +254,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
248 254
249 private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) 255 private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
250 { 256 {
251// m_log.DebugFormat( 257 lock (sp.AttachmentsSyncLock)
252// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
253// group.Name, group.LocalId, sp.Name, AttachmentPt, silent);
254
255 if (sp.GetAttachments(attachmentPt).Contains(group))
256 {
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);
260
261 return false;
262 }
263
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 { 258 {
281 // Check object for stored attachment point 259// m_log.DebugFormat(
282 attachmentPt = group.AttachmentPoint; 260// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
283 } 261// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
284 262
285 // if we still didn't find a suitable attachment point....... 263 if (sp.GetAttachments(attachmentPt).Contains(group))
286 if (attachmentPt == 0) 264 {
287 { 265 // m_log.WarnFormat(
288 // Stick it on left hand with Zero Offset from the attachment point. 266 // "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
289 attachmentPt = (uint)AttachmentPoint.LeftHand; 267 // group.Name, group.LocalId, sp.Name, AttachmentPt);
290 attachPos = Vector3.Zero; 268
291 } 269 return false;
292 270 }
293 group.AttachmentPoint = attachmentPt; 271
294 group.AbsolutePosition = attachPos; 272 Vector3 attachPos = group.AbsolutePosition;
295 273
296 // Remove any previous attachments 274 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
297 UUID itemID = UUID.Zero; 275 // be removed when that functionality is implemented in opensim
298 276 attachmentPt &= 0x7f;
299 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt); 277
300 278 // If the attachment point isn't the same as the one previously used
301 // At the moment we can only deal with a single attachment 279 // set it's offset position = 0 so that it appears on the attachment point
302 // We also don't want to do any of the inventory operations for an NPC. 280 // and not in a weird location somewhere unknown.
303 if (sp.PresenceType != PresenceType.Npc) 281 if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
304 { 282 {
305 if (attachments.Count != 0) 283 attachPos = Vector3.Zero;
306 itemID = attachments[0].GetFromItemID(); 284 }
285
286 // AttachmentPt 0 means the client chose to 'wear' the attachment.
287 if (attachmentPt == 0)
288 {
289 // Check object for stored attachment point
290 attachmentPt = group.AttachmentPoint;
291 }
292
293 // if we still didn't find a suitable attachment point.......
294 if (attachmentPt == 0)
295 {
296 // Stick it on left hand with Zero Offset from the attachment point.
297 attachmentPt = (uint)AttachmentPoint.LeftHand;
298 attachPos = Vector3.Zero;
299 }
300
301 group.AttachmentPoint = attachmentPt;
302 group.AbsolutePosition = attachPos;
303
304 // We also don't want to do any of the inventory operations for an NPC.
305 if (sp.PresenceType != PresenceType.Npc)
306 {
307 // Remove any previous attachments
308 List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
307 309
308 if (itemID != UUID.Zero) 310 // At the moment we can only deal with a single attachment
309 DetachSingleAttachmentToInv(itemID, sp); 311 if (attachments.Count != 0)
312 {
313 UUID oldAttachmentItemID = attachments[0].GetFromItemID();
314
315 if (oldAttachmentItemID != UUID.Zero)
316 DetachSingleAttachmentToInv(oldAttachmentItemID, sp);
317 else
318 m_log.WarnFormat(
319 "[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!",
320 attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
321 }
310 322
311 itemID = group.GetFromItemID(); 323 // Add the new attachment to inventory if we don't already have it.
312 if (itemID == UUID.Zero) 324 UUID newAttachmentItemID = group.GetFromItemID();
313 itemID = AddSceneObjectAsAttachment(sp.ControllingClient, group).ID; 325 if (newAttachmentItemID == UUID.Zero)
326 newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID;
327
328 ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
329 }
314 330
315 ShowAttachInUserInventory(sp, attachmentPt, itemID, group); 331 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
316 } 332 }
317 333
318 AttachToAgent(sp, group, attachmentPt, attachPos, silent);
319
320 return true; 334 return true;
321 } 335 }
322 336
@@ -325,20 +339,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
325 RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, 339 RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header,
326 RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) 340 RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects)
327 { 341 {
328 foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) 342 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
343
344 if (sp == null)
329 { 345 {
330 RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); 346 m_log.ErrorFormat(
347 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()",
348 remoteClient.Name, remoteClient.AgentId);
349 return;
350 }
351
352 lock (sp.AttachmentsSyncLock)
353 {
354// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
355
356 foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects)
357 {
358 RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt);
359 }
331 } 360 }
332 } 361 }
333 362
334 public ISceneEntity RezSingleAttachmentFromInventory( 363 public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
335 IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
336 {
337 return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true);
338 }
339
340 public ISceneEntity RezSingleAttachmentFromInventory(
341 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus)
342 { 364 {
343 return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null); 365 return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null);
344 } 366 }
@@ -347,21 +369,59 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
347 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc) 369 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
348 { 370 {
349 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 371 ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
350 if (sp == null) { m_log.ErrorFormat( "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()", remoteClient.Name, remoteClient.AgentId); return null; } 372
373 if (sp == null)
374 {
375 m_log.ErrorFormat(
376 "[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()",
377 remoteClient.Name, remoteClient.AgentId);
378 return null;
379 }
380
381 return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt);
382 }
383
384 public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt)
385 {
386// m_log.DebugFormat(
387// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
388// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
389
351 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should 390 // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
352 // be removed when that functionality is implemented in opensim 391 // be removed when that functionality is implemented in opensim
353 AttachmentPt &= 0x7f; 392 AttachmentPt &= 0x7f;
354 393
355 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc); 394 // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
395 // This often happens during login - not sure the exact reason.
396 // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the
397 // ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login
398 // before anything has actually been attached.
399 bool alreadyOn = false;
400 List<SceneObjectGroup> existingAttachments = sp.GetAttachments();
401 foreach (SceneObjectGroup so in existingAttachments)
402 {
403 if (so.GetFromItemID() == itemID)
404 {
405 alreadyOn = true;
406 break;
407 }
408 }
356 409
357 if (updateInventoryStatus) 410// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
411 if (alreadyOn)
358 { 412 {
359 if (att == null) 413// m_log.WarnFormat(
360 DetachSingleAttachmentToInv(itemID, sp.ControllingClient); 414// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
361 else 415// sp.Name, itemID, AttachmentPt);
362 ShowAttachInUserInventory(att, sp, itemID, AttachmentPt); 416
417 return null;
363 } 418 }
364 419
420 SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, null);
421
422 if (att == null)
423 DetachSingleAttachmentToInv(itemID, sp.ControllingClient);
424
365 return att; 425 return att;
366 } 426 }
367 427
@@ -371,50 +431,67 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
371 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); 431 IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
372 if (invAccess != null) 432 if (invAccess != null)
373 { 433 {
374 SceneObjectGroup objatt; 434 lock (sp.AttachmentsSyncLock)
375
376 if (itemID != UUID.Zero)
377 objatt = invAccess.RezObject(sp.ControllingClient,
378 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
379 false, false, sp.UUID, true);
380 else
381 objatt = invAccess.RezObject(sp.ControllingClient,
382 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
383 false, false, sp.UUID, true);
384
385// m_log.DebugFormat(
386// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
387// objatt.Name, remoteClient.Name, AttachmentPt);
388
389 if (objatt != null)
390 { 435 {
391 // Loading the inventory from XML will have set this, but 436 SceneObjectGroup objatt;
392 // there is no way the object could have changed yet, 437
393 // since scripts aren't running yet. So, clear it here. 438 if (itemID != UUID.Zero)
394 objatt.HasGroupChanged = false; 439 objatt = invAccess.RezObject(sp.ControllingClient,
395 bool tainted = false; 440 itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
396 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) 441 false, false, sp.UUID, true);
397 tainted = true; 442 else
398 443 objatt = invAccess.RezObject(sp.ControllingClient,
399 // This will throw if the attachment fails 444 null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
400 try 445 false, false, sp.UUID, true);
446
447 // m_log.DebugFormat(
448 // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
449 // objatt.Name, remoteClient.Name, AttachmentPt);
450
451 if (objatt != null)
401 { 452 {
402 AttachObject(sp, objatt, attachmentPt, false); 453 // HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
454 objatt.HasGroupChanged = false;
455 bool tainted = false;
456 if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
457 tainted = true;
458
459 // This will throw if the attachment fails
460 try
461 {
462 AttachObject(sp, objatt, attachmentPt, false);
463 }
464 catch (Exception e)
465 {
466 m_log.ErrorFormat(
467 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
468 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
469
470 // Make sure the object doesn't stick around and bail
471 sp.RemoveAttachment(objatt);
472 m_scene.DeleteSceneObject(objatt, false);
473 return null;
474 }
475
476 if (tainted)
477 objatt.HasGroupChanged = true;
478
479 // Fire after attach, so we don't get messy perms dialogs
480 // 4 == AttachedRez
481 objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
482 objatt.ResumeScripts();
483
484 // Do this last so that event listeners have access to all the effects of the attachment
485 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
486
487 return objatt;
403 } 488 }
404 catch (Exception e) 489 else
405 { 490 {
406 m_log.ErrorFormat( 491 m_log.WarnFormat(
407 "[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}", 492 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
408 objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace); 493 itemID, sp.Name, attachmentPt);
409
410 // Make sure the object doesn't stick around and bail
411 sp.RemoveAttachment(objatt);
412 m_scene.DeleteSceneObject(objatt, false);
413 return null;
414 } 494 }
415
416 if (tainted)
417 objatt.HasGroupChanged = true;
418 495
419 if (doc != null) 496 if (doc != null)
420 { 497 {
@@ -430,47 +507,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
430 // Do this last so that event listeners have access to all the effects of the attachment 507 // Do this last so that event listeners have access to all the effects of the attachment
431 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID); 508 m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
432 } 509 }
433 else
434 {
435 m_log.WarnFormat(
436 "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
437 itemID, sp.Name, attachmentPt);
438 }
439
440 return objatt;
441 } 510 }
442 511
443 return null; 512 return null;
444 } 513 }
445
446 /// <summary>
447 /// Update the user inventory to the attachment of an item
448 /// </summary>
449 /// <param name="att"></param>
450 /// <param name="sp"></param>
451 /// <param name="itemID"></param>
452 /// <param name="attachmentPoint"></param>
453 /// <returns></returns>
454 private UUID ShowAttachInUserInventory(
455 SceneObjectGroup att, IScenePresence sp, UUID itemID, uint attachmentPoint)
456 {
457// m_log.DebugFormat(
458// "[ATTACHMENTS MODULE]: Updating inventory of {0} to show attachment of {1} {2} (item ID {3}) at {4}",
459// sp.Name, att.Name, att.LocalId, itemID, AttachmentPt);
460
461 if (!att.IsDeleted)
462 attachmentPoint = att.AttachmentPoint;
463
464 InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
465 if (m_scene.InventoryService != null)
466 item = m_scene.InventoryService.GetItem(item);
467
468 bool changed = sp.Appearance.SetAttachment((int)attachmentPoint, itemID, item.AssetID);
469 if (changed && m_scene.AvatarFactory != null)
470 m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
471
472 return att.UUID;
473 }
474 514
475 /// <summary> 515 /// <summary>
476 /// Update the user inventory to reflect an attachment 516 /// Update the user inventory to reflect an attachment
@@ -483,8 +523,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
483 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) 523 IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
484 { 524 {
485// m_log.DebugFormat( 525// m_log.DebugFormat(
486// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", 526// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
487// att.Name, remoteClient.Name, AttachmentPt, itemID); 527// att.Name, sp.Name, AttachmentPt, itemID);
488 528
489 if (UUID.Zero == itemID) 529 if (UUID.Zero == itemID)
490 { 530 {
@@ -518,6 +558,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
518 558
519 public void DetachObject(uint objectLocalID, IClientAPI remoteClient) 559 public void DetachObject(uint objectLocalID, IClientAPI remoteClient)
520 { 560 {
561// m_log.DebugFormat(
562// "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name);
563
521 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); 564 SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
522 if (group != null) 565 if (group != null)
523 { 566 {
@@ -530,14 +573,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
530 ScenePresence presence; 573 ScenePresence presence;
531 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 574 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
532 { 575 {
533 // Save avatar attachment information 576 lock (presence.AttachmentsSyncLock)
534 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); 577 {
535 578 // Save avatar attachment information
536 bool changed = presence.Appearance.DetachAttachment(itemID); 579 m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
537 if (changed && m_scene.AvatarFactory != null)
538 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
539 580
540 DetachSingleAttachmentToInv(itemID, presence); 581 bool changed = presence.Appearance.DetachAttachment(itemID);
582 if (changed && m_scene.AvatarFactory != null)
583 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
584
585 DetachSingleAttachmentToInv(itemID, presence);
586 }
541 } 587 }
542 } 588 }
543 589
@@ -545,7 +591,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
545 { 591 {
546// m_log.DebugFormat( 592// m_log.DebugFormat(
547// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", 593// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
548// remoteClient.Name, sceneObjectID); 594// remoteClient.Name, soLocalId);
549 595
550 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); 596 SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
551 597
@@ -564,24 +610,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
564 ScenePresence presence; 610 ScenePresence presence;
565 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) 611 if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
566 { 612 {
567 if (!m_scene.Permissions.CanRezObject( 613 lock (presence.AttachmentsSyncLock)
568 so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) 614 {
569 return; 615 if (!m_scene.Permissions.CanRezObject(
616 so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
617 return;
570 618
571 bool changed = presence.Appearance.DetachAttachment(inventoryID); 619 bool changed = presence.Appearance.DetachAttachment(inventoryID);
572 if (changed && m_scene.AvatarFactory != null) 620 if (changed && m_scene.AvatarFactory != null)
573 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); 621 m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
574 622
575 presence.RemoveAttachment(so); 623 presence.RemoveAttachment(so);
576 DetachSceneObjectToGround(so, presence); 624 DetachSceneObjectToGround(so, presence);
577 625
578 List<UUID> uuids = new List<UUID>(); 626 List<UUID> uuids = new List<UUID>();
579 uuids.Add(inventoryID); 627 uuids.Add(inventoryID);
580 m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); 628 m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids);
581 remoteClient.SendRemoveInventoryItem(inventoryID); 629 remoteClient.SendRemoveInventoryItem(inventoryID);
582 } 630 }
583 631
584 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero); 632 m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
633 }
585 } 634 }
586 635
587 /// <summary> 636 /// <summary>
@@ -615,6 +664,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
615 // To LocalId or UUID, *THAT* is the question. How now Brown UUID?? 664 // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
616 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) 665 private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp)
617 { 666 {
667// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
668
618 if (itemID == UUID.Zero) // If this happened, someone made a mistake.... 669 if (itemID == UUID.Zero) // If this happened, someone made a mistake....
619 return; 670 return;
620 671
@@ -623,40 +674,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
623 EntityBase[] detachEntities = m_scene.GetEntities(); 674 EntityBase[] detachEntities = m_scene.GetEntities();
624 SceneObjectGroup group; 675 SceneObjectGroup group;
625 676
626 foreach (EntityBase entity in detachEntities) 677 lock (sp.AttachmentsSyncLock)
627 { 678 {
628 if (entity is SceneObjectGroup) 679 foreach (EntityBase entity in detachEntities)
629 { 680 {
630 group = (SceneObjectGroup)entity; 681 if (entity is SceneObjectGroup)
631 if (group.GetFromItemID() == itemID)
632 { 682 {
633 m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); 683 group = (SceneObjectGroup)entity; if (group.GetFromItemID() == itemID) { m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
634 // CM / XMREngine!!!! Needed to conclude attach event 684 // CM / XMREngine!!!! Needed to conclude attach event
635 //SceneObjectSerializer.ToOriginalXmlFormat(group); 685 //SceneObjectSerializer.ToOriginalXmlFormat(group);
636 group.DetachToInventoryPrep(); 686 group.DetachToInventoryPrep();
637 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); 687 m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
638 688
639 // Prepare sog for storage 689 // Prepare sog for storage
640 group.AttachedAvatar = UUID.Zero; 690 group.AttachedAvatar = UUID.Zero;
641 691 group.RootPart.SetParentLocalId(0);
642 group.ForEachPart( 692 group.IsAttachment = false;
643 delegate(SceneObjectPart part) 693 group.AbsolutePosition = group.RootPart.AttachedPos;
644 {
645 // If there are any scripts,
646 // then always trigger a new object and state persistence in UpdateKnownItem()
647 if (part.Inventory.ContainsScripts())
648 group.HasGroupChanged = true;
649 }
650 );
651
652 group.RootPart.SetParentLocalId(0);
653 group.IsAttachment = false;
654 group.AbsolutePosition = group.RootPart.AttachedPos;
655 694
656 UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID); 695 UpdateKnownItem(sp.ControllingClient, group);
657 m_scene.DeleteSceneObject(group, false); 696 m_scene.DeleteSceneObject(group, false);
658 697
659 return; 698 return;
699 }
660 } 700 }
661 } 701 }
662 } 702 }
@@ -687,28 +727,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
687 /// </remarks> 727 /// </remarks>
688 /// <param name="remoteClient"></param> 728 /// <param name="remoteClient"></param>
689 /// <param name="grp"></param> 729 /// <param name="grp"></param>
690 /// <param name="itemID"></param> 730 private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp)
691 /// <param name="agentID"></param>
692 public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID)
693 { 731 {
694 if (grp != null) 732 if (grp.HasGroupChanged || grp.ContainsScripts())
695 { 733 {
696 if (!grp.HasGroupChanged)
697 {
698 m_log.DebugFormat(
699 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
700 grp.UUID, grp.AttachmentPoint);
701
702 return;
703 }
704
705 m_log.DebugFormat( 734 m_log.DebugFormat(
706 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", 735 "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
707 grp.UUID, grp.AttachmentPoint); 736 grp.UUID, grp.AttachmentPoint);
708 737
709 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); 738 string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
710 739
711 InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); 740 InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId);
712 item = m_scene.InventoryService.GetItem(item); 741 item = m_scene.InventoryService.GetItem(item);
713 742
714 if (item != null) 743 if (item != null)
@@ -734,6 +763,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
734 remoteClient.SendInventoryItemCreateUpdate(item, 0); 763 remoteClient.SendInventoryItemCreateUpdate(item, 0);
735 } 764 }
736 } 765 }
766 else
767 {
768 m_log.DebugFormat(
769 "[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
770 grp.UUID, grp.AttachmentPoint);
771 }
737 } 772 }
738 773
739 /// <summary> 774 /// <summary>
@@ -751,7 +786,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
751 private void AttachToAgent( 786 private void AttachToAgent(
752 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) 787 IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
753 { 788 {
754// m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", 789// m_log.DebugFormat(
790// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
755// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); 791// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
756 792
757 so.DetachFromBackup(); 793 so.DetachFromBackup();
@@ -788,14 +824,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
788 } 824 }
789 825
790 /// <summary> 826 /// <summary>
791 /// Add a scene object that was previously free in the scene as an attachment to an avatar. 827 /// Add a scene object as a new attachment in the user inventory.
792 /// </summary> 828 /// </summary>
793 /// <param name="remoteClient"></param> 829 /// <param name="remoteClient"></param>
794 /// <param name="grp"></param> 830 /// <param name="grp"></param>
795 /// <returns>The user inventory item created that holds the attachment.</returns> 831 /// <returns>The user inventory item created that holds the attachment.</returns>
796 private InventoryItemBase AddSceneObjectAsAttachment(IClientAPI remoteClient, SceneObjectGroup grp) 832 private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp)
797 { 833 {
798// m_log.DebugFormat("[SCENE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId); 834// m_log.DebugFormat(
835// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
836// grp.Name, grp.LocalId, remoteClient.Name);
799 837
800 Vector3 inventoryStoredPosition = new Vector3 838 Vector3 inventoryStoredPosition = new Vector3
801 (((grp.AbsolutePosition.X > (int)Constants.RegionSize) 839 (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
@@ -879,4 +917,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
879 return item; 917 return item;
880 } 918 }
881 } 919 }
882} 920} \ 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 363e258..ff3358f 100644
--- a/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
+++ b/OpenSim/Region/CoreModules/Avatar/Attachments/Tests/AttachmentsModuleTests.cs
@@ -58,12 +58,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
58 private AttachmentsModule m_attMod; 58 private AttachmentsModule m_attMod;
59 private ScenePresence m_presence; 59 private ScenePresence m_presence;
60 60
61 [SetUp] 61 [TestFixtureSetUp]
62 public void Init() 62 public void FixtureInit()
63 { 63 {
64 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. 64 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
65 Util.FireAndForgetMethod = FireAndForgetMethod.None; 65 Util.FireAndForgetMethod = FireAndForgetMethod.None;
66 }
66 67
68 [SetUp]
69 public void Init()
70 {
67 IConfigSource config = new IniConfigSource(); 71 IConfigSource config = new IniConfigSource();
68 config.AddConfig("Modules"); 72 config.AddConfig("Modules");
69 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); 73 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
@@ -73,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
73 SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule()); 77 SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule());
74 } 78 }
75 79
76 [TearDown] 80 [TestFixtureTearDown]
77 public void TearDown() 81 public void TearDown()
78 { 82 {
79 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple 83 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
@@ -150,6 +154,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
150 Assert.That(attSo.IsTemporary, Is.False); 154 Assert.That(attSo.IsTemporary, Is.False);
151 155
152 // Check appearance status 156 // Check appearance status
157 Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(1));
153 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest)); 158 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
154 } 159 }
155 160
@@ -215,6 +220,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
215 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); 220 Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0));
216 } 221 }
217 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
218 [Test] 255 [Test]
219 public void TestRezAttachmentsOnAvatarEntrance() 256 public void TestRezAttachmentsOnAvatarEntrance()
220 { 257 {
@@ -246,6 +283,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
246 Assert.That(attSo.IsAttachment); 283 Assert.That(attSo.IsAttachment);
247 Assert.That(attSo.UsesPhysics, Is.False); 284 Assert.That(attSo.UsesPhysics, Is.False);
248 Assert.That(attSo.IsTemporary, Is.False); 285 Assert.That(attSo.IsTemporary, Is.False);
286
287 // Check appearance status
288 List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments();
289 Assert.That(retreivedAttachments.Count, Is.EqualTo(1));
290 Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
291 Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItemId));
292 Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attAssetId));
293 Assert.That(presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
249 } 294 }
250 295
251 // I'm commenting this test because scene setup NEEDS InventoryService to 296 // I'm commenting this test because scene setup NEEDS InventoryService to
diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs
index faccab2..25d5e0e 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
@@ -210,7 +208,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
210 sp.Teleport(position); 208 sp.Teleport(position);
211 209
212 foreach (SceneObjectGroup grp in sp.GetAttachments()) 210 foreach (SceneObjectGroup grp in sp.GetAttachments())
213 sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); 211 {
212 if (grp.IsDeleted)
213 sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
214 }
214 } 215 }
215 else // Another region possibly in another simulator 216 else // Another region possibly in another simulator
216 { 217 {
@@ -328,10 +329,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
328 sp.StandUp(); 329 sp.StandUp();
329 330
330 if (!sp.ValidateAttachments()) 331 if (!sp.ValidateAttachments())
331 { 332 m_log.DebugFormat(
332 sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); 333 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
333 return; 334 sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
334 } 335
336// if (!sp.ValidateAttachments())
337// {
338// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
339// return;
340// }
335 341
336 string reason; 342 string reason;
337 string version; 343 string version;
@@ -955,7 +961,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
955 /// This Closes child agents on neighbouring regions 961 /// This Closes child agents on neighbouring regions
956 /// Calls an asynchronous method to do so.. so it doesn't lag the sim. 962 /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
957 /// </summary> 963 /// </summary>
958 protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) 964 protected ScenePresence CrossAgentToNewRegionAsync(
965 ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion,
966 bool isFlying, string version)
959 { 967 {
960 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); 968 ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
961 969
@@ -963,8 +971,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
963 971
964 Scene m_scene = agent.Scene; 972 Scene m_scene = agent.Scene;
965 973
966 if (neighbourRegion != null && agent.ValidateAttachments()) 974 if (neighbourRegion != null)
967 { 975 {
976 if (!agent.ValidateAttachments())
977 m_log.DebugFormat(
978 "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.",
979 agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName);
980
968 pos = pos + (agent.Velocity); 981 pos = pos + (agent.Velocity);
969 982
970 SetInTransit(agent.UUID); 983 SetInTransit(agent.UUID);
@@ -1789,16 +1802,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
1789 List<SceneObjectGroup> m_attachments = sp.GetAttachments(); 1802 List<SceneObjectGroup> m_attachments = sp.GetAttachments();
1790 1803
1791 // Validate 1804 // Validate
1792 foreach (SceneObjectGroup gobj in m_attachments) 1805// foreach (SceneObjectGroup gobj in m_attachments)
1793 { 1806// {
1794 if (gobj == null || gobj.IsDeleted) 1807// if (gobj == null || gobj.IsDeleted)
1795 return false; 1808// return false;
1796 } 1809// }
1797 1810
1798 foreach (SceneObjectGroup gobj in m_attachments) 1811 foreach (SceneObjectGroup gobj in m_attachments)
1799 { 1812 {
1800 // If the prim group is null then something must have happened to it! 1813 // If the prim group is null then something must have happened to it!
1801 if (gobj != null) 1814 if (gobj != null && !gobj.IsDeleted)
1802 { 1815 {
1803 // Set the parent localID to 0 so it transfers over properly. 1816 // Set the parent localID to 0 so it transfers over properly.
1804 gobj.RootPart.SetParentLocalId(0); 1817 gobj.RootPart.SetParentLocalId(0);
diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
index a4bb40e..f05b090 100644
--- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs
@@ -726,8 +726,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
726 SceneObjectGroup group = null; 726 SceneObjectGroup group = null;
727 727
728 string xmlData = Utils.BytesToString(rezAsset.Data); 728 string xmlData = Utils.BytesToString(rezAsset.Data);
729 List<SceneObjectGroup> objlist = 729 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>();
730 new List<SceneObjectGroup>();
731 List<Vector3> veclist = new List<Vector3>(); 730 List<Vector3> veclist = new List<Vector3>();
732 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); 731 byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
733 Vector3 pos; 732 Vector3 pos;
@@ -799,6 +798,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
799 m_log.Debug("[InventoryAccessModule]: Object has UUID.Zero! Position 3"); 798 m_log.Debug("[InventoryAccessModule]: Object has UUID.Zero! Position 3");
800 } 799 }
801 800
801 foreach (SceneObjectPart part in group.Parts)
802 {
803 // Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
804 part.LastOwnerID = part.OwnerID;
805 part.OwnerID = remoteClient.AgentId;
806 }
807
802 if (!attachment) 808 if (!attachment)
803 { 809 {
804 // If it's rezzed in world, select it. Much easier to 810 // If it's rezzed in world, select it. Much easier to
@@ -839,7 +845,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
839 845
840 if (!attachment) 846 if (!attachment)
841 { 847 {
842 if (group.RootPart.Shape.PCode == (byte)PCode.Prim) 848 if (rootPart.Shape.PCode == (byte)PCode.Prim)
843 group.ClearPartAttachmentData(); 849 group.ClearPartAttachmentData();
844 850
845 // Fire on_rez 851 // Fire on_rez
@@ -1017,11 +1023,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
1017 if ((part.OwnerID != item.Owner) || 1023 if ((part.OwnerID != item.Owner) ||
1018 (item.CurrentPermissions & 16) != 0) 1024 (item.CurrentPermissions & 16) != 0)
1019 { 1025 {
1020 part.LastOwnerID = part.OwnerID;
1021 part.OwnerID = item.Owner;
1022 part.Inventory.ChangeInventoryOwner(item.Owner); 1026 part.Inventory.ChangeInventoryOwner(item.Owner);
1023 part.GroupMask = 0; // DO NOT propagate here 1027 part.GroupMask = 0; // DO NOT propagate here
1024 } 1028 }
1029
1025 part.EveryoneMask = item.EveryOnePermissions; 1030 part.EveryoneMask = item.EveryOnePermissions;
1026 part.NextOwnerMask = item.NextPermissions; 1031 part.NextOwnerMask = item.NextPermissions;
1027 } 1032 }
diff --git a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
index b0b35e4..bef0d69 100644
--- a/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
+++ b/OpenSim/Region/CoreModules/Framework/UserManagement/UserManagementModule.cs
@@ -87,8 +87,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
87 "Show the bindings between user UUIDs and user names", 87 "Show the bindings between user UUIDs and user names",
88 String.Empty, 88 String.Empty,
89 HandleShowUsers); 89 HandleShowUsers);
90
91
92 } 90 }
93 91
94 public bool IsSharedModule 92 public bool IsSharedModule
@@ -365,9 +363,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
365 lock (m_UserCache) 363 lock (m_UserCache)
366 m_UserCache[user.Id] = user; 364 m_UserCache[user.Id] = user;
367 365
368 m_log.DebugFormat( 366// m_log.DebugFormat(
369 "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", 367// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
370 user.Id, user.FirstName, user.LastName, user.HomeURL); 368// user.Id, user.FirstName, user.LastName, user.HomeURL);
371 } 369 }
372 370
373 //public void AddUser(UUID uuid, string userData) 371 //public void AddUser(UUID uuid, string userData)
diff --git a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
index b20a875..a14a84b 100644
--- a/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
+++ b/OpenSim/Region/CoreModules/Scripting/WorldComm/WorldCommModule.cs
@@ -323,7 +323,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
323 List<UUID> targets = new List<UUID>(); 323 List<UUID> targets = new List<UUID>();
324 foreach (SceneObjectGroup sog in attachments) 324 foreach (SceneObjectGroup sog in attachments)
325 { 325 {
326 targets.Add(sog.UUID); 326 if (!sog.IsDeleted)
327 targets.Add(sog.UUID);
327 } 328 }
328 329
329 // Need to check each attachment 330 // Need to check each attachment
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
index 72ae3363..0d121ed 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs
@@ -64,7 +64,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
64 get 64 get
65 { 65 {
66 if (m_UserManagement == null) 66 if (m_UserManagement == null)
67 {
67 m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>(); 68 m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>();
69
70 if (m_UserManagement == null)
71 m_log.ErrorFormat(
72 "[HG INVENTORY CONNECTOR]: Could not retrieve IUserManagement module from {0}",
73 m_Scenes[0].RegionInfo.RegionName);
74 }
75
68 return m_UserManagement; 76 return m_UserManagement;
69 } 77 }
70 } 78 }
@@ -140,8 +148,29 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
140 148
141 scene.RegisterModuleInterface<IInventoryService>(this); 149 scene.RegisterModuleInterface<IInventoryService>(this);
142 150
143 scene.EventManager.OnClientClosed += OnClientClosed; 151 if (m_Scenes.Count == 1)
152 {
153 // FIXME: The local connector needs the scene to extract the UserManager. However, it's not enabled so
154 // we can't just add the region. But this approach is super-messy.
155 if (m_LocalGridInventoryService is RemoteXInventoryServicesConnector)
156 {
157 m_log.DebugFormat(
158 "[HG INVENTORY BROKER]: Manually setting scene in RemoteXInventoryServicesConnector to {0}",
159 scene.RegionInfo.RegionName);
160
161 ((RemoteXInventoryServicesConnector)m_LocalGridInventoryService).Scene = scene;
162 }
163 else if (m_LocalGridInventoryService is LocalInventoryServicesConnector)
164 {
165 m_log.DebugFormat(
166 "[HG INVENTORY BROKER]: Manually setting scene in LocalInventoryServicesConnector to {0}",
167 scene.RegionInfo.RegionName);
144 168
169 ((LocalInventoryServicesConnector)m_LocalGridInventoryService).Scene = scene;
170 }
171
172 scene.EventManager.OnClientClosed += OnClientClosed;
173 }
145 } 174 }
146 175
147 public void RemoveRegion(Scene scene) 176 public void RemoveRegion(Scene scene)
@@ -323,7 +352,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
323 352
324 } 353 }
325 354
326 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) 355 public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
327 { 356 {
328 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); 357 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID);
329 358
@@ -338,7 +367,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
338 367
339 } 368 }
340 369
341 public bool AddFolder(InventoryFolderBase folder) 370 public bool AddFolder(InventoryFolderBase folder)
342 { 371 {
343 if (folder == null) 372 if (folder == null)
344 return false; 373 return false;
@@ -355,7 +384,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
355 return connector.AddFolder(folder); 384 return connector.AddFolder(folder);
356 } 385 }
357 386
358 public bool UpdateFolder(InventoryFolderBase folder) 387 public bool UpdateFolder(InventoryFolderBase folder)
359 { 388 {
360 if (folder == null) 389 if (folder == null)
361 return false; 390 return false;
@@ -372,7 +401,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
372 return connector.UpdateFolder(folder); 401 return connector.UpdateFolder(folder);
373 } 402 }
374 403
375 public bool DeleteFolders(UUID ownerID, List<UUID> folderIDs) 404 public bool DeleteFolders(UUID ownerID, List<UUID> folderIDs)
376 { 405 {
377 if (folderIDs == null) 406 if (folderIDs == null)
378 return false; 407 return false;
@@ -391,7 +420,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
391 return connector.DeleteFolders(ownerID, folderIDs); 420 return connector.DeleteFolders(ownerID, folderIDs);
392 } 421 }
393 422
394 public bool MoveFolder(InventoryFolderBase folder) 423 public bool MoveFolder(InventoryFolderBase folder)
395 { 424 {
396 if (folder == null) 425 if (folder == null)
397 return false; 426 return false;
@@ -408,7 +437,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
408 return connector.MoveFolder(folder); 437 return connector.MoveFolder(folder);
409 } 438 }
410 439
411 public bool PurgeFolder(InventoryFolderBase folder) 440 public bool PurgeFolder(InventoryFolderBase folder)
412 { 441 {
413 if (folder == null) 442 if (folder == null)
414 return false; 443 return false;
@@ -442,7 +471,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
442 return connector.AddItem(item); 471 return connector.AddItem(item);
443 } 472 }
444 473
445 public bool UpdateItem(InventoryItemBase item) 474 public bool UpdateItem(InventoryItemBase item)
446 { 475 {
447 if (item == null) 476 if (item == null)
448 return false; 477 return false;
@@ -459,7 +488,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
459 return connector.UpdateItem(item); 488 return connector.UpdateItem(item);
460 } 489 }
461 490
462 public bool MoveItems(UUID ownerID, List<InventoryItemBase> items) 491 public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
463 { 492 {
464 if (items == null) 493 if (items == null)
465 return false; 494 return false;
@@ -478,7 +507,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
478 return connector.MoveItems(ownerID, items); 507 return connector.MoveItems(ownerID, items);
479 } 508 }
480 509
481 public bool DeleteItems(UUID ownerID, List<UUID> itemIDs) 510 public bool DeleteItems(UUID ownerID, List<UUID> itemIDs)
482 { 511 {
483 //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Delete {0} items for user {1}", itemIDs.Count, ownerID); 512 //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Delete {0} items for user {1}", itemIDs.Count, ownerID);
484 513
@@ -497,7 +526,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
497 return connector.DeleteItems(ownerID, itemIDs); 526 return connector.DeleteItems(ownerID, itemIDs);
498 } 527 }
499 528
500 public InventoryItemBase GetItem(InventoryItemBase item) 529 public InventoryItemBase GetItem(InventoryItemBase item)
501 { 530 {
502 if (item == null) 531 if (item == null)
503 return null; 532 return null;
@@ -513,7 +542,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
513 return connector.GetItem(item); 542 return connector.GetItem(item);
514 } 543 }
515 544
516 public InventoryFolderBase GetFolder(InventoryFolderBase folder) 545 public InventoryFolderBase GetFolder(InventoryFolderBase folder)
517 { 546 {
518 if (folder == null) 547 if (folder == null)
519 return null; 548 return null;
@@ -530,17 +559,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
530 return connector.GetFolder(folder); 559 return connector.GetFolder(folder);
531 } 560 }
532 561
533 public bool HasInventoryForUser(UUID userID) 562 public bool HasInventoryForUser(UUID userID)
534 { 563 {
535 return false; 564 return false;
536 } 565 }
537 566
538 public List<InventoryItemBase> GetActiveGestures(UUID userId) 567 public List<InventoryItemBase> GetActiveGestures(UUID userId)
539 { 568 {
540 return new List<InventoryItemBase>(); 569 return new List<InventoryItemBase>();
541 } 570 }
542 571
543 public int GetAssetPermissions(UUID userID, UUID assetID) 572 public int GetAssetPermissions(UUID userID, UUID assetID)
544 { 573 {
545 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetAssetPermissions " + assetID); 574 //m_log.Debug("[HG INVENTORY CONNECTOR]: GetAssetPermissions " + assetID);
546 575
@@ -572,14 +601,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
572 string connectorType = new HeloServicesConnector(url).Helo(); 601 string connectorType = new HeloServicesConnector(url).Helo();
573 m_log.DebugFormat("[HG INVENTORY SERVICE]: HELO returned {0}", connectorType); 602 m_log.DebugFormat("[HG INVENTORY SERVICE]: HELO returned {0}", connectorType);
574 if (connectorType == "opensim-simian") 603 if (connectorType == "opensim-simian")
604 {
575 connector = new SimianInventoryServiceConnector(url); 605 connector = new SimianInventoryServiceConnector(url);
606 }
576 else 607 else
577 connector = new RemoteXInventoryServicesConnector(url); 608 {
609 RemoteXInventoryServicesConnector rxisc = new RemoteXInventoryServicesConnector(url);
610 rxisc.Scene = m_Scenes[0];
611 connector = rxisc;
612 }
613
578 m_connectors.Add(url, connector); 614 m_connectors.Add(url, connector);
579 } 615 }
580 } 616 }
617
581 return connector; 618 return connector;
582 } 619 }
583
584 } 620 }
585} 621} \ No newline at end of file
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
index 65e39c0..1c83f8e 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/LocalInventoryServiceConnector.cs
@@ -47,9 +47,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
47 LogManager.GetLogger( 47 LogManager.GetLogger(
48 MethodBase.GetCurrentMethod().DeclaringType); 48 MethodBase.GetCurrentMethod().DeclaringType);
49 49
50 private IInventoryService m_InventoryService; 50 /// <summary>
51 /// Scene used by this module. This currently needs to be publicly settable for HGInventoryBroker.
52 /// </summary>
53 public Scene Scene { get; set; }
51 54
52 private Scene m_Scene; 55 private IInventoryService m_InventoryService;
53 56
54 private IUserManagement m_UserManager; 57 private IUserManagement m_UserManager;
55 private IUserManagement UserManager 58 private IUserManagement UserManager
@@ -58,7 +61,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
58 { 61 {
59 if (m_UserManager == null) 62 if (m_UserManager == null)
60 { 63 {
61 m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>(); 64 m_UserManager = Scene.RequestModuleInterface<IUserManagement>();
62 } 65 }
63 return m_UserManager; 66 return m_UserManager;
64 } 67 }
@@ -131,8 +134,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
131 134
132 scene.RegisterModuleInterface<IInventoryService>(this); 135 scene.RegisterModuleInterface<IInventoryService>(this);
133 136
134 if (m_Scene == null) 137 if (Scene == null)
135 m_Scene = scene; 138 Scene = scene;
136 } 139 }
137 140
138 public void RemoveRegion(Scene scene) 141 public void RemoveRegion(Scene scene)
@@ -185,8 +188,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
185 Util.FireAndForget(delegate 188 Util.FireAndForget(delegate
186 { 189 {
187 if (UserManager != null) 190 if (UserManager != null)
188 foreach (InventoryItemBase item in invCol.Items) 191 {
192 // Protect ourselves against the caller subsequently modifying the items list
193 foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
189 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 194 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
195 }
190 }); 196 });
191 197
192 return invCol; 198 return invCol;
diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
index 8f1f257..c9c716c 100644
--- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
+++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/RemoteXInventoryServiceConnector.cs
@@ -45,19 +45,30 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
45 private static readonly ILog m_log = 45 private static readonly ILog m_log =
46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 46 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
47 47
48 /// <summary>
49 /// Scene used by this module. This currently needs to be publicly settable for HGInventoryBroker.
50 /// </summary>
51 public Scene Scene { get; set; }
52
48 private bool m_Enabled = false; 53 private bool m_Enabled = false;
49 private Scene m_Scene; 54 private Scene m_Scene;
50 private XInventoryServicesConnector m_RemoteConnector; 55 private XInventoryServicesConnector m_RemoteConnector;
51 56
52 private IUserManagement m_UserManager; 57 private IUserManagement m_UserManager;
53 private IUserManagement UserManager 58 public IUserManagement UserManager
54 { 59 {
55 get 60 get
56 { 61 {
57 if (m_UserManager == null) 62 if (m_UserManager == null)
58 { 63 {
59 m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>(); 64 m_UserManager = Scene.RequestModuleInterface<IUserManagement>();
65
66 if (m_UserManager == null)
67 m_log.ErrorFormat(
68 "[XINVENTORY CONNECTOR]: Could not retrieve IUserManagement module from {0}",
69 Scene.RegionInfo.RegionName);
60 } 70 }
71
61 return m_UserManager; 72 return m_UserManager;
62 } 73 }
63 } 74 }
@@ -86,12 +97,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
86 Init(source); 97 Init(source);
87 } 98 }
88 99
89 protected void Init(IConfigSource source) 100 protected void Init(IConfigSource source)
90 { 101 {
91 m_RemoteConnector = new XInventoryServicesConnector(source); 102 m_RemoteConnector = new XInventoryServicesConnector(source);
92 } 103 }
93 104
94
95 #region ISharedRegionModule 105 #region ISharedRegionModule
96 106
97 public void Initialise(IConfigSource source) 107 public void Initialise(IConfigSource source)
@@ -128,15 +138,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
128 138
129 scene.RegisterModuleInterface<IInventoryService>(this); 139 scene.RegisterModuleInterface<IInventoryService>(this);
130 140
131 if (m_Scene == null) 141 if (Scene == null)
132 m_Scene = scene; 142 Scene = scene;
133 } 143 }
134 144
135 public void RemoveRegion(Scene scene) 145 public void RemoveRegion(Scene scene)
136 { 146 {
137 if (!m_Enabled) 147 if (!m_Enabled)
138 return; 148 return;
139
140 } 149 }
141 150
142 public void RegionLoaded(Scene scene) 151 public void RegionLoaded(Scene scene)
@@ -181,14 +190,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
181 return m_RemoteConnector.GetFolderForType(userID, type); 190 return m_RemoteConnector.GetFolderForType(userID, type);
182 } 191 }
183 192
184 public InventoryCollection GetFolderContent(UUID userID, UUID folderID) 193 public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
185 { 194 {
186 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); 195 InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
187 Util.FireAndForget(delegate 196 Util.FireAndForget(delegate
188 { 197 {
189 if (UserManager != null) 198 if (UserManager != null)
190 foreach (InventoryItemBase item in invCol.Items) 199 {
200 // Protect ourselves against the caller subsequently modifying the items list
201 foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
191 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); 202 UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
203 }
192 }); 204 });
193 205
194 return invCol; 206 return invCol;
diff --git a/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs b/OpenSim/Region/CoreModules/World/Archiver/ArchiveReadRequest.cs
index f85a917..238863e 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 fb32288..321f6b6 100644
--- a/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Estate/EstateManagementModule.cs
@@ -992,6 +992,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
992 args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; 992 args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3;
993 args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; 993 args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4;
994 994
995// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName);
996// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName);
997// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName);
998// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName);
999
995 remoteClient.SendRegionHandshake(Scene.RegionInfo,args); 1000 remoteClient.SendRegionHandshake(Scene.RegionInfo,args);
996 } 1001 }
997 1002
diff --git a/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs b/OpenSim/Region/CoreModules/World/Permissions/PermissionsModule.cs
index afb641f..2e877f0 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
40namespace OpenSim.Region.CoreModules.World.Permissions 40namespace 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.
diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
index 59c26e7..d1b7dc1 100644
--- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs
@@ -89,18 +89,13 @@ namespace OpenSim.Region.Framework.Interfaces
89 ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt); 89 ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt);
90 90
91 /// <summary> 91 /// <summary>
92 /// Rez an attachment from user inventory 92 /// Rez an attachment from user inventory and change inventory status to match.
93 /// </summary> 93 /// </summary>
94 /// <param name="remoteClient"></param> 94 /// <param name="sp"></param>
95 /// <param name="itemID"></param> 95 /// <param name="itemID"></param>
96 /// <param name="AttachmentPt"></param> 96 /// <param name="AttachmentPt"></param>
97 /// <param name="updateinventoryStatus"> 97 /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
98 /// If true, we also update the user's inventory to show that the attachment is set. If false, we do not. 98 ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt);
99 /// False is required so that we don't attempt to update information when a user enters a scene with the
100 /// attachment already correctly set up in inventory.
101 /// <returns>The uuid of the scene object that was attached. Null if the scene object could not be found</returns>
102 ISceneEntity RezSingleAttachmentFromInventory(
103 IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus);
104 99
105 // Same as above, but also load script states from a separate doc 100 // Same as above, but also load script states from a separate doc
106 ISceneEntity RezSingleAttachmentFromInventory( 101 ISceneEntity RezSingleAttachmentFromInventory(
@@ -146,13 +141,10 @@ namespace OpenSim.Region.Framework.Interfaces
146 /// </param> 141 /// </param>
147 void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient); 142 void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient);
148 143
149 /// <summary> 144 /// Update the position of an attachment.
150 /// Update the user inventory with a changed attachment
151 /// </summary> 145 /// </summary>
152 /// <param name="remoteClient"></param> 146 /// <param name="sog"></param>
153 /// <param name="grp"></param> 147 /// <param name="pos"></param>
154 /// <param name="itemID"></param> 148 void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos);
155 /// <param name="agentID"></param>
156 void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID);
157 } 149 }
158} 150}
diff --git a/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs
new file mode 100644
index 0000000..1ed978b
--- /dev/null
+++ b/OpenSim/Region/Framework/Interfaces/IPermissionsModule.cs
@@ -0,0 +1,54 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using OpenMetaverse;
29using OpenSim.Region.Framework.Scenes;
30
31namespace OpenSim.Region.Framework.Interfaces
32{
33 /// <value>
34 /// Which set of permissions a user has.
35 /// </value>
36 public enum PermissionClass
37 {
38 Owner,
39 Group,
40 Everyone
41 };
42
43 public interface IPermissionsModule
44 {
45
46 /// <summary>
47 /// Returns the type of permissions that the user has over an object.
48 /// </summary>
49 /// <param name="user">The user</param>
50 /// <param name="obj">The object</param>
51 /// <returns>The type of permissions the user has over the object</returns>
52 PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj);
53 }
54}
diff --git a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
index 8913133..ff39283 100644
--- a/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScenePresence.cs
@@ -61,6 +61,14 @@ namespace OpenSim.Region.Framework.Interfaces
61 AvatarAppearance Appearance { get; set; } 61 AvatarAppearance Appearance { get; set; }
62 62
63 /// <summary> 63 /// <summary>
64 /// The AttachmentsModule synchronizes on this to avoid race conditions between commands to add and remove attachments.
65 /// </summary>
66 /// <remarks>
67 /// All add and remove attachment operations must synchronize on this for the lifetime of their operations.
68 /// </remarks>
69 Object AttachmentsSyncLock { get; }
70
71 /// <summary>
64 /// The scene objects attached to this avatar. 72 /// The scene objects attached to this avatar.
65 /// </summary> 73 /// </summary>
66 /// <returns> 74 /// <returns>
diff --git a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs b/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
index 2397f22..e715e70 100644
--- a/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
+++ b/OpenSim/Region/Framework/Interfaces/ISceneViewer.cs
@@ -30,12 +30,21 @@ using OpenSim.Region.Framework.Scenes;
30 30
31namespace OpenSim.Region.Framework.Interfaces 31namespace OpenSim.Region.Framework.Interfaces
32{ 32{
33 /// <summary>
34 /// Sends scheduled updates to it's associated ScenePresence.
35 /// </summary>
33 public interface ISceneViewer 36 public interface ISceneViewer
34 { 37 {
35 void Reset(); 38// void Reset();
36 void Close(); 39 void Close();
40
41 /// <summary>
42 /// Add the part to the queue of parts for which we need to send an update to the client
43 /// </summary>
44 /// <param name="part"></param>
37 void QueuePartForUpdate(SceneObjectPart part); 45 void QueuePartForUpdate(SceneObjectPart part);
46
38 void SendPrimUpdates(); 47 void SendPrimUpdates();
39 int GetPendingObjectsCount(); 48 int GetPendingObjectsCount();
40 } 49 }
41} 50} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
index 641e226..7dde586 100644
--- a/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
+++ b/OpenSim/Region/Framework/Interfaces/IScriptModule.cs
@@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
54 bool HasScript(UUID itemID, out bool running); 54 bool HasScript(UUID itemID, out bool running);
55 55
56 void SaveAllState(); 56 void SaveAllState();
57
58 /// <summary>
59 /// Starts the processing threads.
60 /// </summary>
61 void StartProcessing();
57 } 62 }
58} 63}
diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
index 63dd550..c2ec5d0 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs
@@ -57,11 +57,11 @@ namespace OpenSim.Region.Framework.Scenes
57 protected AsyncInventorySender m_asyncInventorySender; 57 protected AsyncInventorySender m_asyncInventorySender;
58 58
59 /// <summary> 59 /// <summary>
60 /// Start all the scripts in the scene which should be started. 60 /// Creates all the scripts in the scene which should be started.
61 /// </summary> 61 /// </summary>
62 public void CreateScriptInstances() 62 public void CreateScriptInstances()
63 { 63 {
64 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); 64 m_log.Info("[PRIM INVENTORY]: Creating scripts in scene");
65 65
66 EntityBase[] entities = Entities.GetEntities(); 66 EntityBase[] entities = Entities.GetEntities();
67 foreach (EntityBase group in entities) 67 foreach (EntityBase group in entities)
@@ -74,6 +74,26 @@ namespace OpenSim.Region.Framework.Scenes
74 } 74 }
75 } 75 }
76 76
77 /// <summary>
78 /// Lets the script engines start processing scripts.
79 /// </summary>
80 public void StartScripts()
81 {
82 m_log.Info("[PRIM INVENTORY]: Starting scripts in scene");
83
84 IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
85 if (engines != null)
86 {
87 foreach (IScriptModule engine in engines)
88 {
89 if (engine != null)
90 {
91 engine.StartProcessing();
92 }
93 }
94 }
95 }
96
77 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) 97 public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item)
78 { 98 {
79 IMoneyModule money = RequestModuleInterface<IMoneyModule>(); 99 IMoneyModule money = RequestModuleInterface<IMoneyModule>();
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index a661ab8..c5bb2b2 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -610,9 +610,42 @@ namespace OpenSim.Region.Framework.Scenes
610 #region Region Settings 610 #region Region Settings
611 611
612 // Load region settings 612 // Load region settings
613 m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID); 613 // LoadRegionSettings creates new region settings in persistence if they don't already exist for this region.
614 // However, in this case, the default textures are not set in memory properly, so we need to do it here and
615 // resave.
616 // FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new
617 // region is set up and avoid these gyrations.
618 RegionSettings rs = simDataService.LoadRegionSettings(m_regInfo.RegionID);
619 bool updatedTerrainTextures = false;
620 if (rs.TerrainTexture1 == UUID.Zero)
621 {
622 rs.TerrainTexture1 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_1;
623 updatedTerrainTextures = true;
624 }
625
626 if (rs.TerrainTexture2 == UUID.Zero)
627 {
628 rs.TerrainTexture2 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_2;
629 updatedTerrainTextures = true;
630 }
631
632 if (rs.TerrainTexture3 == UUID.Zero)
633 {
634 rs.TerrainTexture3 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_3;
635 updatedTerrainTextures = true;
636 }
637
638 if (rs.TerrainTexture4 == UUID.Zero)
639 {
640 rs.TerrainTexture4 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_4;
641 updatedTerrainTextures = true;
642 }
643
644 if (updatedTerrainTextures)
645 rs.Save();
646
647 m_regInfo.RegionSettings = rs;
614 648
615 m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
616 if (estateDataService != null) 649 if (estateDataService != null)
617 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); 650 m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
618 651
@@ -645,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
645 EventManager.OnLandObjectRemoved += 678 EventManager.OnLandObjectRemoved +=
646 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); 679 new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
647 680
648 m_sceneGraph = new SceneGraph(this, m_regInfo); 681 m_sceneGraph = new SceneGraph(this);
649 682
650 // If the scene graph has an Unrecoverable error, restart this sim. 683 // If the scene graph has an Unrecoverable error, restart this sim.
651 // Currently the only thing that causes it to happen is two kinds of specific 684 // Currently the only thing that causes it to happen is two kinds of specific
@@ -1575,7 +1608,9 @@ namespace OpenSim.Region.Framework.Scenes
1575 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; 1608 msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
1576 msg.Position = Vector3.Zero; 1609 msg.Position = Vector3.Zero;
1577 msg.RegionID = RegionInfo.RegionID.Guid; 1610 msg.RegionID = RegionInfo.RegionID.Guid;
1578 msg.binaryBucket = new byte[0]; 1611
1612 // We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
1613 msg.binaryBucket = Util.StringToBytes256("\0");
1579 if (ret.Value.count > 1) 1614 if (ret.Value.count > 1)
1580 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason); 1615 msg.message = string.Format("Your {0} objects were returned from {1} in region {2} due to {3}", ret.Value.count, ret.Value.location.ToString(), RegionInfo.RegionName, ret.Value.reason);
1581 else 1616 else
@@ -2492,14 +2527,16 @@ namespace OpenSim.Region.Framework.Scenes
2492 /// <returns>False</returns> 2527 /// <returns>False</returns>
2493 public virtual bool IncomingCreateObject(UUID userID, UUID itemID) 2528 public virtual bool IncomingCreateObject(UUID userID, UUID itemID)
2494 { 2529 {
2495 //m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID); 2530 m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID);
2496 2531
2497 ScenePresence sp = GetScenePresence(userID); 2532 // Commented out since this is as yet unused and is arguably not the appropriate place to do this, as
2498 if (sp != null && AttachmentsModule != null) 2533 // attachments are being rezzed elsewhere in AddNewClient()
2499 { 2534// ScenePresence sp = GetScenePresence(userID);
2500 uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID); 2535// if (sp != null && AttachmentsModule != null)
2501 AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt); 2536// {
2502 } 2537// uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID);
2538// AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt);
2539// }
2503 2540
2504 return false; 2541 return false;
2505 } 2542 }
@@ -3272,8 +3309,8 @@ namespace OpenSim.Region.Framework.Scenes
3272 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) 3309 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3273 AttachmentsModule.SaveChangedAttachments(avatar); 3310 AttachmentsModule.SaveChangedAttachments(avatar);
3274 3311
3275 if (avatar != null && (!avatar.IsChildAgent)) 3312 if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
3276 avatar.SaveChangedAttachments(); 3313 AttachmentsModule.SaveChangedAttachments(avatar);
3277 3314
3278 ForEachClient( 3315 ForEachClient(
3279 delegate(IClientAPI client) 3316 delegate(IClientAPI client)
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 42e2502..d1ee990 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -83,7 +83,6 @@ namespace OpenSim.Region.Framework.Scenes
83 83
84 protected internal EntityManager Entities = new EntityManager(); 84 protected internal EntityManager Entities = new EntityManager();
85 85
86 protected RegionInfo m_regInfo;
87 protected Scene m_parentScene; 86 protected Scene m_parentScene;
88 protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>(); 87 protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>();
89 protected int m_numRootAgents = 0; 88 protected int m_numRootAgents = 0;
@@ -117,10 +116,9 @@ namespace OpenSim.Region.Framework.Scenes
117 116
118 #endregion 117 #endregion
119 118
120 protected internal SceneGraph(Scene parent, RegionInfo regInfo) 119 protected internal SceneGraph(Scene parent)
121 { 120 {
122 m_parentScene = parent; 121 m_parentScene = parent;
123 m_regInfo = regInfo;
124 } 122 }
125 123
126 public PhysicsScene PhysicsScene 124 public PhysicsScene PhysicsScene
@@ -131,7 +129,6 @@ namespace OpenSim.Region.Framework.Scenes
131 // If we're not doing the initial set 129 // If we're not doing the initial set
132 // Then we've got to remove the previous 130 // Then we've got to remove the previous
133 // event handler 131 // event handler
134
135 if (_PhyScene != null) 132 if (_PhyScene != null)
136 _PhyScene.OnPhysicsCrash -= physicsBasedCrash; 133 _PhyScene.OnPhysicsCrash -= physicsBasedCrash;
137 134
@@ -413,12 +410,12 @@ namespace OpenSim.Region.Framework.Scenes
413// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", 410// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
414// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); 411// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
415 412
416 SceneObjectPart[] children = sceneObject.Parts; 413 SceneObjectPart[] parts = sceneObject.Parts;
417 414
418 // Clamp child prim sizes and add child prims to the m_numPrim count 415 // Clamp child prim sizes and add child prims to the m_numPrim count
419 if (m_parentScene.m_clampPrimSize) 416 if (m_parentScene.m_clampPrimSize)
420 { 417 {
421 foreach (SceneObjectPart part in children) 418 foreach (SceneObjectPart part in parts)
422 { 419 {
423 Vector3 scale = part.Shape.Scale; 420 Vector3 scale = part.Shape.Scale;
424 421
@@ -432,7 +429,7 @@ namespace OpenSim.Region.Framework.Scenes
432 part.Shape.Scale = scale; 429 part.Shape.Scale = scale;
433 } 430 }
434 } 431 }
435 m_numPrim += children.Length; 432 m_numPrim += parts.Length;
436 433
437 sceneObject.AttachToScene(m_parentScene); 434 sceneObject.AttachToScene(m_parentScene);
438 435
@@ -452,15 +449,17 @@ namespace OpenSim.Region.Framework.Scenes
452 449
453 lock (SceneObjectGroupsByFullPartID) 450 lock (SceneObjectGroupsByFullPartID)
454 { 451 {
455 SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject; 452 foreach (SceneObjectPart part in parts)
456 foreach (SceneObjectPart part in children)
457 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; 453 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
458 } 454 }
459 455
460 lock (SceneObjectGroupsByLocalPartID) 456 lock (SceneObjectGroupsByLocalPartID)
461 { 457 {
462 SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject; 458// m_log.DebugFormat(
463 foreach (SceneObjectPart part in children) 459// "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
460// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
461
462 foreach (SceneObjectPart part in parts)
464 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; 463 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
465 } 464 }
466 465
@@ -473,6 +472,10 @@ namespace OpenSim.Region.Framework.Scenes
473 /// <returns>true if the object was deleted, false if there was no object to delete</returns> 472 /// <returns>true if the object was deleted, false if there was no object to delete</returns>
474 public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) 473 public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked)
475 { 474 {
475// m_log.DebugFormat(
476// "[SCENE GRAPH]: Deleting scene object with uuid {0}, resultOfObjectLinked = {1}",
477// uuid, resultOfObjectLinked);
478
476 EntityBase entity; 479 EntityBase entity;
477 if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup))) 480 if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup)))
478 return false; 481 return false;
@@ -501,7 +504,6 @@ namespace OpenSim.Region.Framework.Scenes
501 SceneObjectPart[] parts = grp.Parts; 504 SceneObjectPart[] parts = grp.Parts;
502 for (int i = 0; i < parts.Length; i++) 505 for (int i = 0; i < parts.Length; i++)
503 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); 506 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
504 SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID);
505 } 507 }
506 508
507 lock (SceneObjectGroupsByLocalPartID) 509 lock (SceneObjectGroupsByLocalPartID)
@@ -509,7 +511,6 @@ namespace OpenSim.Region.Framework.Scenes
509 SceneObjectPart[] parts = grp.Parts; 511 SceneObjectPart[] parts = grp.Parts;
510 for (int i = 0; i < parts.Length; i++) 512 for (int i = 0; i < parts.Length; i++)
511 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); 513 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
512 SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId);
513 } 514 }
514 515
515 return Entities.Remove(uuid); 516 return Entities.Remove(uuid);
@@ -654,7 +655,7 @@ namespace OpenSim.Region.Framework.Scenes
654 ScenePresence newAvatar = null; 655 ScenePresence newAvatar = null;
655 656
656 // ScenePresence always defaults to child agent 657 // ScenePresence always defaults to child agent
657 newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance, type); 658 newAvatar = new ScenePresence(client, m_parentScene, appearance, type);
658 659
659 AddScenePresence(newAvatar); 660 AddScenePresence(newAvatar);
660 661
@@ -721,7 +722,7 @@ namespace OpenSim.Region.Framework.Scenes
721 if (!Entities.Remove(agentID)) 722 if (!Entities.Remove(agentID))
722 { 723 {
723 m_log.WarnFormat( 724 m_log.WarnFormat(
724 "[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", 725 "[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
725 agentID); 726 agentID);
726 } 727 }
727 728
@@ -745,7 +746,7 @@ namespace OpenSim.Region.Framework.Scenes
745 } 746 }
746 else 747 else
747 { 748 {
748 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 749 m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
749 } 750 }
750 } 751 }
751 finally 752 finally
@@ -956,7 +957,8 @@ namespace OpenSim.Region.Framework.Scenes
956 if (Entities.TryGetValue(localID, out entity)) 957 if (Entities.TryGetValue(localID, out entity))
957 return entity as SceneObjectGroup; 958 return entity as SceneObjectGroup;
958 959
959 //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); 960// m_log.DebugFormat("[SCENE GRAPH]: Entered GetGroupByPrim with localID {0}", localID);
961
960 SceneObjectGroup sog; 962 SceneObjectGroup sog;
961 lock (SceneObjectGroupsByLocalPartID) 963 lock (SceneObjectGroupsByLocalPartID)
962 SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog); 964 SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog);
@@ -964,8 +966,24 @@ namespace OpenSim.Region.Framework.Scenes
964 if (sog != null) 966 if (sog != null)
965 { 967 {
966 if (sog.HasChildPrim(localID)) 968 if (sog.HasChildPrim(localID))
969 {
970// m_log.DebugFormat(
971// "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.",
972// sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
973
967 return sog; 974 return sog;
968 SceneObjectGroupsByLocalPartID.Remove(localID); 975 }
976 else
977 {
978 lock (SceneObjectGroupsByLocalPartID)
979 {
980 m_log.WarnFormat(
981 "[SCENE GRAPH]: Found scene object {0} {1} {2} via SceneObjectGroupsByLocalPartID index but it doesn't contain part with local id {3}. Removing from entry from index in {4}.",
982 sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
983
984 SceneObjectGroupsByLocalPartID.Remove(localID);
985 }
986 }
969 } 987 }
970 988
971 EntityBase[] entityList = GetEntities(); 989 EntityBase[] entityList = GetEntities();
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
index 9f0ac4f..6bd9183 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs
@@ -388,5 +388,18 @@ namespace OpenSim.Region.Framework.Scenes
388 for (int i = 0; i < parts.Length; i++) 388 for (int i = 0; i < parts.Length; i++)
389 parts[i].Inventory.ResumeScripts(); 389 parts[i].Inventory.ResumeScripts();
390 } 390 }
391
392 /// <summary>
393 /// Returns true if any part in the scene object contains scripts, false otherwise.
394 /// </summary>
395 /// <returns></returns>
396 public bool ContainsScripts()
397 {
398 foreach (SceneObjectPart part in Parts)
399 if (part.Inventory.ContainsScripts())
400 return true;
401
402 return false;
403 }
391 } 404 }
392} 405}
diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
index 1f0840d..f6b690c 100644
--- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs
@@ -1239,10 +1239,15 @@ namespace OpenSim.Region.Framework.Scenes
1239 item.CurrentPermissions = perms; 1239 item.CurrentPermissions = perms;
1240 item.BasePermissions = perms; 1240 item.BasePermissions = perms;
1241 } 1241 }
1242
1242 m_inventorySerial++; 1243 m_inventorySerial++;
1243 HasInventoryChanged = true; 1244 HasInventoryChanged = true;
1244 } 1245 }
1245 1246
1247 /// <summary>
1248 /// Returns true if this part inventory contains any scripts. False otherwise.
1249 /// </summary>
1250 /// <returns></returns>
1246 public bool ContainsScripts() 1251 public bool ContainsScripts()
1247 { 1252 {
1248 foreach (TaskInventoryItem item in m_items.Values) 1253 foreach (TaskInventoryItem item in m_items.Values)
diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
index 35a8df7..7a86f98 100644
--- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs
+++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs
@@ -124,6 +124,8 @@ namespace OpenSim.Region.Framework.Scenes
124 124
125 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); 125 protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
126 126
127 public Object AttachmentsSyncLock { get; private set; }
128
127 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); 129 private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
128 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; 130 private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
129 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; 131 private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
@@ -199,7 +201,6 @@ namespace OpenSim.Region.Framework.Scenes
199 201
200 private float m_health = 100f; 202 private float m_health = 100f;
201 203
202 protected RegionInfo m_regionInfo;
203 protected ulong crossingFromRegion; 204 protected ulong crossingFromRegion;
204 205
205 private readonly Vector3[] Dir_Vectors = new Vector3[11]; 206 private readonly Vector3[] Dir_Vectors = new Vector3[11];
@@ -770,23 +771,24 @@ namespace OpenSim.Region.Framework.Scenes
770 #endregion 771 #endregion
771 772
772 #region Constructor(s) 773 #region Constructor(s)
773 774
774 public ScenePresence( 775 public ScenePresence(
775 IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance, PresenceType type) 776 IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
776 { 777 {
778 AttachmentsSyncLock = new Object();
779
777 m_sendCourseLocationsMethod = SendCoarseLocationsDefault; 780 m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
778 m_sceneViewer = new SceneViewer(this); 781 m_sceneViewer = new SceneViewer(this);
779 m_animator = new ScenePresenceAnimator(this); 782 m_animator = new ScenePresenceAnimator(this);
780 PresenceType = type; 783 PresenceType = type;
781 m_DrawDistance = world.DefaultDrawDistance; 784 m_DrawDistance = world.DefaultDrawDistance;
782 m_rootRegionHandle = reginfo.RegionHandle; 785 m_rootRegionHandle = world.RegionInfo.RegionHandle;
783 m_controllingClient = client; 786 m_controllingClient = client;
784 m_firstname = m_controllingClient.FirstName; 787 m_firstname = m_controllingClient.FirstName;
785 m_lastname = m_controllingClient.LastName; 788 m_lastname = m_controllingClient.LastName;
786 m_name = String.Format("{0} {1}", m_firstname, m_lastname); 789 m_name = String.Format("{0} {1}", m_firstname, m_lastname);
787 m_scene = world; 790 m_scene = world;
788 m_uuid = client.AgentId; 791 m_uuid = client.AgentId;
789 m_regionInfo = reginfo;
790 m_localId = m_scene.AllocateLocalId(); 792 m_localId = m_scene.AllocateLocalId();
791 793
792 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); 794 UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
@@ -1302,7 +1304,7 @@ namespace OpenSim.Region.Framework.Scenes
1302 1304
1303 //m_log.DebugFormat("Completed movement"); 1305 //m_log.DebugFormat("Completed movement");
1304 1306
1305 m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); 1307 m_controllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
1306 SendInitialData(); 1308 SendInitialData();
1307 1309
1308 // Create child agents in neighbouring regions 1310 // Create child agents in neighbouring regions
@@ -3226,8 +3228,8 @@ namespace OpenSim.Region.Framework.Scenes
3226 /// </returns> 3228 /// </returns>
3227 protected int HaveNeighbor(Cardinals car, ref int[] fix) 3229 protected int HaveNeighbor(Cardinals car, ref int[] fix)
3228 { 3230 {
3229 uint neighbourx = m_regionInfo.RegionLocX; 3231 uint neighbourx = m_scene.RegionInfo.RegionLocX;
3230 uint neighboury = m_regionInfo.RegionLocY; 3232 uint neighboury = m_scene.RegionInfo.RegionLocY;
3231 3233
3232 int dir = (int)car; 3234 int dir = (int)car;
3233 3235
@@ -3247,8 +3249,8 @@ namespace OpenSim.Region.Framework.Scenes
3247 3249
3248 if (neighbourRegion == null) 3250 if (neighbourRegion == null)
3249 { 3251 {
3250 fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); 3252 fix[0] = (int)(m_scene.RegionInfo.RegionLocX - neighbourx);
3251 fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); 3253 fix[1] = (int)(m_scene.RegionInfo.RegionLocY - neighboury);
3252 return dir * (-1); 3254 return dir * (-1);
3253 } 3255 }
3254 else 3256 else
@@ -3494,26 +3496,30 @@ namespace OpenSim.Region.Framework.Scenes
3494 catch { } 3496 catch { }
3495 3497
3496 // Attachment objects 3498 // Attachment objects
3497 if (m_attachments != null && m_attachments.Count > 0) 3499 lock (m_attachments)
3498 { 3500 {
3499 cAgent.AttachmentObjects = new List<ISceneObject>(); 3501 if (m_attachments.Count > 0)
3500 cAgent.AttachmentObjectStates = new List<string>();
3501// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
3502 m_InTransitScriptStates.Clear();
3503 foreach (SceneObjectGroup sog in m_attachments)
3504 { 3502 {
3505 // We need to make a copy and pass that copy 3503 cAgent.AttachmentObjects = new List<ISceneObject>();
3506 // because of transfers withn the same sim 3504 cAgent.AttachmentObjectStates = new List<string>();
3507 ISceneObject clone = sog.CloneForNewScene(); 3505 // IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
3508 // Attachment module assumes that GroupPosition holds the offsets...! 3506 m_InTransitScriptStates.Clear();
3509 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos; 3507
3510 ((SceneObjectGroup)clone).IsAttachment = false; 3508 foreach (SceneObjectGroup sog in m_attachments)
3511 cAgent.AttachmentObjects.Add(clone); 3509 {
3512 string state = sog.GetStateSnapshot(); 3510 // We need to make a copy and pass that copy
3513 cAgent.AttachmentObjectStates.Add(state); 3511 // because of transfers withn the same sim
3514 m_InTransitScriptStates.Add(state); 3512 ISceneObject clone = sog.CloneForNewScene();
3515 // Let's remove the scripts of the original object here 3513 // Attachment module assumes that GroupPosition holds the offsets...!
3516 sog.RemoveScriptInstances(true); 3514 ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
3515 ((SceneObjectGroup)clone).IsAttachment = false;
3516 cAgent.AttachmentObjects.Add(clone);
3517 string state = sog.GetStateSnapshot();
3518 cAgent.AttachmentObjectStates.Add(state);
3519 m_InTransitScriptStates.Add(state);
3520 // Let's remove the scripts of the original object here
3521 sog.RemoveScriptInstances(true);
3522 }
3517 } 3523 }
3518 } 3524 }
3519 } 3525 }
@@ -3931,7 +3937,8 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
3931 3937
3932 public void Close() 3938 public void Close()
3933 { 3939 {
3934 m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false); 3940 if (!IsChildAgent)
3941 m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false);
3935 3942
3936 lock (m_knownChildRegions) 3943 lock (m_knownChildRegions)
3937 { 3944 {
@@ -4035,8 +4042,13 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
4035 m_attachments.Clear(); 4042 m_attachments.Clear();
4036 } 4043 }
4037 4044
4045 /// <summary>
4046 /// This is currently just being done for information.
4047 /// </summary>
4038 public bool ValidateAttachments() 4048 public bool ValidateAttachments()
4039 { 4049 {
4050 bool validated = true;
4051
4040 lock (m_attachments) 4052 lock (m_attachments)
4041 { 4053 {
4042 // Validate 4054 // Validate
@@ -4045,21 +4057,22 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
4045 if (gobj == null) 4057 if (gobj == null)
4046 { 4058 {
4047 m_log.WarnFormat( 4059 m_log.WarnFormat(
4048 "[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null", Name); 4060 "[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null. Continuing", Name);
4049 return false;
4050 }
4051 4061
4052 if (gobj.IsDeleted) 4062 validated = false;
4063 }
4064 else if (gobj.IsDeleted)
4053 { 4065 {
4054 m_log.WarnFormat( 4066 m_log.WarnFormat(
4055 "[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted", 4067 "[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted. Continuing",
4056 gobj.Name, gobj.UUID, Name); 4068 gobj.Name, gobj.UUID, Name);
4057 return false; 4069
4070 validated = false;
4058 } 4071 }
4059 } 4072 }
4060 } 4073 }
4061 4074
4062 return true; 4075 return validated;
4063 } 4076 }
4064 4077
4065 /// <summary> 4078 /// <summary>
@@ -4091,29 +4104,6 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
4091 } 4104 }
4092 } 4105 }
4093 4106
4094
4095 public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
4096 {
4097 m_controllingClient = client;
4098 m_regionInfo = region;
4099 m_scene = scene;
4100
4101 RegisterToEvents();
4102
4103 /*
4104 AbsolutePosition = client.StartPos;
4105
4106 Animations = new AvatarAnimations();
4107 Animations.LoadAnims();
4108
4109 m_animations = new List<UUID>();
4110 m_animations.Add(Animations.AnimsUUID["STAND"]);
4111 m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
4112
4113 SetDirectionVectors();
4114 */
4115 }
4116
4117 internal void PushForce(Vector3 impulse) 4107 internal void PushForce(Vector3 impulse)
4118 { 4108 {
4119 if (PhysicsActor != null) 4109 if (PhysicsActor != null)
@@ -4141,6 +4131,7 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
4141 obj.ignoreControls = (ScriptControlled)controls; 4131 obj.ignoreControls = (ScriptControlled)controls;
4142 obj.eventControls = (ScriptControlled)controls; 4132 obj.eventControls = (ScriptControlled)controls;
4143 } 4133 }
4134
4144 if (pass_on == 1 && accept == 1) 4135 if (pass_on == 1 && accept == 1)
4145 { 4136 {
4146 IgnoredControls = ScriptControlled.CONTROL_ZERO; 4137 IgnoredControls = ScriptControlled.CONTROL_ZERO;
@@ -4161,6 +4152,7 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
4161 scriptedcontrols[Script_item_UUID] = obj; 4152 scriptedcontrols[Script_item_UUID] = obj;
4162 } 4153 }
4163 } 4154 }
4155
4164 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); 4156 ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
4165 } 4157 }
4166 4158
@@ -4351,29 +4343,6 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
4351 return(new Vector3(x,y,z)); 4343 return(new Vector3(x,y,z));
4352 } 4344 }
4353 4345
4354 public void SaveChangedAttachments()
4355 {
4356 // Need to copy this list because DetachToInventoryPrep mods it
4357 List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(GetAttachments().ToArray());
4358
4359 IAttachmentsModule attachmentsModule = m_scene.AttachmentsModule;
4360 if (attachmentsModule != null)
4361 {
4362 foreach (SceneObjectGroup grp in attachments)
4363 {
4364 if (grp.HasGroupChanged) // Resizer scripts?
4365 {
4366 grp.IsAttachment = false;
4367 grp.AbsolutePosition = grp.RootPart.AttachedPos;
4368// grp.DetachToInventoryPrep();
4369 attachmentsModule.UpdateKnownItem(ControllingClient,
4370 grp, grp.GetFromItemID(), grp.OwnerID);
4371 grp.IsAttachment = true;
4372 }
4373 }
4374 }
4375 }
4376
4377 private void CheckLandingPoint(ref Vector3 pos) 4346 private void CheckLandingPoint(ref Vector3 pos)
4378 { 4347 {
4379 // Never constrain lures 4348 // Never constrain lures
diff --git a/OpenSim/Region/Framework/Scenes/SceneViewer.cs b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
index 501487a..8a0d288 100644
--- a/OpenSim/Region/Framework/Scenes/SceneViewer.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneViewer.cs
@@ -38,27 +38,42 @@ namespace OpenSim.Region.Framework.Scenes
38{ 38{
39 public class SceneViewer : ISceneViewer 39 public class SceneViewer : ISceneViewer
40 { 40 {
41 /// <summary>
42 /// Is this scene viewer enabled?
43 /// </summary>
44 private bool IsEnabled { get; set; }
45
46 /// <summary>
47 /// The scene presence serviced by this viewer.
48 /// </summary>
41 protected ScenePresence m_presence; 49 protected ScenePresence m_presence;
50
51 /// <summary>
52 /// The queue of parts for which we need to send out updates.
53 /// </summary>
42 protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); 54 protected UpdateQueue m_partsUpdateQueue = new UpdateQueue();
55
56 /// <summary>
57 /// The queue of objects for which we need to send out updates.
58 /// </summary>
43 protected Queue<SceneObjectGroup> m_pendingObjects; 59 protected Queue<SceneObjectGroup> m_pendingObjects;
44 60
61 /// <summary>
62 /// The last update assocated with a given part update.
63 /// </summary>
45 protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>(); 64 protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
46 65
47 public SceneViewer()
48 {
49 }
50
51 public SceneViewer(ScenePresence presence) 66 public SceneViewer(ScenePresence presence)
52 { 67 {
53 m_presence = presence; 68 m_presence = presence;
69 IsEnabled = true;
54 } 70 }
55 71
56 /// <summary>
57 /// Add the part to the queue of parts for which we need to send an update to the client
58 /// </summary>
59 /// <param name="part"></param>
60 public void QueuePartForUpdate(SceneObjectPart part) 72 public void QueuePartForUpdate(SceneObjectPart part)
61 { 73 {
74 if (!IsEnabled)
75 return;
76
62 lock (m_partsUpdateQueue) 77 lock (m_partsUpdateQueue)
63 { 78 {
64 m_partsUpdateQueue.Enqueue(part); 79 m_partsUpdateQueue.Enqueue(part);
@@ -87,6 +102,11 @@ namespace OpenSim.Region.Framework.Scenes
87 102
88 lock (m_pendingObjects) 103 lock (m_pendingObjects)
89 { 104 {
105 // We must do this under lock so that we don't suffer a race condition if another thread closes the
106 // viewer
107 if (!IsEnabled)
108 return;
109
90 while (m_pendingObjects != null && m_pendingObjects.Count > 0) 110 while (m_pendingObjects != null && m_pendingObjects.Count > 0)
91 { 111 {
92 SceneObjectGroup g = m_pendingObjects.Dequeue(); 112 SceneObjectGroup g = m_pendingObjects.Dequeue();
@@ -119,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes
119 139
120 // We deal with the possibility that two updates occur at 140 // We deal with the possibility that two updates occur at
121 // the same unix time at the update point itself. 141 // the same unix time at the update point itself.
122
123 if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment) 142 if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment)
124 { 143 {
125 // m_log.DebugFormat( 144 // m_log.DebugFormat(
@@ -135,9 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
135 // this update. If this happened, then subsequent 154 // this update. If this happened, then subsequent
136 // updates which occurred on the same tick or the 155 // updates which occurred on the same tick or the
137 // next tick of the last update would be ignored. 156 // next tick of the last update would be ignored.
138
139 update.LastFullUpdateTime = part.TimeStampFull; 157 update.LastFullUpdateTime = part.TimeStampFull;
140
141 } 158 }
142 else if (update.LastTerseUpdateTime <= part.TimeStampTerse) 159 else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
143 { 160 {
@@ -176,38 +193,46 @@ namespace OpenSim.Region.Framework.Scenes
176 } 193 }
177 } 194 }
178 195
179 public void Reset() 196// public void Reset()
180 { 197// {
181 if (m_pendingObjects == null) 198// if (m_pendingObjects == null)
182 return; 199// return;
200//
201// lock (m_pendingObjects)
202// {
203// if (m_pendingObjects != null)
204// {
205// m_pendingObjects.Clear();
206// m_pendingObjects = null;
207// }
208// }
209// }
183 210
211 public void Close()
212 {
184 lock (m_pendingObjects) 213 lock (m_pendingObjects)
185 { 214 {
186 if (m_pendingObjects != null) 215 // We perform this under the m_pendingObjects lock in order to avoid a race condition with another
216 // thread on SendPrimUpdates()
217 IsEnabled = false;
218
219 lock (m_updateTimes)
187 { 220 {
188 m_pendingObjects.Clear(); 221 m_updateTimes.Clear();
189 m_pendingObjects = null;
190 } 222 }
191 }
192 }
193 223
194 public void Close() 224 lock (m_partsUpdateQueue)
195 { 225 {
196 lock (m_updateTimes) 226 m_partsUpdateQueue.Clear();
197 { 227 }
198 m_updateTimes.Clear();
199 }
200 lock (m_partsUpdateQueue)
201 {
202 m_partsUpdateQueue.Clear();
203 } 228 }
204 Reset();
205 } 229 }
206 230
207 public int GetPendingObjectsCount() 231 public int GetPendingObjectsCount()
208 { 232 {
209 if (m_pendingObjects != null) 233 if (m_pendingObjects != null)
210 return m_pendingObjects.Count; 234 lock (m_pendingObjects)
235 return m_pendingObjects.Count;
211 236
212 return 0; 237 return 0;
213 } 238 }
diff --git a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
index 1ea2329..80f198d 100644
--- a/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
+++ b/OpenSim/Region/Framework/Scenes/Tests/SceneObjectBasicTests.cs
@@ -52,22 +52,25 @@ namespace OpenSim.Region.Framework.Scenes.Tests
52 TestHelpers.InMethod(); 52 TestHelpers.InMethod();
53 53
54 Scene scene = SceneHelpers.SetupScene(); 54 Scene scene = SceneHelpers.SetupScene();
55 int partsToTestCount = 3;
55 56
56 string objName = "obj1"; 57 SceneObjectGroup so
57 UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); 58 = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
58 59 SceneObjectPart[] parts = so.Parts;
59 SceneObjectPart part
60 = new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
61 { Name = objName, UUID = objUuid };
62 60
63 Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part), false), Is.True); 61 Assert.That(scene.AddNewSceneObject(so, false), Is.True);
64 62 SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID);
65 SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid); 63 SceneObjectPart[] retrievedParts = retrievedSo.Parts;
66 64
67 //m_log.Debug("retrievedPart : {0}", retrievedPart); 65 //m_log.Debug("retrievedPart : {0}", retrievedPart);
68 // If the parts have the same UUID then we will consider them as one and the same 66 // If the parts have the same UUID then we will consider them as one and the same
69 Assert.That(retrievedPart.Name, Is.EqualTo(objName)); 67 Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount));
70 Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); 68
69 for (int i = 0; i < partsToTestCount; i++)
70 {
71 Assert.That(retrievedParts[i].Name, Is.EqualTo(parts[i].Name));
72 Assert.That(retrievedParts[i].UUID, Is.EqualTo(parts[i].UUID));
73 }
71 } 74 }
72 75
73 [Test] 76 [Test]
@@ -103,6 +106,39 @@ namespace OpenSim.Region.Framework.Scenes.Tests
103 Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name)); 106 Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name));
104 Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); 107 Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid));
105 } 108 }
109
110 /// <summary>
111 /// Test retrieving a scene object via the local id of one of its parts.
112 /// </summary>
113 [Test]
114 public void TestGetSceneObjectByPartLocalId()
115 {
116 TestHelpers.InMethod();
117
118 Scene scene = SceneHelpers.SetupScene();
119 int partsToTestCount = 3;
120
121 SceneObjectGroup so
122 = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
123 SceneObjectPart[] parts = so.Parts;
124
125 scene.AddNewSceneObject(so, false);
126
127 // Test getting via the root part's local id
128 Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Not.Null);
129
130 // Test getting via a non root part's local id
131 Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Not.Null);
132
133 // Test that we don't get back an object for a local id that doesn't exist
134 Assert.That(scene.GetGroupByPrim(999), Is.Null);
135
136 // Now delete the scene object and check again
137 scene.DeleteSceneObject(so, false);
138
139 Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Null);
140 Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Null);
141 }
106 142
107 /// <summary> 143 /// <summary>
108 /// Test deleting an object from a scene. 144 /// Test deleting an object from a scene.
diff --git a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
index fdfbc78..8d41f00 100644
--- a/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
+++ b/OpenSim/Region/Framework/Scenes/UuidGatherer.cs
@@ -43,11 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
43 /// <summary> 43 /// <summary>
44 /// Gather uuids for a given entity. 44 /// Gather uuids for a given entity.
45 /// </summary> 45 /// </summary>
46 /// 46 /// <remarks>
47 /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts 47 /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts
48 /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets 48 /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets
49 /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be 49 /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be
50 /// retrieved to work out which assets it references). 50 /// retrieved to work out which assets it references).
51 /// </remarks>
51 public class UuidGatherer 52 public class UuidGatherer
52 { 53 {
53 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 54 private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@@ -76,11 +77,11 @@ namespace OpenSim.Region.Framework.Scenes
76 /// <summary> 77 /// <summary>
77 /// Gather all the asset uuids associated with the asset referenced by a given uuid 78 /// Gather all the asset uuids associated with the asset referenced by a given uuid
78 /// </summary> 79 /// </summary>
79 /// 80 /// <remarks>
80 /// This includes both those directly associated with 81 /// This includes both those directly associated with
81 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained 82 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
82 /// within this object). 83 /// within this object).
83 /// 84 /// </remarks>
84 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> 85 /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
85 /// <param name="assetType">The type of the asset for the uuid given</param> 86 /// <param name="assetType">The type of the asset for the uuid given</param>
86 /// <param name="assetUuids">The assets gathered</param> 87 /// <param name="assetUuids">The assets gathered</param>
@@ -119,11 +120,11 @@ namespace OpenSim.Region.Framework.Scenes
119 /// <summary> 120 /// <summary>
120 /// Gather all the asset uuids associated with a given object. 121 /// Gather all the asset uuids associated with a given object.
121 /// </summary> 122 /// </summary>
122 /// 123 /// <remarks>
123 /// This includes both those directly associated with 124 /// This includes both those directly associated with
124 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained 125 /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
125 /// within this object). 126 /// within this object).
126 /// 127 /// </remarks>
127 /// <param name="sceneObject">The scene object for which to gather assets</param> 128 /// <param name="sceneObject">The scene object for which to gather assets</param>
128 /// <param name="assetUuids">The assets gathered</param> 129 /// <param name="assetUuids">The assets gathered</param>
129 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) 130 public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids)
diff --git a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
index 78296a4..246bc34 100644
--- a/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
+++ b/OpenSim/Region/OptionalModules/World/NPC/Tests/NPCModuleTests.cs
@@ -26,6 +26,7 @@
26 */ 26 */
27 27
28using System; 28using System;
29using System.Collections.Generic;
29using System.Reflection; 30using System.Reflection;
30using log4net; 31using log4net;
31using Nini.Config; 32using Nini.Config;
@@ -33,7 +34,9 @@ using NUnit.Framework;
33using OpenMetaverse; 34using OpenMetaverse;
34using OpenSim.Framework; 35using OpenSim.Framework;
35using OpenSim.Framework.Communications; 36using OpenSim.Framework.Communications;
37using OpenSim.Region.CoreModules.Avatar.Attachments;
36using OpenSim.Region.CoreModules.Avatar.AvatarFactory; 38using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
39using OpenSim.Region.CoreModules.Framework.InventoryAccess;
37using OpenSim.Region.CoreModules.Framework.UserManagement; 40using OpenSim.Region.CoreModules.Framework.UserManagement;
38using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar; 41using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar;
39using OpenSim.Region.Framework.Interfaces; 42using OpenSim.Region.Framework.Interfaces;
@@ -47,21 +50,49 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
47 [TestFixture] 50 [TestFixture]
48 public class NPCModuleTests 51 public class NPCModuleTests
49 { 52 {
50 [Test] 53 private TestScene scene;
51 public void TestCreate() 54 private AvatarFactoryModule afm;
55 private UserManagementModule umm;
56 private AttachmentsModule am;
57
58 [TestFixtureSetUp]
59 public void FixtureInit()
52 { 60 {
53 TestHelpers.InMethod(); 61 // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
54// log4net.Config.XmlConfigurator.Configure(); 62 Util.FireAndForgetMethod = FireAndForgetMethod.None;
63 }
55 64
65 [TestFixtureTearDown]
66 public void TearDown()
67 {
68 // We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
69 // threads. Possibly, later tests should be rewritten not to worry about such things.
70 Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
71 }
72
73 [SetUp]
74 public void Init()
75 {
56 IConfigSource config = new IniConfigSource(); 76 IConfigSource config = new IniConfigSource();
57 config.AddConfig("NPC"); 77 config.AddConfig("NPC");
58 config.Configs["NPC"].Set("Enabled", "true"); 78 config.Configs["NPC"].Set("Enabled", "true");
79 config.AddConfig("Modules");
80 config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
59 81
60 AvatarFactoryModule afm = new AvatarFactoryModule(); 82 afm = new AvatarFactoryModule();
61 UserManagementModule umm = new UserManagementModule(); 83 umm = new UserManagementModule();
84 am = new AttachmentsModule();
85
86 scene = SceneHelpers.SetupScene();
87 SceneHelpers.SetupSceneModules(scene, config, afm, umm, am, new BasicInventoryAccessModule(), new NPCModule());
88 }
89
90 [Test]
91 public void TestCreate()
92 {
93 TestHelpers.InMethod();
94// log4net.Config.XmlConfigurator.Configure();
62 95
63 TestScene scene = SceneHelpers.SetupScene();
64 SceneHelpers.SetupSceneModules(scene, config, afm, umm, new NPCModule());
65 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 96 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
66// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); 97// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
67 98
@@ -88,18 +119,53 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
88 } 119 }
89 120
90 [Test] 121 [Test]
91 public void TestMove() 122 public void TestAttachments()
92 { 123 {
93 TestHelpers.InMethod(); 124 TestHelpers.InMethod();
94// log4net.Config.XmlConfigurator.Configure(); 125// log4net.Config.XmlConfigurator.Configure();
95 126
96 IConfigSource config = new IniConfigSource(); 127 UUID userId = TestHelpers.ParseTail(0x1);
128 UserAccountHelpers.CreateUserWithInventory(scene, userId);
129 ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
97 130
98 config.AddConfig("NPC"); 131 UUID attItemId = TestHelpers.ParseTail(0x2);
99 config.Configs["NPC"].Set("Enabled", "true"); 132 UUID attAssetId = TestHelpers.ParseTail(0x3);
133 string attName = "att";
134
135 UserInventoryHelpers.CreateInventoryItem(
136 scene, attName, attItemId, attAssetId, sp.UUID, InventoryType.Object);
137
138 am.RezSingleAttachmentFromInventory(
139 sp.ControllingClient, attItemId, (uint)AttachmentPoint.Chest);
140
141 INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
142 UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance);
143
144 ScenePresence npc = scene.GetScenePresence(npcId);
145
146 // Check scene presence status
147 Assert.That(npc.HasAttachments(), Is.True);
148 List<SceneObjectGroup> attachments = npc.GetAttachments();
149 Assert.That(attachments.Count, Is.EqualTo(1));
150 SceneObjectGroup attSo = attachments[0];
151
152 // Just for now, we won't test the name since this is (wrongly) the asset part name rather than the item
153 // name. TODO: Do need to fix ultimately since the item may be renamed before being passed on to an NPC.
154// Assert.That(attSo.Name, Is.EqualTo(attName));
155
156 Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
157 Assert.That(attSo.IsAttachment);
158 Assert.That(attSo.UsesPhysics, Is.False);
159 Assert.That(attSo.IsTemporary, Is.False);
160 Assert.That(attSo.OwnerID, Is.EqualTo(npc.UUID));
161 }
162
163 [Test]
164 public void TestMove()
165 {
166 TestHelpers.InMethod();
167// log4net.Config.XmlConfigurator.Configure();
100 168
101 TestScene scene = SceneHelpers.SetupScene();
102 SceneHelpers.SetupSceneModules(scene, config, new NPCModule());
103 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); 169 ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
104// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); 170// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
105 171
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
index 6f34168..18c0dd2 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs
@@ -7040,6 +7040,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7040 7040
7041 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) 7041 protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
7042 { 7042 {
7043 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7043 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); 7044 ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
7044 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 7045 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7045 return shapeBlock; 7046 return shapeBlock;
@@ -7123,8 +7124,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7123 { 7124 {
7124 twist.y = 1.0f; 7125 twist.y = 1.0f;
7125 } 7126 }
7126 shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); 7127 // A fairly large precision error occurs for some calculations,
7127 shapeBlock.PathTwist = (sbyte)(100 * twist.y); 7128 // if a float or double is directly cast to a byte or sbyte
7129 // variable, in both .Net and Mono. In .Net, coding
7130 // "(sbyte)(float)(some expression)" corrects the precision
7131 // errors. But this does not work for Mono. This longer coding
7132 // form of creating a tempoary float variable from the
7133 // expression first, then casting that variable to a byte or
7134 // sbyte, works for both .Net and Mono. These types of
7135 // assignments occur in SetPrimtiveBlockShapeParams and
7136 // SetPrimitiveShapeParams in support of llSetPrimitiveParams.
7137 tempFloat = (float)(100.0d * twist.x);
7138 shapeBlock.PathTwistBegin = (sbyte)tempFloat;
7139 tempFloat = (float)(100.0d * twist.y);
7140 shapeBlock.PathTwist = (sbyte)tempFloat;
7128 7141
7129 shapeBlock.ObjectLocalID = part.LocalId; 7142 shapeBlock.ObjectLocalID = part.LocalId;
7130 7143
@@ -7138,6 +7151,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7138 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 7151 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7139 return; 7152 return;
7140 7153
7154 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7141 ObjectShapePacket.ObjectDataBlock shapeBlock; 7155 ObjectShapePacket.ObjectDataBlock shapeBlock;
7142 7156
7143 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7157 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7158,8 +7172,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7158 { 7172 {
7159 taper_b.y = 2f; 7173 taper_b.y = 2f;
7160 } 7174 }
7161 shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); 7175 tempFloat = (float)(100.0d * (2.0d - taper_b.x));
7162 shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); 7176 shapeBlock.PathScaleX = (byte)tempFloat;
7177 tempFloat = (float)(100.0d * (2.0d - taper_b.y));
7178 shapeBlock.PathScaleY = (byte)tempFloat;
7163 if (topshear.x < -0.5f) 7179 if (topshear.x < -0.5f)
7164 { 7180 {
7165 topshear.x = -0.5f; 7181 topshear.x = -0.5f;
@@ -7176,8 +7192,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7176 { 7192 {
7177 topshear.y = 0.5f; 7193 topshear.y = 0.5f;
7178 } 7194 }
7179 shapeBlock.PathShearX = (byte)(100 * topshear.x); 7195 tempFloat = (float)(100.0d * topshear.x);
7180 shapeBlock.PathShearY = (byte)(100 * topshear.y); 7196 shapeBlock.PathShearX = (byte)tempFloat;
7197 tempFloat = (float)(100.0d * topshear.y);
7198 shapeBlock.PathShearY = (byte)tempFloat;
7181 7199
7182 part.Shape.SculptEntry = false; 7200 part.Shape.SculptEntry = false;
7183 part.UpdateShape(shapeBlock); 7201 part.UpdateShape(shapeBlock);
@@ -7233,6 +7251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7233 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) 7251 if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
7234 return; 7252 return;
7235 7253
7254 float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
7236 ObjectShapePacket.ObjectDataBlock shapeBlock; 7255 ObjectShapePacket.ObjectDataBlock shapeBlock;
7237 7256
7238 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); 7257 shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@@ -7257,8 +7276,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7257 { 7276 {
7258 holesize.y = 0.5f; 7277 holesize.y = 0.5f;
7259 } 7278 }
7260 shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); 7279 tempFloat = (float)(100.0d * (2.0d - holesize.x));
7261 shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); 7280 shapeBlock.PathScaleX = (byte)tempFloat;
7281 tempFloat = (float)(100.0d * (2.0d - holesize.y));
7282 shapeBlock.PathScaleY = (byte)tempFloat;
7262 if (topshear.x < -0.5f) 7283 if (topshear.x < -0.5f)
7263 { 7284 {
7264 topshear.x = -0.5f; 7285 topshear.x = -0.5f;
@@ -7275,8 +7296,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7275 { 7296 {
7276 topshear.y = 0.5f; 7297 topshear.y = 0.5f;
7277 } 7298 }
7278 shapeBlock.PathShearX = (byte)(100 * topshear.x); 7299 tempFloat = (float)(100.0d * topshear.x);
7279 shapeBlock.PathShearY = (byte)(100 * topshear.y); 7300 shapeBlock.PathShearX = (byte)tempFloat;
7301 tempFloat = (float)(100.0d * topshear.y);
7302 shapeBlock.PathShearY = (byte)tempFloat;
7280 if (profilecut.x < 0f) 7303 if (profilecut.x < 0f)
7281 { 7304 {
7282 profilecut.x = 0f; 7305 profilecut.x = 0f;
@@ -7320,8 +7343,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7320 { 7343 {
7321 taper_a.y = 1f; 7344 taper_a.y = 1f;
7322 } 7345 }
7323 shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); 7346 tempFloat = (float)(100.0d * taper_a.x);
7324 shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); 7347 shapeBlock.PathTaperX = (sbyte)tempFloat;
7348 tempFloat = (float)(100.0d * taper_a.y);
7349 shapeBlock.PathTaperY = (sbyte)tempFloat;
7325 if (revolutions < 1f) 7350 if (revolutions < 1f)
7326 { 7351 {
7327 revolutions = 1f; 7352 revolutions = 1f;
@@ -7330,7 +7355,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7330 { 7355 {
7331 revolutions = 4f; 7356 revolutions = 4f;
7332 } 7357 }
7333 shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); 7358 tempFloat = 66.66667f * (revolutions - 1.0f);
7359 shapeBlock.PathRevolutions = (byte)tempFloat;
7334 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 7360 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
7335 if (radiusoffset < 0f) 7361 if (radiusoffset < 0f)
7336 { 7362 {
@@ -7340,7 +7366,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7340 { 7366 {
7341 radiusoffset = 1f; 7367 radiusoffset = 1f;
7342 } 7368 }
7343 shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); 7369 tempFloat = 100.0f * radiusoffset;
7370 shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
7344 if (skew < -0.95f) 7371 if (skew < -0.95f)
7345 { 7372 {
7346 skew = -0.95f; 7373 skew = -0.95f;
@@ -7349,7 +7376,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
7349 { 7376 {
7350 skew = 0.95f; 7377 skew = 0.95f;
7351 } 7378 }
7352 shapeBlock.PathSkew = (sbyte)(100 * skew); 7379 tempFloat = 100.0f * skew;
7380 shapeBlock.PathSkew = (sbyte)tempFloat;
7353 7381
7354 part.Shape.SculptEntry = false; 7382 part.Shape.SculptEntry = false;
7355 part.UpdateShape(shapeBlock); 7383 part.UpdateShape(shapeBlock);
@@ -8268,10 +8296,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
8268 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); 8296 res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
8269 8297
8270 // float revolutions 8298 // float revolutions
8271 res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned 8299 res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
8272 // byte is being used to represent the entire 8300 // Slightly inaccurate, because an unsigned byte is being used to represent
8273 // range of floating-point values from 1.0 8301 // the entire range of floating-point values from 1.0 through 4.0 (which is how
8274 // through 4.0 (which is how SL does it). 8302 // SL does it).
8303 //
8304 // Using these formulas to store and retrieve PathRevolutions, it is not
8305 // possible to use all values between 1.00 and 4.00. For instance, you can't
8306 // represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
8307 // use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
8308 // with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
8309 // behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
8310 // In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
8311 // such as 1.10. So, SL must store and retreive the actual user input rather
8312 // than only storing the encoded value.
8275 8313
8276 // float radiusoffset 8314 // float radiusoffset
8277 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); 8315 res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));
diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
index 0c1da47..8f450f8 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs
@@ -712,9 +712,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
712 == World.LandChannel.GetLandObject( 712 == World.LandChannel.GetLandObject(
713 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 713 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
714 { 714 {
715 World.RequestTeleportLocation(presence.ControllingClient, regionName, 715 // We will launch the teleport on a new thread so that when the script threads are terminated
716 new Vector3((float)position.x, (float)position.y, (float)position.z), 716 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
717 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); 717 Util.FireAndForget(
718 o => World.RequestTeleportLocation(presence.ControllingClient, regionName,
719 new Vector3((float)position.x, (float)position.y, (float)position.z),
720 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
718 721
719 ScriptSleep(5000); 722 ScriptSleep(5000);
720 } 723 }
@@ -750,9 +753,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
750 == World.LandChannel.GetLandObject( 753 == World.LandChannel.GetLandObject(
751 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) 754 presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
752 { 755 {
753 World.RequestTeleportLocation(presence.ControllingClient, regionHandle, 756 // We will launch the teleport on a new thread so that when the script threads are terminated
754 new Vector3((float)position.x, (float)position.y, (float)position.z), 757 // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
755 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); 758 Util.FireAndForget(
759 o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle,
760 new Vector3((float)position.x, (float)position.y, (float)position.z),
761 new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
762
756 ScriptSleep(5000); 763 ScriptSleep(5000);
757 } 764 }
758 } 765 }
diff --git a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
index 8cd1e84..0cbad41 100644
--- a/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
+++ b/OpenSim/Region/ScriptEngine/Shared/Tests/LSL_ApiTest.cs
@@ -49,7 +49,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
49 49
50 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6; 50 private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
51 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; 51 private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
52 private const double FLOAT_ACCURACY = 0.00005d; 52 private const float FLOAT_ACCURACY = 0.00005f;
53 private LSL_Api m_lslApi; 53 private LSL_Api m_lslApi;
54 54
55 [SetUp] 55 [SetUp]
@@ -194,10 +194,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
194 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type 194 ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
195 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type 195 ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
196 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut 196 new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
197 0.80d, // Prim hollow 197 0.80f, // Prim hollow
198 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist 198 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
199 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple 199 new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
200 0.80d); // Prim hollow check 200 0.80f); // Prim hollow check
201 201
202 // Test a prism. 202 // Test a prism.
203 CheckllSetPrimitiveParams( 203 CheckllSetPrimitiveParams(
@@ -206,11 +206,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
206 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type 206 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
207 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type 207 ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
208 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 208 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
209 0.90d, // Prim hollow 209 0.90f, // Prim hollow
210 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist 210 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
211 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper 211 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
212 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 212 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
213 0.90d); // Prim hollow check 213 0.90f); // Prim hollow check
214 214
215 // Test a box. 215 // Test a box.
216 CheckllSetPrimitiveParams( 216 CheckllSetPrimitiveParams(
@@ -219,11 +219,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
219 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type 219 ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
220 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type 220 ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
221 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 221 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
222 0.95d, // Prim hollow 222 0.95f, // Prim hollow
223 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist 223 new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
224 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper 224 new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
225 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 225 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
226 0.95d); // Prim hollow check 226 0.95f); // Prim hollow check
227 227
228 // Test a tube. 228 // Test a tube.
229 CheckllSetPrimitiveParams( 229 CheckllSetPrimitiveParams(
@@ -232,16 +232,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
232 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type 232 ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
233 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type 233 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
234 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 234 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
235 0.00d, // Prim hollow 235 0.00f, // Prim hollow
236 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist 236 new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
237 new LSL_Types.Vector3(1.0d, 0.5d, 0.0d), // Prim hole size 237 new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
238 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 238 // Expression for y selected to test precision problems during byte
239 // cast in SetPrimitiveShapeParams.
240 new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
239 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut 241 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
240 new LSL_Types.Vector3(-1.0d, 1.0d, 0.0d), // Prim taper 242 // Expression for y selected to test precision problems during sbyte
241 1.0d, // Prim revolutions 243 // cast in SetPrimitiveShapeParams.
242 1.0d, // Prim radius 244 new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
243 0.0d, // Prim skew 245 1.11f, // Prim revolutions
244 0.00d); // Prim hollow check 246 0.88f, // Prim radius
247 0.95f, // Prim skew
248 0.00f); // Prim hollow check
245 249
246 // Test a prism. 250 // Test a prism.
247 CheckllSetPrimitiveParams( 251 CheckllSetPrimitiveParams(
@@ -250,11 +254,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
250 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type 254 ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
251 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type 255 ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
252 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut 256 new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
253 0.95d, // Prim hollow 257 0.95f, // Prim hollow
254 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist 258 // Expression for x selected to test precision problems during sbyte
255 new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper 259 // cast in SetPrimitiveShapeBlockParams.
260 new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
261 // Expression for y selected to test precision problems during sbyte
262 // cast in SetPrimitiveShapeParams.
263 new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
256 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear 264 new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
257 0.70d); // Prim hollow check 265 0.70f); // Prim hollow check
258 266
259 // Test a sculpted prim. 267 // Test a sculpted prim.
260 CheckllSetPrimitiveParams( 268 CheckllSetPrimitiveParams(
@@ -268,8 +276,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
268 // Set prim params for a box, cylinder or prism and check results. 276 // Set prim params for a box, cylinder or prism and check results.
269 public void CheckllSetPrimitiveParams(string primTest, 277 public void CheckllSetPrimitiveParams(string primTest,
270 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, 278 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
271 double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, 279 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
272 double primHollowCheck) 280 float primHollowCheck)
273 { 281 {
274 // Set the prim params. 282 // Set the prim params.
275 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, 283 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@@ -297,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
297 // Set prim params for a sphere and check results. 305 // Set prim params for a sphere and check results.
298 public void CheckllSetPrimitiveParams(string primTest, 306 public void CheckllSetPrimitiveParams(string primTest,
299 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, 307 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
300 double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, double primHollowCheck) 308 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
301 { 309 {
302 // Set the prim params. 310 // Set the prim params.
303 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, 311 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@@ -324,9 +332,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
324 // Set prim params for a torus, tube or ring and check results. 332 // Set prim params for a torus, tube or ring and check results.
325 public void CheckllSetPrimitiveParams(string primTest, 333 public void CheckllSetPrimitiveParams(string primTest,
326 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, 334 LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
327 double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize, 335 float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
328 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper, 336 LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
329 double primRev, double primRadius, double primSkew, double primHollowCheck) 337 float primRev, float primRadius, float primSkew, float primHollowCheck)
330 { 338 {
331 // Set the prim params. 339 // Set the prim params.
332 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, 340 m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@@ -353,7 +361,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
353 CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut"); 361 CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
354 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper"); 362 CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
355 Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY, 363 Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
356 "TestllSetPrimitiveParams " + primTest + " prim revolution fail"); 364 "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
357 Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY, 365 Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
358 "TestllSetPrimitiveParams " + primTest + " prim radius fail"); 366 "TestllSetPrimitiveParams " + primTest + " prim radius fail");
359 Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY, 367 Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,
diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
index 9cb074a..975e9cc 100644
--- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
+++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs
@@ -409,7 +409,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
409 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), 409 m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup),
410 new Object[] { m_SaveTime }); 410 new Object[] { m_SaveTime });
411 } 411 }
412 }
412 413
414 public void StartProcessing()
415 {
413 m_ThreadPool.Start(); 416 m_ThreadPool.Start();
414 } 417 }
415 418
@@ -659,7 +662,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
659 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); 662 SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
660 if (part == null) 663 if (part == null)
661 { 664 {
662 m_log.Error("[Script] SceneObjectPart unavailable. Script NOT started."); 665 m_log.ErrorFormat("[Script]: SceneObjectPart with localID {0} unavailable. Script NOT started.", localID);
663 m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n"; 666 m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n";
664 m_ScriptFailCount++; 667 m_ScriptFailCount++;
665 return false; 668 return false;