If an attachment fails, then start logging the exception for now, in order to help with the inconsistent state bug.

This also refactors AttachmentsModules to stop pointlessly refetching the ScenePresence in various methods.  However, more of this is required.
bulletsim
Justin Clark-Casey (justincc) 2011-08-22 23:59:48 +01:00
parent 2eaadf2dc0
commit d328046efb
3 changed files with 84 additions and 61 deletions

View File

@ -105,6 +105,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
try try
{ {
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
if (sp == null)
{
m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Could not find presence for client {0} {1}", remoteClient.Name, remoteClient.AgentId);
return;
}
// If we can't take it, we can't attach it! // If we can't take it, we can't attach it!
SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID); SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID);
if (part == null) if (part == null)
@ -123,7 +132,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
AttachmentPt &= 0x7f; AttachmentPt &= 0x7f;
// Calls attach with a Zero position // Calls attach with a Zero position
if (AttachObject(remoteClient, part.ParentGroup, AttachmentPt, false)) if (AttachObject(sp, part.ParentGroup, AttachmentPt, false))
{ {
m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
@ -136,11 +145,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
} }
catch (Exception e) catch (Exception e)
{ {
m_log.DebugFormat("[ATTACHMENTS MODULE]: exception upon Attach Object {0}", e); m_log.ErrorFormat("[ATTACHMENTS MODULE]: exception upon Attach Object {0}{1}", e.Message, e.StackTrace);
} }
} }
public bool AttachObject(IClientAPI remoteClient, SceneObjectGroup group, uint AttachmentPt, bool silent) public bool AttachObject(IClientAPI remoteClient, SceneObjectGroup group, uint AttachmentPt, bool silent)
{
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
if (sp == null)
{
m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Could not find presence for client {0} {1}", remoteClient.Name, remoteClient.AgentId);
return false;
}
return AttachObject(sp, group, AttachmentPt, silent);
}
public bool AttachObject(ScenePresence sp, SceneObjectGroup group, uint AttachmentPt, bool silent)
{ {
Vector3 attachPos = group.AbsolutePosition; Vector3 attachPos = group.AbsolutePosition;
@ -175,32 +198,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
group.AbsolutePosition = attachPos; group.AbsolutePosition = attachPos;
// Remove any previous attachments // Remove any previous attachments
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
UUID itemID = UUID.Zero; UUID itemID = UUID.Zero;
if (sp != null) foreach (SceneObjectGroup grp in sp.Attachments)
{ {
foreach (SceneObjectGroup grp in sp.Attachments) if (grp.GetAttachmentPoint() == (byte)AttachmentPt)
{ {
if (grp.GetAttachmentPoint() == (byte)AttachmentPt) itemID = grp.GetFromItemID();
{ break;
itemID = grp.GetFromItemID();
break;
}
} }
if (itemID != UUID.Zero)
DetachSingleAttachmentToInv(itemID, remoteClient);
} }
if (itemID != UUID.Zero)
DetachSingleAttachmentToInv(itemID, sp);
if (group.GetFromItemID() == UUID.Zero) if (group.GetFromItemID() == UUID.Zero)
{ {
m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemID); m_scene.attachObjectAssetStore(sp.ControllingClient, group, sp.UUID, out itemID);
} }
else else
{ {
itemID = group.GetFromItemID(); itemID = group.GetFromItemID();
} }
ShowAttachInUserInventory(remoteClient, AttachmentPt, itemID, group); ShowAttachInUserInventory(sp, AttachmentPt, itemID, group);
AttachToAgent(sp, group, AttachmentPt, attachPos, silent); AttachToAgent(sp, group, AttachmentPt, attachPos, silent);
@ -230,18 +250,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}", // "[ATTACHMENTS MODULE]: Rezzing attachment to point {0} from item {1} for {2}",
// (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name); // (AttachmentPoint)AttachmentPt, itemID, remoteClient.Name);
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
if (sp == null)
{
m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()",
remoteClient.Name, remoteClient.AgentId);
return UUID.Zero;
}
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should // TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim // be removed when that functionality is implemented in opensim
AttachmentPt &= 0x7f; AttachmentPt &= 0x7f;
SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(remoteClient, itemID, AttachmentPt); SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, AttachmentPt);
if (updateInventoryStatus) if (updateInventoryStatus)
{ {
if (att == null) if (att == null)
ShowDetachInUserInventory(itemID, remoteClient); ShowDetachInUserInventory(itemID, sp.ControllingClient);
else else
ShowAttachInUserInventory(att, remoteClient, itemID, AttachmentPt); ShowAttachInUserInventory(att, sp, itemID, AttachmentPt);
} }
if (null == att) if (null == att)
@ -250,15 +280,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return att.UUID; return att.UUID;
} }
protected SceneObjectGroup RezSingleAttachmentFromInventoryInternal( private SceneObjectGroup RezSingleAttachmentFromInventoryInternal(
IClientAPI remoteClient, UUID itemID, uint AttachmentPt) ScenePresence sp, UUID itemID, uint AttachmentPt)
{ {
IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
if (invAccess != null) if (invAccess != null)
{ {
SceneObjectGroup objatt = invAccess.RezObject(remoteClient, SceneObjectGroup objatt = invAccess.RezObject(sp.ControllingClient,
itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true, itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
false, false, remoteClient.AgentId, true); false, false, sp.UUID, true);
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}", // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
@ -277,10 +307,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// This will throw if the attachment fails // This will throw if the attachment fails
try try
{ {
AttachObject(remoteClient, objatt, AttachmentPt, false); AttachObject(sp, objatt, AttachmentPt, false);
} }
catch catch (Exception e)
{ {
m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Failed to attach {0} {1} for {2}, exception {3}{4}",
objatt.Name, objatt.UUID, sp.Name, e.Message, e.StackTrace);
// Make sure the object doesn't stick around and bail // Make sure the object doesn't stick around and bail
m_scene.DeleteSceneObject(objatt, false); m_scene.DeleteSceneObject(objatt, false);
return null; return null;
@ -295,13 +329,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
objatt.ResumeScripts(); objatt.ResumeScripts();
// Do this last so that event listeners have access to all the effects of the attachment // Do this last so that event listeners have access to all the effects of the attachment
m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, remoteClient.AgentId); m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
} }
else else
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}", "[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
itemID, remoteClient.Name, AttachmentPt); itemID, sp.Name, AttachmentPt);
} }
return objatt; return objatt;
@ -314,12 +348,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// Update the user inventory to the attachment of an item /// Update the user inventory to the attachment of an item
/// </summary> /// </summary>
/// <param name="att"></param> /// <param name="att"></param>
/// <param name="remoteClient"></param> /// <param name="sp"></param>
/// <param name="itemID"></param> /// <param name="itemID"></param>
/// <param name="AttachmentPt"></param> /// <param name="AttachmentPt"></param>
/// <returns></returns> /// <returns></returns>
protected UUID ShowAttachInUserInventory( private UUID ShowAttachInUserInventory(
SceneObjectGroup att, IClientAPI remoteClient, UUID itemID, uint AttachmentPt) SceneObjectGroup att, ScenePresence sp, UUID itemID, uint AttachmentPt)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Updating inventory of {0} to show attachment of {1} (item ID {2})", // "[ATTACHMENTS MODULE]: Updating inventory of {0} to show attachment of {1} (item ID {2})",
@ -328,16 +362,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (!att.IsDeleted) if (!att.IsDeleted)
AttachmentPt = att.RootPart.AttachmentPoint; AttachmentPt = att.RootPart.AttachmentPoint;
ScenePresence presence; InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) item = m_scene.InventoryService.GetItem(item);
{
InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
item = m_scene.InventoryService.GetItem(item);
bool changed = presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID); bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
if (changed && m_scene.AvatarFactory != null) if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
}
return att.UUID; return att.UUID;
} }
@ -345,12 +375,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// <summary> /// <summary>
/// Update the user inventory to reflect an attachment /// Update the user inventory to reflect an attachment
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="sp"></param>
/// <param name="AttachmentPt"></param> /// <param name="AttachmentPt"></param>
/// <param name="itemID"></param> /// <param name="itemID"></param>
/// <param name="att"></param> /// <param name="att"></param>
protected void ShowAttachInUserInventory( private void ShowAttachInUserInventory(
IClientAPI remoteClient, uint AttachmentPt, UUID itemID, SceneObjectGroup att) ScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}", // "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
@ -374,16 +404,11 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return; return;
} }
ScenePresence presence; InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) item = m_scene.InventoryService.GetItem(item);
{ bool changed = sp.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
// XXYY!! if (changed && m_scene.AvatarFactory != null)
InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
item = m_scene.InventoryService.GetItem(item);
bool changed = presence.Appearance.SetAttachment((int)AttachmentPt, itemID, item.AssetID);
if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
}
} }
public void DetachObject(uint objectLocalID, IClientAPI remoteClient) public void DetachObject(uint objectLocalID, IClientAPI remoteClient)
@ -407,9 +432,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
bool changed = presence.Appearance.DetachAttachment(itemID); bool changed = presence.Appearance.DetachAttachment(itemID);
if (changed && m_scene.AvatarFactory != null) if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
}
DetachSingleAttachmentToInv(itemID, remoteClient); DetachSingleAttachmentToInv(itemID, presence);
}
} }
public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient) public void DetachSingleAttachmentToGround(UUID itemID, IClientAPI remoteClient)
@ -447,7 +472,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards. // What makes this method odd and unique is it tries to detach using an UUID.... Yay for standards.
// To LocalId or UUID, *THAT* is the question. How now Brown UUID?? // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
protected void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient) private void DetachSingleAttachmentToInv(UUID itemID, ScenePresence sp)
{ {
if (itemID == UUID.Zero) // If this happened, someone made a mistake.... if (itemID == UUID.Zero) // If this happened, someone made a mistake....
return; return;
@ -474,7 +499,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
if (p.Inventory.ContainsScripts()) if (p.Inventory.ContainsScripts())
group.HasGroupChanged = true; group.HasGroupChanged = true;
UpdateKnownItem(remoteClient, group, group.GetFromItemID(), group.OwnerID); UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID);
m_scene.DeleteSceneObject(group, false); m_scene.DeleteSceneObject(group, false);
return; return;
} }

View File

@ -49,11 +49,9 @@ namespace OpenSim.Region.Framework.Interfaces
/// <summary> /// <summary>
/// Attach an object to an avatar. /// Attach an object to an avatar.
/// </summary> /// </summary>
/// <param name="controllingClient"></param> /// <param name="remoteClient"></param>
/// <param name="localID"></param> /// <param name="grp"></param>
/// <param name="attachPoint"></param> /// <param name="AttachmentPt"></param>
/// <param name="rot"></param>
/// <param name="attachPos"></param>
/// <param name="silent"></param> /// <param name="silent"></param>
/// <returns>true if the object was successfully attached, false otherwise</returns> /// <returns>true if the object was successfully attached, false otherwise</returns>
bool AttachObject( bool AttachObject(