Fix llAttachToAvatar()
Apart from one obvious bug, this was failing because attempting to serialize the script from inside the script (as part of saving the attachment as an inventory asset) was triggering an extremely long delay. So we now don't do this. The state will be serialized anyway when the avatar normally logs out. The worst that can happen is that if the client/server crashes, the attachment scripts start without previous state.bulletsim
parent
97b207240e
commit
cf3ffe5bb4
|
@ -101,7 +101,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
/// <param name="silent"></param>
|
/// <param name="silent"></param>
|
||||||
public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
|
public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent)
|
||||||
{
|
{
|
||||||
// m_log.Debug("[ATTACHMENTS MODULE]: Invoking AttachObject");
|
// m_log.DebugFormat(
|
||||||
|
// "[ATTACHMENTS MODULE]: Attaching object local id {0} to {1} point {2} from ground (silent = {3})",
|
||||||
|
// objectLocalID, remoteClient.Name, AttachmentPt, silent);
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
@ -163,8 +165,21 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
return AttachObject(sp, group, AttachmentPt, silent);
|
return AttachObject(sp, group, AttachmentPt, silent);
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool AttachObject(ScenePresence sp, SceneObjectGroup group, uint AttachmentPt, bool silent)
|
private bool AttachObject(ScenePresence sp, SceneObjectGroup group, uint AttachmentPt, bool silent)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat(
|
||||||
|
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
|
||||||
|
// group.Name, group.LocalId, sp.Name, AttachmentPt, silent);
|
||||||
|
|
||||||
|
if (sp.GetAttachments(AttachmentPt).Contains(group))
|
||||||
|
{
|
||||||
|
// m_log.WarnFormat(
|
||||||
|
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
|
||||||
|
// group.Name, group.LocalId, sp.Name, AttachmentPt);
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
Vector3 attachPos = group.AbsolutePosition;
|
Vector3 attachPos = group.AbsolutePosition;
|
||||||
|
|
||||||
// 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
|
||||||
|
@ -211,14 +226,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
if (itemID != UUID.Zero)
|
if (itemID != UUID.Zero)
|
||||||
DetachSingleAttachmentToInv(itemID, sp);
|
DetachSingleAttachmentToInv(itemID, sp);
|
||||||
|
|
||||||
if (group.GetFromItemID() == UUID.Zero)
|
|
||||||
{
|
|
||||||
m_scene.attachObjectAssetStore(sp.ControllingClient, group, sp.UUID, out itemID);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
itemID = group.GetFromItemID();
|
itemID = group.GetFromItemID();
|
||||||
}
|
if (itemID == UUID.Zero)
|
||||||
|
m_scene.attachObjectAssetStore(sp.ControllingClient, group, sp.UUID, out itemID);
|
||||||
|
|
||||||
ShowAttachInUserInventory(sp, AttachmentPt, itemID, group);
|
ShowAttachInUserInventory(sp, AttachmentPt, itemID, group);
|
||||||
|
|
||||||
|
@ -548,7 +558,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
|
||||||
"[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
|
"[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
|
||||||
grp.UUID, grp.GetAttachmentPoint());
|
grp.UUID, grp.GetAttachmentPoint());
|
||||||
|
|
||||||
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
|
// If we're being called from a script, then trying to serialize that same script's state will not complete
|
||||||
|
// in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
|
||||||
|
// the client/server crashes rather than logging out normally, the attachment's scripts will resume
|
||||||
|
// without state on relog. Arguably, this is what we want anyway.
|
||||||
|
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false);
|
||||||
|
|
||||||
InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
|
InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId);
|
||||||
item = m_scene.InventoryService.GetItem(item);
|
item = m_scene.InventoryService.GetItem(item);
|
||||||
|
|
||||||
|
|
|
@ -1873,6 +1873,8 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
|
|
||||||
public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
|
public UUID attachObjectAssetStore(IClientAPI remoteClient, SceneObjectGroup grp, UUID AgentId, out UUID itemID)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[SCENE]: Called attachObjectAssetStore for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId);
|
||||||
|
|
||||||
itemID = UUID.Zero;
|
itemID = UUID.Zero;
|
||||||
if (grp != null)
|
if (grp != null)
|
||||||
{
|
{
|
||||||
|
@ -1881,16 +1883,20 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
? 250
|
? 250
|
||||||
: grp.AbsolutePosition.X)
|
: grp.AbsolutePosition.X)
|
||||||
,
|
,
|
||||||
(grp.AbsolutePosition.X > (int)Constants.RegionSize)
|
(grp.AbsolutePosition.Y > (int)Constants.RegionSize)
|
||||||
? 250
|
? 250
|
||||||
: grp.AbsolutePosition.X,
|
: grp.AbsolutePosition.Y,
|
||||||
grp.AbsolutePosition.Z);
|
grp.AbsolutePosition.Z);
|
||||||
|
|
||||||
Vector3 originalPosition = grp.AbsolutePosition;
|
Vector3 originalPosition = grp.AbsolutePosition;
|
||||||
|
|
||||||
grp.AbsolutePosition = inventoryStoredPosition;
|
grp.AbsolutePosition = inventoryStoredPosition;
|
||||||
|
|
||||||
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
|
// If we're being called from a script, then trying to serialize that same script's state will not complete
|
||||||
|
// in any reasonable time period. Therefore, we'll avoid it. The worst that can happen is that if
|
||||||
|
// the client/server crashes rather than logging out normally, the attachment's scripts will resume
|
||||||
|
// without state on relog. Arguably, this is what we want anyway.
|
||||||
|
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp, false);
|
||||||
|
|
||||||
grp.AbsolutePosition = originalPosition;
|
grp.AbsolutePosition = originalPosition;
|
||||||
|
|
||||||
|
@ -1900,6 +1906,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
(sbyte)AssetType.Object,
|
(sbyte)AssetType.Object,
|
||||||
Utils.StringToBytes(sceneObjectXml),
|
Utils.StringToBytes(sceneObjectXml),
|
||||||
remoteClient.AgentId);
|
remoteClient.AgentId);
|
||||||
|
|
||||||
AssetService.Store(asset);
|
AssetService.Store(asset);
|
||||||
|
|
||||||
InventoryItemBase item = new InventoryItemBase();
|
InventoryItemBase item = new InventoryItemBase();
|
||||||
|
@ -1948,6 +1955,7 @@ namespace OpenSim.Region.Framework.Scenes
|
||||||
itemID = item.ID;
|
itemID = item.ID;
|
||||||
return item.AssetID;
|
return item.AssetID;
|
||||||
}
|
}
|
||||||
|
|
||||||
return UUID.Zero;
|
return UUID.Zero;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -126,27 +126,37 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
/// <param name="sceneObject"></param>
|
/// <param name="sceneObject"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static string ToOriginalXmlFormat(SceneObjectGroup sceneObject)
|
public static string ToOriginalXmlFormat(SceneObjectGroup sceneObject)
|
||||||
|
{
|
||||||
|
return ToOriginalXmlFormat(sceneObject, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Serialize a scene object to the original xml format
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="sceneObject"></param>
|
||||||
|
/// <param name="doScriptStates">Control whether script states are also serialized.</para>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static string ToOriginalXmlFormat(SceneObjectGroup sceneObject, bool doScriptStates)
|
||||||
{
|
{
|
||||||
using (StringWriter sw = new StringWriter())
|
using (StringWriter sw = new StringWriter())
|
||||||
{
|
{
|
||||||
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
using (XmlTextWriter writer = new XmlTextWriter(sw))
|
||||||
{
|
{
|
||||||
ToOriginalXmlFormat(sceneObject, writer);
|
ToOriginalXmlFormat(sceneObject, writer, doScriptStates);
|
||||||
}
|
}
|
||||||
|
|
||||||
return sw.ToString();
|
return sw.ToString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Serialize a scene object to the original xml format
|
/// Serialize a scene object to the original xml format
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="sceneObject"></param>
|
/// <param name="sceneObject"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer)
|
public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer, bool doScriptStates)
|
||||||
{
|
{
|
||||||
ToOriginalXmlFormat(sceneObject, writer, false);
|
ToOriginalXmlFormat(sceneObject, writer, doScriptStates, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -156,10 +166,11 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
/// <param name="writer"></param>
|
/// <param name="writer"></param>
|
||||||
/// <param name="noRootElement">If false, don't write the enclosing SceneObjectGroup element</param>
|
/// <param name="noRootElement">If false, don't write the enclosing SceneObjectGroup element</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static void ToOriginalXmlFormat(SceneObjectGroup sceneObject, XmlTextWriter writer, bool noRootElement)
|
public static void ToOriginalXmlFormat(
|
||||||
|
SceneObjectGroup sceneObject, XmlTextWriter writer, bool doScriptStates, bool noRootElement)
|
||||||
{
|
{
|
||||||
//m_log.DebugFormat("[SERIALIZER]: Starting serialization of {0}", Name);
|
// m_log.DebugFormat("[SERIALIZER]: Starting serialization of {0}", sceneObject.Name);
|
||||||
//int time = System.Environment.TickCount;
|
// int time = System.Environment.TickCount;
|
||||||
|
|
||||||
if (!noRootElement)
|
if (!noRootElement)
|
||||||
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
|
writer.WriteStartElement(String.Empty, "SceneObjectGroup", String.Empty);
|
||||||
|
@ -182,12 +193,14 @@ namespace OpenSim.Region.Framework.Scenes.Serialization
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.WriteEndElement(); // OtherParts
|
writer.WriteEndElement(); // OtherParts
|
||||||
|
|
||||||
|
if (doScriptStates)
|
||||||
sceneObject.SaveScriptedState(writer);
|
sceneObject.SaveScriptedState(writer);
|
||||||
|
|
||||||
if (!noRootElement)
|
if (!noRootElement)
|
||||||
writer.WriteEndElement(); // SceneObjectGroup
|
writer.WriteEndElement(); // SceneObjectGroup
|
||||||
|
|
||||||
//m_log.DebugFormat("[SERIALIZER]: Finished serialization of SOG {0}, {1}ms", Name, System.Environment.TickCount - time);
|
// m_log.DebugFormat("[SERIALIZER]: Finished serialization of SOG {0}, {1}ms", sceneObject.Name, System.Environment.TickCount - time);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected static void ToXmlFormat(SceneObjectPart part, XmlTextWriter writer)
|
protected static void ToXmlFormat(SceneObjectPart part, XmlTextWriter writer)
|
||||||
|
|
|
@ -58,7 +58,11 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IScriptInstance
|
public interface IScriptInstance
|
||||||
{
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Is this script currently running?
|
||||||
|
/// </summary>
|
||||||
bool Running { get; set; }
|
bool Running { get; set; }
|
||||||
|
|
||||||
bool ShuttingDown { get; set; }
|
bool ShuttingDown { get; set; }
|
||||||
string State { get; set; }
|
string State { get; set; }
|
||||||
IScriptEngine Engine { get; }
|
IScriptEngine Engine { get; }
|
||||||
|
@ -78,7 +82,14 @@ namespace OpenSim.Region.ScriptEngine.Interfaces
|
||||||
|
|
||||||
void Init();
|
void Init();
|
||||||
void Start();
|
void Start();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop the script.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="timeout"></param>
|
||||||
|
/// <returns>true if the script was successfully stopped, false otherwise</returns>
|
||||||
bool Stop(int timeout);
|
bool Stop(int timeout);
|
||||||
|
|
||||||
void SetState(string state);
|
void SetState(string state);
|
||||||
|
|
||||||
void PostEvent(EventParams data);
|
void PostEvent(EventParams data);
|
||||||
|
|
|
@ -2964,8 +2964,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
|
||||||
{
|
{
|
||||||
m_host.AddScriptLPS(1);
|
m_host.AddScriptLPS(1);
|
||||||
|
|
||||||
if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
|
// if (m_host.ParentGroup.RootPart.AttachmentPoint == 0)
|
||||||
return;
|
// return;
|
||||||
|
|
||||||
TaskInventoryItem item;
|
TaskInventoryItem item;
|
||||||
|
|
||||||
|
|
|
@ -1294,9 +1294,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
|
|
||||||
public string GetXMLState(UUID itemID)
|
public string GetXMLState(UUID itemID)
|
||||||
{
|
{
|
||||||
|
// m_log.DebugFormat("[XEngine]: Getting XML state for {0}", itemID);
|
||||||
|
|
||||||
IScriptInstance instance = GetInstance(itemID);
|
IScriptInstance instance = GetInstance(itemID);
|
||||||
if (instance == null)
|
if (instance == null)
|
||||||
|
{
|
||||||
|
// m_log.DebugFormat("[XEngine]: Found no script for {0}, returning empty string", itemID);
|
||||||
return "";
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
string xml = instance.GetXMLState();
|
string xml = instance.GetXMLState();
|
||||||
|
|
||||||
XmlDocument sdoc = new XmlDocument();
|
XmlDocument sdoc = new XmlDocument();
|
||||||
|
@ -1437,6 +1443,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine
|
||||||
mapData.InnerText = map;
|
mapData.InnerText = map;
|
||||||
|
|
||||||
stateData.AppendChild(mapData);
|
stateData.AppendChild(mapData);
|
||||||
|
|
||||||
|
// m_log.DebugFormat("[XEngine]: Got XML state for {0}", itemID);
|
||||||
|
|
||||||
return doc.InnerXml;
|
return doc.InnerXml;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue