Bring us up to date.

avinationmerge
Tom 2011-09-14 19:11:32 -07:00
commit 5484c9b585
49 changed files with 1324 additions and 632 deletions

View File

@ -117,6 +117,7 @@ what it is today.
* nornalbion * nornalbion
* Omar Vera Ustariz (IBM) * Omar Vera Ustariz (IBM)
* openlifegrid.com * openlifegrid.com
* Oren Hurvitz (Kitely)
* otakup0pe * otakup0pe
* ralphos * ralphos
* RemedyTomm * RemedyTomm

View File

@ -812,6 +812,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// ok, client wants us to use an explicit UUID // ok, client wants us to use an explicit UUID
// regardless of what the avatar name provided // regardless of what the avatar name provided
userID = new UUID((string) requestData["estate_owner_uuid"]); userID = new UUID((string) requestData["estate_owner_uuid"]);
// Check that the specified user exists
Scene currentOrFirst = m_application.SceneManager.CurrentOrFirstScene;
IUserAccountService accountService = currentOrFirst.UserAccountService;
UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, userID);
if (user == null)
throw new Exception("Specified user was not found.");
} }
else if (requestData.ContainsKey("estate_owner_first") & requestData.ContainsKey("estate_owner_last")) else if (requestData.ContainsKey("estate_owner_first") & requestData.ContainsKey("estate_owner_last"))
{ {
@ -823,6 +831,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
IUserAccountService accountService = currentOrFirst.UserAccountService; IUserAccountService accountService = currentOrFirst.UserAccountService;
UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID, UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID,
ownerFirst, ownerLast); ownerFirst, ownerLast);
// Check that the specified user exists
if (user == null)
throw new Exception("Specified user was not found.");
userID = user.PrincipalID; userID = user.PrincipalID;
} }
else else

View File

@ -47,7 +47,6 @@ using Caps = OpenSim.Framework.Capabilities.Caps;
namespace OpenSim.Capabilities.Handlers namespace OpenSim.Capabilities.Handlers
{ {
public class GetTextureHandler : BaseStreamHandler public class GetTextureHandler : BaseStreamHandler
{ {
private static readonly ILog m_log = private static readonly ILog m_log =
@ -67,7 +66,6 @@ namespace OpenSim.Capabilities.Handlers
public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse) public override byte[] Handle(string path, Stream request, OSHttpRequest httpRequest, OSHttpResponse httpResponse)
{ {
// Try to parse the texture ID from the request URL // Try to parse the texture ID from the request URL
NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query); NameValueCollection query = HttpUtility.ParseQueryString(httpRequest.Url.Query);
string textureStr = query.GetOne("texture_id"); string textureStr = query.GetOne("texture_id");
@ -85,6 +83,8 @@ namespace OpenSim.Capabilities.Handlers
UUID textureID; UUID textureID;
if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID)) if (!String.IsNullOrEmpty(textureStr) && UUID.TryParse(textureStr, out textureID))
{ {
// m_log.DebugFormat("[GETTEXTURE]: Received request for texture id {0}", textureID);
string[] formats; string[] formats;
if (format != null && format != string.Empty) if (format != null && format != string.Empty)
{ {
@ -105,7 +105,6 @@ namespace OpenSim.Capabilities.Handlers
if (FetchTexture(httpRequest, httpResponse, textureID, f)) if (FetchTexture(httpRequest, httpResponse, textureID, f))
break; break;
} }
} }
else else
{ {

View File

@ -1209,7 +1209,6 @@ namespace OpenSim.Data.MySQL
return prim; return prim;
} }
/// <summary> /// <summary>
/// Build a prim inventory item from the persisted data. /// Build a prim inventory item from the persisted data.
/// </summary> /// </summary>

View File

@ -59,19 +59,23 @@ namespace OpenSim.Data.Null
public void StoreRegionSettings(RegionSettings rs) public void StoreRegionSettings(RegionSettings rs)
{ {
} }
public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID) public RegionLightShareData LoadRegionWindlightSettings(UUID regionUUID)
{ {
//This connector doesn't support the windlight module yet //This connector doesn't support the windlight module yet
//Return default LL windlight settings //Return default LL windlight settings
return new RegionLightShareData(); return new RegionLightShareData();
} }
public void RemoveRegionWindlightSettings(UUID regionID) public void RemoveRegionWindlightSettings(UUID regionID)
{ {
} }
public void StoreRegionWindlightSettings(RegionLightShareData wl) public void StoreRegionWindlightSettings(RegionLightShareData wl)
{ {
//This connector doesn't support the windlight module yet //This connector doesn't support the windlight module yet
} }
public RegionSettings LoadRegionSettings(UUID regionUUID) public RegionSettings LoadRegionSettings(UUID regionUUID)
{ {
return null; return null;

View File

@ -405,31 +405,40 @@ namespace OpenSim.Framework
/// </remarks> /// </remarks>
public List<AvatarAttachment> GetAttachments() public List<AvatarAttachment> GetAttachments()
{ {
lock (m_attachments) lock (m_attachments)
{ {
List<AvatarAttachment> alist = new List<AvatarAttachment>(); List<AvatarAttachment> alist = new List<AvatarAttachment>();
foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments) foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
{ {
foreach (AvatarAttachment attach in kvp.Value) foreach (AvatarAttachment attach in kvp.Value)
alist.Add(new AvatarAttachment(attach)); alist.Add(new AvatarAttachment(attach));
} }
return alist;
return alist; } }
}
}
internal void AppendAttachment(AvatarAttachment attach) internal void AppendAttachment(AvatarAttachment attach)
{ {
// m_log.DebugFormat(
// "[AVATAR APPEARNCE]: Appending itemID={0}, assetID={1} at {2}",
// attach.ItemID, attach.AssetID, attach.AttachPoint);
lock (m_attachments) lock (m_attachments)
{ {
if (!m_attachments.ContainsKey(attach.AttachPoint)) if (!m_attachments.ContainsKey(attach.AttachPoint))
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>(); m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
m_attachments[attach.AttachPoint].Add(attach); m_attachments[attach.AttachPoint].Add(attach);
} }
} }
internal void ReplaceAttachment(AvatarAttachment attach) internal void ReplaceAttachment(AvatarAttachment attach)
{ {
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Replacing itemID={0}, assetID={1} at {2}",
// attach.ItemID, attach.AssetID, attach.AttachPoint);
lock (m_attachments) lock (m_attachments)
{ {
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>(); m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
@ -438,7 +447,7 @@ namespace OpenSim.Framework
} }
/// <summary> /// <summary>
/// Add an attachment /// Set an attachment
/// </summary> /// </summary>
/// <remarks> /// <remarks>
/// If the attachpoint has the /// If the attachpoint has the
@ -454,13 +463,13 @@ namespace OpenSim.Framework
/// </returns> /// </returns>
public bool SetAttachment(int attachpoint, UUID item, UUID asset) public bool SetAttachment(int attachpoint, UUID item, UUID asset)
{ {
if (attachpoint == 0)
return false;
// m_log.DebugFormat( // m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Setting attachment at {0} with item ID {1}, asset ID {2}", // "[AVATAR APPEARANCE]: Setting attachment at {0} with item ID {1}, asset ID {2}",
// attachpoint, item, asset); // attachpoint, item, asset);
if (attachpoint == 0)
return false;
if (item == UUID.Zero) if (item == UUID.Zero)
{ {
lock (m_attachments) lock (m_attachments)
@ -470,12 +479,21 @@ namespace OpenSim.Framework
m_attachments.Remove(attachpoint); m_attachments.Remove(attachpoint);
return true; return true;
} }
return false;
} }
return false;
} }
// check if the item is already attached at this point // When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
if (GetAttachpoint(item) == (attachpoint & 0x7F)) // the asset ids are not saved. When the avatar enters a simulator the attachments are set again. If
// we simply perform an item check here then the asset ids (which are now present) are never set, and NPC attachments
// later fail unless the attachment is detached and reattached.
//
// Therefore, we will carry on with the set if the existing attachment has no asset id.
AvatarAttachment existingAttachment = GetAttachmentForItem(item);
if (existingAttachment != null
&& existingAttachment.AssetID != UUID.Zero
&& existingAttachment.AttachPoint == (attachpoint & 0x7F))
{ {
// m_log.DebugFormat("[AVATAR APPEARANCE] attempt to attach an already attached item {0}",item); // m_log.DebugFormat("[AVATAR APPEARANCE] attempt to attach an already attached item {0}",item);
return false; return false;
@ -492,9 +510,30 @@ namespace OpenSim.Framework
{ {
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset)); ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
} }
return true; return true;
} }
/// <summary>
/// If the item is already attached, return it.
/// </summary>
/// <param name="itemID"></param>
/// <returns>Returns null if this item is not attached.</returns>
public AvatarAttachment GetAttachmentForItem(UUID itemID)
{
lock (m_attachments)
{
foreach (KeyValuePair<int, List<AvatarAttachment>> kvp in m_attachments)
{
int index = kvp.Value.FindIndex(delegate(AvatarAttachment a) { return a.ItemID == itemID; });
if (index >= 0)
return kvp.Value[index];
}
}
return null;
}
public int GetAttachpoint(UUID itemID) public int GetAttachpoint(UUID itemID)
{ {
lock (m_attachments) lock (m_attachments)
@ -505,9 +544,8 @@ namespace OpenSim.Framework
if (index >= 0) if (index >= 0)
return kvp.Key; return kvp.Key;
} }
return 0;
} }
return 0;
} }
public bool DetachAttachment(UUID itemID) public bool DetachAttachment(UUID itemID)
@ -521,23 +559,23 @@ namespace OpenSim.Framework
{ {
// Remove it from the list of attachments at that attach point // Remove it from the list of attachments at that attach point
m_attachments[kvp.Key].RemoveAt(index); m_attachments[kvp.Key].RemoveAt(index);
// And remove the list if there are no more attachments here // And remove the list if there are no more attachments here
if (m_attachments[kvp.Key].Count == 0) if (m_attachments[kvp.Key].Count == 0)
m_attachments.Remove(kvp.Key); m_attachments.Remove(kvp.Key);
return true; return true;
} }
} }
} }
return false; return false;
} }
public void ClearAttachments() public void ClearAttachments()
{ {
lock (m_attachments) lock (m_attachments)
{
m_attachments.Clear(); m_attachments.Clear();
}
} }
#region Packing Functions #region Packing Functions

View File

@ -441,7 +441,6 @@ namespace OpenSim.Framework
args["controllers"] = controls; args["controllers"] = controls;
} }
if ((CallbackURI != null) && (!CallbackURI.Equals(""))) if ((CallbackURI != null) && (!CallbackURI.Equals("")))
args["callback_uri"] = OSD.FromString(CallbackURI); args["callback_uri"] = OSD.FromString(CallbackURI);
@ -628,6 +627,7 @@ namespace OpenSim.Framework
// We know all of these must end up as attachments so we // We know all of these must end up as attachments so we
// append rather than replace to ensure multiple attachments // append rather than replace to ensure multiple attachments
// per point continues to work // per point continues to work
// m_log.DebugFormat("[CHILDAGENTDATAUPDATE]: Appending attachments for {0}", AgentID);
Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o)); Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o));
} }
} }

View File

@ -1384,11 +1384,30 @@ namespace OpenSim.Framework
return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri; return (ipaddr1 != null) ? "http://" + ipaddr1.ToString() + ":" + port1 : uri;
} }
/// <summary>
/// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
/// </summary>
/// <param name="str">
/// If null or empty, then an bytes[0] is returned.
/// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
/// </param>
/// <param name="args">
/// Arguments to substitute into the string via the {} mechanism.
/// </param>
/// <returns></returns>
public static byte[] StringToBytes256(string str, params object[] args) public static byte[] StringToBytes256(string str, params object[] args)
{ {
return StringToBytes256(string.Format(str, args)); return StringToBytes256(string.Format(str, args));
} }
/// <summary>
/// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 256 bytes if necessary.
/// </summary>
/// <param name="str">
/// If null or empty, then an bytes[0] is returned.
/// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
/// </param>
/// <returns></returns>
public static byte[] StringToBytes256(string str) public static byte[] StringToBytes256(string str)
{ {
if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
@ -1407,11 +1426,30 @@ namespace OpenSim.Framework
return data; return data;
} }
/// <summary>
/// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary.
/// </summary>
/// <param name="str">
/// If null or empty, then an bytes[0] is returned.
/// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
/// </param>
/// <param name="args">
/// Arguments to substitute into the string via the {} mechanism.
/// </param>
/// <returns></returns>
public static byte[] StringToBytes1024(string str, params object[] args) public static byte[] StringToBytes1024(string str, params object[] args)
{ {
return StringToBytes1024(string.Format(str, args)); return StringToBytes1024(string.Format(str, args));
} }
/// <summary>
/// Convert a string to a byte format suitable for transport in an LLUDP packet. The output is truncated to 1024 bytes if necessary.
/// </summary>
/// <param name="str">
/// If null or empty, then an bytes[0] is returned.
/// Using "\0" will return a conversion of the null character to a byte. This is not the same as bytes[0]
/// </param>
/// <returns></returns>
public static byte[] StringToBytes1024(string str) public static byte[] StringToBytes1024(string str)
{ {
if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; } if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }

View File

@ -269,13 +269,15 @@ namespace OpenSim
m_console.Commands.AddCommand("region", false, "save oar", m_console.Commands.AddCommand("region", false, "save oar",
//"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]", //"save oar [-v|--version=<N>] [-p|--profile=<url>] [<OAR path>]",
"save oar [-p|--profile=<url>] [--noassets] [<OAR path>]", "save oar [-p|--profile=<url>] [--noassets] [--perm=<permissions>] [<OAR path>]",
"Save a region's data to an OAR archive.", "Save a region's data to an OAR archive.",
// "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine // "-v|--version=<N> generates scene objects as per older versions of the serialization (e.g. -v=0)" + Environment.NewLine
"-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine "-p|--profile=<url> adds the url of the profile service to the saved user information." + Environment.NewLine
+ " The OAR path must be a filesystem path." + "--noassets stops assets being saved to the OAR." + Environment.NewLine
+ " If this is not given then the oar is saved to region.oar in the current directory." + Environment.NewLine + "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine
+ "--noassets stops assets being saved to the OAR.", + " <permissions> can contain one or more of these characters: \"C\" = Copy, \"T\" = Transfer" + Environment.NewLine
+ "The OAR path must be a filesystem path."
+ " If this is not given then the oar is saved to region.oar in the current directory.",
SaveOar); SaveOar);
m_console.Commands.AddCommand("region", false, "edit scale", m_console.Commands.AddCommand("region", false, "edit scale",

View File

@ -489,6 +489,8 @@ namespace OpenSim
scene.StartTimer(); scene.StartTimer();
scene.StartTimerWatchdog(); scene.StartTimerWatchdog();
scene.StartScripts();
return clientServer; return clientServer;
} }

View File

@ -144,20 +144,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
public void SaveChangedAttachments(IScenePresence sp) public void SaveChangedAttachments(IScenePresence sp)
{ {
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
foreach (SceneObjectGroup grp in sp.GetAttachments()) foreach (SceneObjectGroup grp in sp.GetAttachments())
{ {
if (grp.HasGroupChanged) // Resizer scripts? // if (grp.HasGroupChanged) // Resizer scripts?
{ // {
grp.IsAttachment = false; grp.IsAttachment = false;
grp.AbsolutePosition = grp.RootPart.AttachedPos; grp.AbsolutePosition = grp.RootPart.AttachedPos;
UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID); UpdateKnownItem(sp.ControllingClient, grp);
grp.IsAttachment = true; grp.IsAttachment = true;
} // }
} }
} }
public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent) public void DeleteAttachmentsFromScene(IScenePresence sp, bool silent)
{ {
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Deleting attachments from scene {0} for {1}, silent = {2}",
// m_scene.RegionInfo.RegionName, sp.Name, silent);
foreach (SceneObjectGroup sop in sp.GetAttachments()) foreach (SceneObjectGroup sop in sp.GetAttachments())
{ {
sop.Scene.DeleteSceneObject(sop, silent); sop.Scene.DeleteSceneObject(sop, silent);
@ -220,7 +226,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId);
// Save avatar attachment information // Save avatar attachment information
m_log.Info( m_log.Debug(
"[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
+ ", AttachmentPoint: " + AttachmentPt); + ", AttachmentPoint: " + AttachmentPt);
@ -248,75 +254,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent) private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
{ {
// m_log.DebugFormat( lock (sp.AttachmentsSyncLock)
// "[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( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached", // "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
// group.Name, group.LocalId, sp.Name, AttachmentPt); // group.Name, group.LocalId, sp.Name, attachmentPt, silent);
return false;
}
Vector3 attachPos = group.AbsolutePosition;
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
attachmentPt &= 0x7f;
// If the attachment point isn't the same as the one previously used
// set it's offset position = 0 so that it appears on the attachment point
// and not in a weird location somewhere unknown.
if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
{
attachPos = Vector3.Zero;
}
// AttachmentPt 0 means the client chose to 'wear' the attachment.
if (attachmentPt == 0)
{
// Check object for stored attachment point
attachmentPt = group.AttachmentPoint;
}
// if we still didn't find a suitable attachment point.......
if (attachmentPt == 0)
{
// Stick it on left hand with Zero Offset from the attachment point.
attachmentPt = (uint)AttachmentPoint.LeftHand;
attachPos = Vector3.Zero;
}
group.AttachmentPoint = attachmentPt;
group.AbsolutePosition = attachPos;
// Remove any previous attachments
UUID itemID = UUID.Zero;
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
// At the moment we can only deal with a single attachment
// We also don't want to do any of the inventory operations for an NPC.
if (sp.PresenceType != PresenceType.Npc)
{
if (attachments.Count != 0)
itemID = attachments[0].GetFromItemID();
if (itemID != UUID.Zero) if (sp.GetAttachments(attachmentPt).Contains(group))
DetachSingleAttachmentToInv(itemID, sp); {
// 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);
itemID = group.GetFromItemID(); return false;
if (itemID == UUID.Zero) }
itemID = AddSceneObjectAsAttachment(sp.ControllingClient, group).ID;
ShowAttachInUserInventory(sp, attachmentPt, itemID, group); Vector3 attachPos = group.AbsolutePosition;
// TODO: this short circuits multiple attachments functionality in LL viewer 2.1+ and should
// be removed when that functionality is implemented in opensim
attachmentPt &= 0x7f;
// If the attachment point isn't the same as the one previously used
// set it's offset position = 0 so that it appears on the attachment point
// and not in a weird location somewhere unknown.
if (attachmentPt != 0 && attachmentPt != group.AttachmentPoint)
{
attachPos = Vector3.Zero;
}
// AttachmentPt 0 means the client chose to 'wear' the attachment.
if (attachmentPt == 0)
{
// Check object for stored attachment point
attachmentPt = group.AttachmentPoint;
}
// if we still didn't find a suitable attachment point.......
if (attachmentPt == 0)
{
// Stick it on left hand with Zero Offset from the attachment point.
attachmentPt = (uint)AttachmentPoint.LeftHand;
attachPos = Vector3.Zero;
}
group.AttachmentPoint = attachmentPt;
group.AbsolutePosition = attachPos;
// We also don't want to do any of the inventory operations for an NPC.
if (sp.PresenceType != PresenceType.Npc)
{
// Remove any previous attachments
List<SceneObjectGroup> attachments = sp.GetAttachments(attachmentPt);
// At the moment we can only deal with a single attachment
if (attachments.Count != 0)
{
UUID oldAttachmentItemID = attachments[0].GetFromItemID();
if (oldAttachmentItemID != UUID.Zero)
DetachSingleAttachmentToInv(oldAttachmentItemID, sp);
else
m_log.WarnFormat(
"[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!",
attachments[0].Name, attachments[0].LocalId, attachmentPt, group.Name, group.LocalId, sp.Name);
}
// Add the new attachment to inventory if we don't already have it.
UUID newAttachmentItemID = group.GetFromItemID();
if (newAttachmentItemID == UUID.Zero)
newAttachmentItemID = AddSceneObjectAsNewAttachmentInInv(sp.ControllingClient, group).ID;
ShowAttachInUserInventory(sp, attachmentPt, newAttachmentItemID, group);
}
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
} }
AttachToAgent(sp, group, attachmentPt, attachPos, silent);
return true; return true;
} }
@ -325,20 +339,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header, RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header,
RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects) RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects)
{ {
foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects) ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId);
if (sp == null)
{ {
RezSingleAttachmentFromInventory(remoteClient, obj.ItemID, obj.AttachmentPt); m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezMultipleAttachmentsFromInventory()",
remoteClient.Name, remoteClient.AgentId);
return;
}
lock (sp.AttachmentsSyncLock)
{
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Rezzing multiple attachments from inventory for {0}", sp.Name);
foreach (RezMultipleAttachmentsFromInvPacket.ObjectDataBlock obj in objects)
{
RezSingleAttachmentFromInventory(sp, obj.ItemID, obj.AttachmentPt);
}
} }
} }
public ISceneEntity RezSingleAttachmentFromInventory( public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
{
return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true);
}
public ISceneEntity RezSingleAttachmentFromInventory(
IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus)
{ {
return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null); return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true, null);
} }
@ -347,21 +369,59 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc) IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus, XmlDocument doc)
{ {
ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); 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 null; }
if (sp == null)
{
m_log.ErrorFormat(
"[ATTACHMENTS MODULE]: Could not find presence for client {0} {1} in RezSingleAttachmentFromInventory()",
remoteClient.Name, remoteClient.AgentId);
return null;
}
return RezSingleAttachmentFromInventory(sp, itemID, AttachmentPt);
}
public ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt)
{
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: RezSingleAttachmentFromInventory to point {0} from item {1} for {2}",
// (AttachmentPoint)AttachmentPt, itemID, sp.Name);
// 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(sp, itemID, UUID.Zero, AttachmentPt, doc); // Viewer 2/3 sometimes asks to re-wear items that are already worn (and show up in it's inventory as such).
// This often happens during login - not sure the exact reason.
if (updateInventoryStatus) // For now, we will ignore the request. Unfortunately, this means that we need to dig through all the
// ScenePresence attachments. We can't use the data in AvatarAppearance because that's present at login
// before anything has actually been attached.
bool alreadyOn = false;
List<SceneObjectGroup> existingAttachments = sp.GetAttachments();
foreach (SceneObjectGroup so in existingAttachments)
{ {
if (att == null) if (so.GetFromItemID() == itemID)
DetachSingleAttachmentToInv(itemID, sp.ControllingClient); {
else alreadyOn = true;
ShowAttachInUserInventory(att, sp, itemID, AttachmentPt); break;
}
} }
// if (sp.Appearance.GetAttachmentForItem(itemID) != null)
if (alreadyOn)
{
// m_log.WarnFormat(
// "[ATTACHMENTS MODULE]: Ignoring request by {0} to wear item {1} at {2} since it is already worn",
// sp.Name, itemID, AttachmentPt);
return null;
}
SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, null);
if (att == null)
DetachSingleAttachmentToInv(itemID, sp.ControllingClient);
return att; return att;
} }
@ -371,50 +431,67 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>(); IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
if (invAccess != null) if (invAccess != null)
{ {
SceneObjectGroup objatt; lock (sp.AttachmentsSyncLock)
if (itemID != UUID.Zero)
objatt = invAccess.RezObject(sp.ControllingClient,
itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
false, false, sp.UUID, true);
else
objatt = invAccess.RezObject(sp.ControllingClient,
null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
false, false, sp.UUID, true);
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
// objatt.Name, remoteClient.Name, AttachmentPt);
if (objatt != null)
{ {
// Loading the inventory from XML will have set this, but SceneObjectGroup objatt;
// there is no way the object could have changed yet,
// since scripts aren't running yet. So, clear it here. if (itemID != UUID.Zero)
objatt.HasGroupChanged = false; objatt = invAccess.RezObject(sp.ControllingClient,
bool tainted = false; itemID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint) false, false, sp.UUID, true);
tainted = true; else
objatt = invAccess.RezObject(sp.ControllingClient,
// This will throw if the attachment fails null, assetID, Vector3.Zero, Vector3.Zero, UUID.Zero, (byte)1, true,
try false, false, sp.UUID, true);
{
AttachObject(sp, objatt, attachmentPt, false); // m_log.DebugFormat(
} // "[ATTACHMENTS MODULE]: Retrieved single object {0} for attachment to {1} on point {2}",
catch (Exception e) // objatt.Name, remoteClient.Name, AttachmentPt);
{
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
sp.RemoveAttachment(objatt);
m_scene.DeleteSceneObject(objatt, false);
return null;
}
if (tainted) if (objatt != null)
objatt.HasGroupChanged = true; {
// HasGroupChanged is being set from within RezObject. Ideally it would be set by the caller.
objatt.HasGroupChanged = false;
bool tainted = false;
if (attachmentPt != 0 && attachmentPt != objatt.AttachmentPoint)
tainted = true;
// This will throw if the attachment fails
try
{
AttachObject(sp, objatt, attachmentPt, false);
}
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
sp.RemoveAttachment(objatt);
m_scene.DeleteSceneObject(objatt, false);
return null;
}
if (tainted)
objatt.HasGroupChanged = true;
// Fire after attach, so we don't get messy perms dialogs
// 4 == AttachedRez
objatt.CreateScriptInstances(0, true, m_scene.DefaultScriptEngine, 4);
objatt.ResumeScripts();
// Do this last so that event listeners have access to all the effects of the attachment
m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
return objatt;
}
else
{
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
itemID, sp.Name, attachmentPt);
}
if (doc != null) if (doc != null)
{ {
@ -430,47 +507,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// 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, sp.UUID); m_scene.EventManager.TriggerOnAttach(objatt.LocalId, itemID, sp.UUID);
} }
else
{
m_log.WarnFormat(
"[ATTACHMENTS MODULE]: Could not retrieve item {0} for attaching to avatar {1} at point {2}",
itemID, sp.Name, attachmentPt);
}
return objatt;
} }
return null; return null;
} }
/// <summary>
/// Update the user inventory to the attachment of an item
/// </summary>
/// <param name="att"></param>
/// <param name="sp"></param>
/// <param name="itemID"></param>
/// <param name="attachmentPoint"></param>
/// <returns></returns>
private UUID ShowAttachInUserInventory(
SceneObjectGroup att, IScenePresence sp, UUID itemID, uint attachmentPoint)
{
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Updating inventory of {0} to show attachment of {1} {2} (item ID {3}) at {4}",
// sp.Name, att.Name, att.LocalId, itemID, AttachmentPt);
if (!att.IsDeleted)
attachmentPoint = att.AttachmentPoint;
InventoryItemBase item = new InventoryItemBase(itemID, sp.UUID);
if (m_scene.InventoryService != null)
item = m_scene.InventoryService.GetItem(item);
bool changed = sp.Appearance.SetAttachment((int)attachmentPoint, itemID, item.AssetID);
if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(sp.UUID);
return att.UUID;
}
/// <summary> /// <summary>
/// Update the user inventory to reflect an attachment /// Update the user inventory to reflect an attachment
@ -483,8 +523,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
IScenePresence sp, uint AttachmentPt, UUID itemID, SceneObjectGroup att) IScenePresence 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}",
// att.Name, remoteClient.Name, AttachmentPt, itemID); // att.Name, sp.Name, AttachmentPt, itemID);
if (UUID.Zero == itemID) if (UUID.Zero == itemID)
{ {
@ -518,6 +558,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
public void DetachObject(uint objectLocalID, IClientAPI remoteClient) public void DetachObject(uint objectLocalID, IClientAPI remoteClient)
{ {
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: DetachObject() for object {0} on {1}", objectLocalID, remoteClient.Name);
SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID);
if (group != null) if (group != null)
{ {
@ -530,14 +573,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ScenePresence presence; ScenePresence presence;
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{ {
// Save avatar attachment information lock (presence.AttachmentsSyncLock)
m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); {
// Save avatar attachment information
m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
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, presence); DetachSingleAttachmentToInv(itemID, presence);
}
} }
} }
@ -545,7 +591,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}", // "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
// remoteClient.Name, sceneObjectID); // remoteClient.Name, soLocalId);
SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId); SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
@ -564,24 +610,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ScenePresence presence; ScenePresence presence;
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{ {
if (!m_scene.Permissions.CanRezObject( lock (presence.AttachmentsSyncLock)
so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition)) {
return; if (!m_scene.Permissions.CanRezObject(
so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
return;
bool changed = presence.Appearance.DetachAttachment(inventoryID); bool changed = presence.Appearance.DetachAttachment(inventoryID);
if (changed && m_scene.AvatarFactory != null) if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId); m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
presence.RemoveAttachment(so); presence.RemoveAttachment(so);
DetachSceneObjectToGround(so, presence); DetachSceneObjectToGround(so, presence);
List<UUID> uuids = new List<UUID>(); List<UUID> uuids = new List<UUID>();
uuids.Add(inventoryID); uuids.Add(inventoryID);
m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids); m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids);
remoteClient.SendRemoveInventoryItem(inventoryID); remoteClient.SendRemoveInventoryItem(inventoryID);
}
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
} }
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
} }
/// <summary> /// <summary>
@ -615,6 +664,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// To LocalId or UUID, *THAT* is the question. How now Brown UUID?? // To LocalId or UUID, *THAT* is the question. How now Brown UUID??
private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp) private void DetachSingleAttachmentToInv(UUID itemID, IScenePresence sp)
{ {
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Detaching item {0} to inventory for {1}", itemID, sp.Name);
if (itemID == UUID.Zero) // If this happened, someone made a mistake.... if (itemID == UUID.Zero) // If this happened, someone made a mistake....
return; return;
@ -623,40 +674,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
EntityBase[] detachEntities = m_scene.GetEntities(); EntityBase[] detachEntities = m_scene.GetEntities();
SceneObjectGroup group; SceneObjectGroup group;
foreach (EntityBase entity in detachEntities) lock (sp.AttachmentsSyncLock)
{ {
if (entity is SceneObjectGroup) foreach (EntityBase entity in detachEntities)
{ {
group = (SceneObjectGroup)entity; if (entity is SceneObjectGroup)
if (group.GetFromItemID() == itemID)
{ {
m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero); group = (SceneObjectGroup)entity; if (group.GetFromItemID() == itemID) { m_scene.EventManager.TriggerOnAttach(group.LocalId, itemID, UUID.Zero);
// CM / XMREngine!!!! Needed to conclude attach event // CM / XMREngine!!!! Needed to conclude attach event
//SceneObjectSerializer.ToOriginalXmlFormat(group); //SceneObjectSerializer.ToOriginalXmlFormat(group);
group.DetachToInventoryPrep(); group.DetachToInventoryPrep();
m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString()); m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
// Prepare sog for storage // Prepare sog for storage
group.AttachedAvatar = UUID.Zero; group.AttachedAvatar = UUID.Zero;
group.RootPart.SetParentLocalId(0);
group.IsAttachment = false;
group.AbsolutePosition = group.RootPart.AttachedPos;
group.ForEachPart( UpdateKnownItem(sp.ControllingClient, group);
delegate(SceneObjectPart part) m_scene.DeleteSceneObject(group, false);
{
// If there are any scripts,
// then always trigger a new object and state persistence in UpdateKnownItem()
if (part.Inventory.ContainsScripts())
group.HasGroupChanged = true;
}
);
group.RootPart.SetParentLocalId(0); return;
group.IsAttachment = false; }
group.AbsolutePosition = group.RootPart.AttachedPos;
UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID);
m_scene.DeleteSceneObject(group, false);
return;
} }
} }
} }
@ -687,28 +727,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// </remarks> /// </remarks>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="grp"></param> /// <param name="grp"></param>
/// <param name="itemID"></param> private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp)
/// <param name="agentID"></param>
public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID)
{ {
if (grp != null) if (grp.HasGroupChanged || grp.ContainsScripts())
{ {
if (!grp.HasGroupChanged)
{
m_log.DebugFormat(
"[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
grp.UUID, grp.AttachmentPoint);
return;
}
m_log.DebugFormat( m_log.DebugFormat(
"[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}", "[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
grp.UUID, grp.AttachmentPoint); grp.UUID, grp.AttachmentPoint);
string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp); string sceneObjectXml = SceneObjectSerializer.ToOriginalXmlFormat(grp);
InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); InventoryItemBase item = new InventoryItemBase(grp.GetFromItemID(), remoteClient.AgentId);
item = m_scene.InventoryService.GetItem(item); item = m_scene.InventoryService.GetItem(item);
if (item != null) if (item != null)
@ -734,6 +763,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
remoteClient.SendInventoryItemCreateUpdate(item, 0); remoteClient.SendInventoryItemCreateUpdate(item, 0);
} }
} }
else
{
m_log.DebugFormat(
"[ATTACHMENTS MODULE]: Don't need to update asset for unchanged attachment {0}, attachpoint {1}",
grp.UUID, grp.AttachmentPoint);
}
} }
/// <summary> /// <summary>
@ -751,7 +786,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
private void AttachToAgent( private void AttachToAgent(
IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent) IScenePresence avatar, SceneObjectGroup so, uint attachmentpoint, Vector3 attachOffset, bool silent)
{ {
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}", // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Adding attachment {0} to avatar {1} in pt {2} pos {3} {4}",
// so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos); // so.Name, avatar.Name, attachmentpoint, attachOffset, so.RootPart.AttachedPos);
so.DetachFromBackup(); so.DetachFromBackup();
@ -788,14 +824,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
} }
/// <summary> /// <summary>
/// Add a scene object that was previously free in the scene as an attachment to an avatar. /// Add a scene object as a new attachment in the user inventory.
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="remoteClient"></param>
/// <param name="grp"></param> /// <param name="grp"></param>
/// <returns>The user inventory item created that holds the attachment.</returns> /// <returns>The user inventory item created that holds the attachment.</returns>
private InventoryItemBase AddSceneObjectAsAttachment(IClientAPI remoteClient, SceneObjectGroup grp) private InventoryItemBase AddSceneObjectAsNewAttachmentInInv(IClientAPI remoteClient, SceneObjectGroup grp)
{ {
// m_log.DebugFormat("[SCENE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2} {3} {4}", grp.Name, grp.LocalId, remoteClient.Name, remoteClient.AgentId, AgentId); // m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Called AddSceneObjectAsAttachment for object {0} {1} for {2}",
// grp.Name, grp.LocalId, remoteClient.Name);
Vector3 inventoryStoredPosition = new Vector3 Vector3 inventoryStoredPosition = new Vector3
(((grp.AbsolutePosition.X > (int)Constants.RegionSize) (((grp.AbsolutePosition.X > (int)Constants.RegionSize)
@ -879,4 +917,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return item; return item;
} }
} }
} }

View File

@ -58,12 +58,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
private AttachmentsModule m_attMod; private AttachmentsModule m_attMod;
private ScenePresence m_presence; private ScenePresence m_presence;
[SetUp] [TestFixtureSetUp]
public void Init() public void FixtureInit()
{ {
// Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread. // Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
Util.FireAndForgetMethod = FireAndForgetMethod.None; Util.FireAndForgetMethod = FireAndForgetMethod.None;
}
[SetUp]
public void Init()
{
IConfigSource config = new IniConfigSource(); IConfigSource config = new IniConfigSource();
config.AddConfig("Modules"); config.AddConfig("Modules");
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule"); config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
@ -73,7 +77,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule()); SceneHelpers.SetupSceneModules(scene, config, m_attMod, new BasicInventoryAccessModule());
} }
[TearDown] [TestFixtureTearDown]
public void TearDown() public void TearDown()
{ {
// We must set this back afterwards, otherwise later tests will fail since they're expecting multiple // 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
Assert.That(attSo.IsTemporary, Is.False); Assert.That(attSo.IsTemporary, Is.False);
// Check appearance status // Check appearance status
Assert.That(m_presence.Appearance.GetAttachments().Count, Is.EqualTo(1));
Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest)); Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
} }
@ -215,6 +220,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0)); Assert.That(m_presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo(0));
} }
/// <summary>
/// Test that attachments don't hang about in the scene when the agent is closed
/// </summary>
[Test]
public void TestRemoveAttachmentsOnAvatarExit()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID userId = TestHelpers.ParseTail(0x1);
UUID attItemId = TestHelpers.ParseTail(0x2);
UUID attAssetId = TestHelpers.ParseTail(0x3);
string attName = "att";
UserAccountHelpers.CreateUserWithInventory(scene, userId);
InventoryItemBase attItem
= UserInventoryHelpers.CreateInventoryItem(
scene, attName, attItemId, attAssetId, userId, InventoryType.Object);
AgentCircuitData acd = SceneHelpers.GenerateAgentData(userId);
acd.Appearance = new AvatarAppearance();
acd.Appearance.SetAttachment((int)AttachmentPoint.Chest, attItem.ID, attItem.AssetID);
ScenePresence presence = SceneHelpers.AddScenePresence(scene, acd);
SceneObjectGroup rezzedAtt = presence.GetAttachments()[0];
scene.IncomingCloseAgent(presence.UUID);
// Check that we can't retrieve this attachment from the scene.
Assert.That(scene.GetSceneObjectGroup(rezzedAtt.UUID), Is.Null);
}
[Test] [Test]
public void TestRezAttachmentsOnAvatarEntrance() public void TestRezAttachmentsOnAvatarEntrance()
{ {
@ -246,6 +283,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
Assert.That(attSo.IsAttachment); Assert.That(attSo.IsAttachment);
Assert.That(attSo.UsesPhysics, Is.False); Assert.That(attSo.UsesPhysics, Is.False);
Assert.That(attSo.IsTemporary, Is.False); Assert.That(attSo.IsTemporary, Is.False);
// Check appearance status
List<AvatarAttachment> retreivedAttachments = presence.Appearance.GetAttachments();
Assert.That(retreivedAttachments.Count, Is.EqualTo(1));
Assert.That(retreivedAttachments[0].AttachPoint, Is.EqualTo((int)AttachmentPoint.Chest));
Assert.That(retreivedAttachments[0].ItemID, Is.EqualTo(attItemId));
Assert.That(retreivedAttachments[0].AssetID, Is.EqualTo(attAssetId));
Assert.That(presence.Appearance.GetAttachpoint(attItemId), Is.EqualTo((int)AttachmentPoint.Chest));
} }
// I'm commenting this test because scene setup NEEDS InventoryService to // I'm commenting this test because scene setup NEEDS InventoryService to

View File

@ -59,7 +59,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
get { return m_MaxTransferDistance; } get { return m_MaxTransferDistance; }
set { m_MaxTransferDistance = value; } set { m_MaxTransferDistance = value; }
} }
protected bool m_Enabled = false; protected bool m_Enabled = false;
protected Scene m_aScene; protected Scene m_aScene;
@ -68,7 +67,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions = private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>(); new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
#region ISharedRegionModule #region ISharedRegionModule
public Type ReplaceableInterface public Type ReplaceableInterface
@ -210,7 +208,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.Teleport(position); sp.Teleport(position);
foreach (SceneObjectGroup grp in sp.GetAttachments()) foreach (SceneObjectGroup grp in sp.GetAttachments())
sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); {
if (grp.IsDeleted)
sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT);
}
} }
else // Another region possibly in another simulator else // Another region possibly in another simulator
{ {
@ -328,10 +329,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.StandUp(); sp.StandUp();
if (!sp.ValidateAttachments()) if (!sp.ValidateAttachments())
{ m_log.DebugFormat(
sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state"); "[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
return; sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
}
// if (!sp.ValidateAttachments())
// {
// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
// return;
// }
string reason; string reason;
string version; string version;
@ -955,7 +961,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// This Closes child agents on neighbouring regions /// This Closes child agents on neighbouring regions
/// Calls an asynchronous method to do so.. so it doesn't lag the sim. /// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </summary> /// </summary>
protected ScenePresence CrossAgentToNewRegionAsync(ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion, bool isFlying, string version) protected ScenePresence CrossAgentToNewRegionAsync(
ScenePresence agent, Vector3 pos, uint neighbourx, uint neighboury, GridRegion neighbourRegion,
bool isFlying, string version)
{ {
ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize)); ulong neighbourHandle = Utils.UIntsToLong((uint)(neighbourx * Constants.RegionSize), (uint)(neighboury * Constants.RegionSize));
@ -963,8 +971,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
Scene m_scene = agent.Scene; Scene m_scene = agent.Scene;
if (neighbourRegion != null && agent.ValidateAttachments()) if (neighbourRegion != null)
{ {
if (!agent.ValidateAttachments())
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Failed validation of all attachments for region crossing of {0} from {1} to {2}. Continuing.",
agent.Name, agent.Scene.RegionInfo.RegionName, neighbourRegion.RegionName);
pos = pos + (agent.Velocity); pos = pos + (agent.Velocity);
SetInTransit(agent.UUID); SetInTransit(agent.UUID);
@ -1789,16 +1802,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
List<SceneObjectGroup> m_attachments = sp.GetAttachments(); List<SceneObjectGroup> m_attachments = sp.GetAttachments();
// Validate // Validate
foreach (SceneObjectGroup gobj in m_attachments) // foreach (SceneObjectGroup gobj in m_attachments)
{ // {
if (gobj == null || gobj.IsDeleted) // if (gobj == null || gobj.IsDeleted)
return false; // return false;
} // }
foreach (SceneObjectGroup gobj in m_attachments) foreach (SceneObjectGroup gobj in m_attachments)
{ {
// If the prim group is null then something must have happened to it! // If the prim group is null then something must have happened to it!
if (gobj != null) if (gobj != null && !gobj.IsDeleted)
{ {
// Set the parent localID to 0 so it transfers over properly. // Set the parent localID to 0 so it transfers over properly.
gobj.RootPart.SetParentLocalId(0); gobj.RootPart.SetParentLocalId(0);

View File

@ -726,8 +726,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
SceneObjectGroup group = null; SceneObjectGroup group = null;
string xmlData = Utils.BytesToString(rezAsset.Data); string xmlData = Utils.BytesToString(rezAsset.Data);
List<SceneObjectGroup> objlist = List<SceneObjectGroup> objlist = new List<SceneObjectGroup>();
new List<SceneObjectGroup>();
List<Vector3> veclist = new List<Vector3>(); List<Vector3> veclist = new List<Vector3>();
byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0); byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
Vector3 pos; Vector3 pos;
@ -799,6 +798,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
m_log.Debug("[InventoryAccessModule]: Object has UUID.Zero! Position 3"); m_log.Debug("[InventoryAccessModule]: Object has UUID.Zero! Position 3");
} }
foreach (SceneObjectPart part in group.Parts)
{
// Make the rezzer the owner, as this is not necessarily set correctly in the serialized asset.
part.LastOwnerID = part.OwnerID;
part.OwnerID = remoteClient.AgentId;
}
if (!attachment) if (!attachment)
{ {
// If it's rezzed in world, select it. Much easier to // If it's rezzed in world, select it. Much easier to
@ -839,7 +845,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (!attachment) if (!attachment)
{ {
if (group.RootPart.Shape.PCode == (byte)PCode.Prim) if (rootPart.Shape.PCode == (byte)PCode.Prim)
group.ClearPartAttachmentData(); group.ClearPartAttachmentData();
// Fire on_rez // Fire on_rez
@ -1017,11 +1023,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if ((part.OwnerID != item.Owner) || if ((part.OwnerID != item.Owner) ||
(item.CurrentPermissions & 16) != 0) (item.CurrentPermissions & 16) != 0)
{ {
part.LastOwnerID = part.OwnerID;
part.OwnerID = item.Owner;
part.Inventory.ChangeInventoryOwner(item.Owner); part.Inventory.ChangeInventoryOwner(item.Owner);
part.GroupMask = 0; // DO NOT propagate here part.GroupMask = 0; // DO NOT propagate here
} }
part.EveryoneMask = item.EveryOnePermissions; part.EveryoneMask = item.EveryOnePermissions;
part.NextOwnerMask = item.NextPermissions; part.NextOwnerMask = item.NextPermissions;
} }

View File

@ -87,8 +87,6 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
"Show the bindings between user UUIDs and user names", "Show the bindings between user UUIDs and user names",
String.Empty, String.Empty,
HandleShowUsers); HandleShowUsers);
} }
public bool IsSharedModule public bool IsSharedModule
@ -365,9 +363,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
lock (m_UserCache) lock (m_UserCache)
m_UserCache[user.Id] = user; m_UserCache[user.Id] = user;
m_log.DebugFormat( // m_log.DebugFormat(
"[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}", // "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
user.Id, user.FirstName, user.LastName, user.HomeURL); // user.Id, user.FirstName, user.LastName, user.HomeURL);
} }
//public void AddUser(UUID uuid, string userData) //public void AddUser(UUID uuid, string userData)

View File

@ -323,7 +323,8 @@ namespace OpenSim.Region.CoreModules.Scripting.WorldComm
List<UUID> targets = new List<UUID>(); List<UUID> targets = new List<UUID>();
foreach (SceneObjectGroup sog in attachments) foreach (SceneObjectGroup sog in attachments)
{ {
targets.Add(sog.UUID); if (!sog.IsDeleted)
targets.Add(sog.UUID);
} }
// Need to check each attachment // Need to check each attachment

View File

@ -64,7 +64,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
get get
{ {
if (m_UserManagement == null) if (m_UserManagement == null)
{
m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>(); m_UserManagement = m_Scenes[0].RequestModuleInterface<IUserManagement>();
if (m_UserManagement == null)
m_log.ErrorFormat(
"[HG INVENTORY CONNECTOR]: Could not retrieve IUserManagement module from {0}",
m_Scenes[0].RegionInfo.RegionName);
}
return m_UserManagement; return m_UserManagement;
} }
} }
@ -140,8 +148,29 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
scene.RegisterModuleInterface<IInventoryService>(this); scene.RegisterModuleInterface<IInventoryService>(this);
scene.EventManager.OnClientClosed += OnClientClosed; if (m_Scenes.Count == 1)
{
// FIXME: The local connector needs the scene to extract the UserManager. However, it's not enabled so
// we can't just add the region. But this approach is super-messy.
if (m_LocalGridInventoryService is RemoteXInventoryServicesConnector)
{
m_log.DebugFormat(
"[HG INVENTORY BROKER]: Manually setting scene in RemoteXInventoryServicesConnector to {0}",
scene.RegionInfo.RegionName);
((RemoteXInventoryServicesConnector)m_LocalGridInventoryService).Scene = scene;
}
else if (m_LocalGridInventoryService is LocalInventoryServicesConnector)
{
m_log.DebugFormat(
"[HG INVENTORY BROKER]: Manually setting scene in LocalInventoryServicesConnector to {0}",
scene.RegionInfo.RegionName);
((LocalInventoryServicesConnector)m_LocalGridInventoryService).Scene = scene;
}
scene.EventManager.OnClientClosed += OnClientClosed;
}
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
@ -323,7 +352,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
} }
public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID) public List<InventoryItemBase> GetFolderItems(UUID userID, UUID folderID)
{ {
//m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID);
@ -338,7 +367,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
} }
public bool AddFolder(InventoryFolderBase folder) public bool AddFolder(InventoryFolderBase folder)
{ {
if (folder == null) if (folder == null)
return false; return false;
@ -355,7 +384,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.AddFolder(folder); return connector.AddFolder(folder);
} }
public bool UpdateFolder(InventoryFolderBase folder) public bool UpdateFolder(InventoryFolderBase folder)
{ {
if (folder == null) if (folder == null)
return false; return false;
@ -372,7 +401,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.UpdateFolder(folder); return connector.UpdateFolder(folder);
} }
public bool DeleteFolders(UUID ownerID, List<UUID> folderIDs) public bool DeleteFolders(UUID ownerID, List<UUID> folderIDs)
{ {
if (folderIDs == null) if (folderIDs == null)
return false; return false;
@ -391,7 +420,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.DeleteFolders(ownerID, folderIDs); return connector.DeleteFolders(ownerID, folderIDs);
} }
public bool MoveFolder(InventoryFolderBase folder) public bool MoveFolder(InventoryFolderBase folder)
{ {
if (folder == null) if (folder == null)
return false; return false;
@ -408,7 +437,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.MoveFolder(folder); return connector.MoveFolder(folder);
} }
public bool PurgeFolder(InventoryFolderBase folder) public bool PurgeFolder(InventoryFolderBase folder)
{ {
if (folder == null) if (folder == null)
return false; return false;
@ -442,7 +471,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.AddItem(item); return connector.AddItem(item);
} }
public bool UpdateItem(InventoryItemBase item) public bool UpdateItem(InventoryItemBase item)
{ {
if (item == null) if (item == null)
return false; return false;
@ -459,7 +488,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.UpdateItem(item); return connector.UpdateItem(item);
} }
public bool MoveItems(UUID ownerID, List<InventoryItemBase> items) public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
{ {
if (items == null) if (items == null)
return false; return false;
@ -478,7 +507,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.MoveItems(ownerID, items); return connector.MoveItems(ownerID, items);
} }
public bool DeleteItems(UUID ownerID, List<UUID> itemIDs) public bool DeleteItems(UUID ownerID, List<UUID> itemIDs)
{ {
//m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Delete {0} items for user {1}", itemIDs.Count, ownerID); //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Delete {0} items for user {1}", itemIDs.Count, ownerID);
@ -497,7 +526,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.DeleteItems(ownerID, itemIDs); return connector.DeleteItems(ownerID, itemIDs);
} }
public InventoryItemBase GetItem(InventoryItemBase item) public InventoryItemBase GetItem(InventoryItemBase item)
{ {
if (item == null) if (item == null)
return null; return null;
@ -513,7 +542,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.GetItem(item); return connector.GetItem(item);
} }
public InventoryFolderBase GetFolder(InventoryFolderBase folder) public InventoryFolderBase GetFolder(InventoryFolderBase folder)
{ {
if (folder == null) if (folder == null)
return null; return null;
@ -530,17 +559,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.GetFolder(folder); return connector.GetFolder(folder);
} }
public bool HasInventoryForUser(UUID userID) public bool HasInventoryForUser(UUID userID)
{ {
return false; return false;
} }
public List<InventoryItemBase> GetActiveGestures(UUID userId) public List<InventoryItemBase> GetActiveGestures(UUID userId)
{ {
return new List<InventoryItemBase>(); return new List<InventoryItemBase>();
} }
public int GetAssetPermissions(UUID userID, UUID assetID) public int GetAssetPermissions(UUID userID, UUID assetID)
{ {
//m_log.Debug("[HG INVENTORY CONNECTOR]: GetAssetPermissions " + assetID); //m_log.Debug("[HG INVENTORY CONNECTOR]: GetAssetPermissions " + assetID);
@ -572,14 +601,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
string connectorType = new HeloServicesConnector(url).Helo(); string connectorType = new HeloServicesConnector(url).Helo();
m_log.DebugFormat("[HG INVENTORY SERVICE]: HELO returned {0}", connectorType); m_log.DebugFormat("[HG INVENTORY SERVICE]: HELO returned {0}", connectorType);
if (connectorType == "opensim-simian") if (connectorType == "opensim-simian")
{
connector = new SimianInventoryServiceConnector(url); connector = new SimianInventoryServiceConnector(url);
}
else else
connector = new RemoteXInventoryServicesConnector(url); {
RemoteXInventoryServicesConnector rxisc = new RemoteXInventoryServicesConnector(url);
rxisc.Scene = m_Scenes[0];
connector = rxisc;
}
m_connectors.Add(url, connector); m_connectors.Add(url, connector);
} }
} }
return connector; return connector;
} }
} }
} }

View File

@ -47,9 +47,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
LogManager.GetLogger( LogManager.GetLogger(
MethodBase.GetCurrentMethod().DeclaringType); MethodBase.GetCurrentMethod().DeclaringType);
private IInventoryService m_InventoryService; /// <summary>
/// Scene used by this module. This currently needs to be publicly settable for HGInventoryBroker.
/// </summary>
public Scene Scene { get; set; }
private Scene m_Scene; private IInventoryService m_InventoryService;
private IUserManagement m_UserManager; private IUserManagement m_UserManager;
private IUserManagement UserManager private IUserManagement UserManager
@ -58,7 +61,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
{ {
if (m_UserManager == null) if (m_UserManager == null)
{ {
m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>(); m_UserManager = Scene.RequestModuleInterface<IUserManagement>();
} }
return m_UserManager; return m_UserManager;
} }
@ -131,8 +134,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
scene.RegisterModuleInterface<IInventoryService>(this); scene.RegisterModuleInterface<IInventoryService>(this);
if (m_Scene == null) if (Scene == null)
m_Scene = scene; Scene = scene;
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
@ -185,8 +188,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
Util.FireAndForget(delegate Util.FireAndForget(delegate
{ {
if (UserManager != null) if (UserManager != null)
foreach (InventoryItemBase item in invCol.Items) {
// Protect ourselves against the caller subsequently modifying the items list
foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
}
}); });
return invCol; return invCol;

View File

@ -45,19 +45,30 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
private static readonly ILog m_log = private static readonly ILog m_log =
LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
/// <summary>
/// Scene used by this module. This currently needs to be publicly settable for HGInventoryBroker.
/// </summary>
public Scene Scene { get; set; }
private bool m_Enabled = false; private bool m_Enabled = false;
private Scene m_Scene; private Scene m_Scene;
private XInventoryServicesConnector m_RemoteConnector; private XInventoryServicesConnector m_RemoteConnector;
private IUserManagement m_UserManager; private IUserManagement m_UserManager;
private IUserManagement UserManager public IUserManagement UserManager
{ {
get get
{ {
if (m_UserManager == null) if (m_UserManager == null)
{ {
m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>(); m_UserManager = Scene.RequestModuleInterface<IUserManagement>();
if (m_UserManager == null)
m_log.ErrorFormat(
"[XINVENTORY CONNECTOR]: Could not retrieve IUserManagement module from {0}",
Scene.RegionInfo.RegionName);
} }
return m_UserManager; return m_UserManager;
} }
} }
@ -86,12 +97,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
Init(source); Init(source);
} }
protected void Init(IConfigSource source) protected void Init(IConfigSource source)
{ {
m_RemoteConnector = new XInventoryServicesConnector(source); m_RemoteConnector = new XInventoryServicesConnector(source);
} }
#region ISharedRegionModule #region ISharedRegionModule
public void Initialise(IConfigSource source) public void Initialise(IConfigSource source)
@ -128,15 +138,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
scene.RegisterModuleInterface<IInventoryService>(this); scene.RegisterModuleInterface<IInventoryService>(this);
if (m_Scene == null) if (Scene == null)
m_Scene = scene; Scene = scene;
} }
public void RemoveRegion(Scene scene) public void RemoveRegion(Scene scene)
{ {
if (!m_Enabled) if (!m_Enabled)
return; return;
} }
public void RegionLoaded(Scene scene) public void RegionLoaded(Scene scene)
@ -181,14 +190,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return m_RemoteConnector.GetFolderForType(userID, type); return m_RemoteConnector.GetFolderForType(userID, type);
} }
public InventoryCollection GetFolderContent(UUID userID, UUID folderID) public InventoryCollection GetFolderContent(UUID userID, UUID folderID)
{ {
InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID); InventoryCollection invCol = m_RemoteConnector.GetFolderContent(userID, folderID);
Util.FireAndForget(delegate Util.FireAndForget(delegate
{ {
if (UserManager != null) if (UserManager != null)
foreach (InventoryItemBase item in invCol.Items) {
// Protect ourselves against the caller subsequently modifying the items list
foreach (InventoryItemBase item in new List<InventoryItemBase>(invCol.Items))
UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData); UserManager.AddUser(item.CreatorIdAsUuid, item.CreatorData);
}
}); });
return invCol; return invCol;

View File

@ -284,8 +284,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
// And zap any troublesome sit target information // And zap any troublesome sit target information
part.SitTargetOrientation = new Quaternion(0, 0, 0, 1); // part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
part.SitTargetPosition = new Vector3(0, 0, 0); // part.SitTargetPosition = new Vector3(0, 0, 0);
// Fix ownership/creator of inventory items // Fix ownership/creator of inventory items
// Not doing so results in inventory items // Not doing so results in inventory items

View File

@ -127,6 +127,12 @@ namespace OpenSim.Region.CoreModules.World.Archiver
EntityBase[] entities = m_scene.GetEntities(); EntityBase[] entities = m_scene.GetEntities();
List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>(); List<SceneObjectGroup> sceneObjects = new List<SceneObjectGroup>();
string checkPermissions = null;
int numObjectsSkippedPermissions = 0;
Object temp;
if (options.TryGetValue("checkPermissions", out temp))
checkPermissions = (string)temp;
// Filter entities so that we only have scene objects. // Filter entities so that we only have scene objects.
// FIXME: Would be nicer to have this as a proper list in SceneGraph, since lots of methods // 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
if (entity is SceneObjectGroup) if (entity is SceneObjectGroup)
{ {
SceneObjectGroup sceneObject = (SceneObjectGroup)entity; SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
if (!sceneObject.IsDeleted && !sceneObject.IsAttachment) if (!sceneObject.IsDeleted && !sceneObject.IsAttachment)
sceneObjects.Add((SceneObjectGroup)entity); {
if (!CanUserArchiveObject(m_scene.RegionInfo.EstateSettings.EstateOwner, sceneObject, checkPermissions))
{
// The user isn't allowed to copy/transfer this object, so it will not be included in the OAR.
++numObjectsSkippedPermissions;
}
else
{
sceneObjects.Add(sceneObject);
}
}
} }
} }
@ -159,7 +175,14 @@ namespace OpenSim.Region.CoreModules.World.Archiver
{ {
m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified"); m_log.DebugFormat("[ARCHIVER]: Not saving assets since --noassets was specified");
} }
if (numObjectsSkippedPermissions > 0)
{
m_log.DebugFormat(
"[ARCHIVER]: {0} scene objects skipped due to lack of permissions",
numObjectsSkippedPermissions);
}
// Make sure that we also request terrain texture assets // Make sure that we also request terrain texture assets
RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings; RegionSettings regionSettings = m_scene.RegionInfo.RegionSettings;
@ -210,6 +233,83 @@ namespace OpenSim.Region.CoreModules.World.Archiver
} }
} }
/// <summary>
/// Checks whether the user has permission to export an object group to an OAR.
/// </summary>
/// <param name="user">The user</param>
/// <param name="objGroup">The object group</param>
/// <param name="checkPermissions">Which permissions to check: "C" = Copy, "T" = Transfer</param>
/// <returns>Whether the user is allowed to export the object to an OAR</returns>
private bool CanUserArchiveObject(UUID user, SceneObjectGroup objGroup, string checkPermissions)
{
if (checkPermissions == null)
return true;
IPermissionsModule module = m_scene.RequestModuleInterface<IPermissionsModule>();
if (module == null)
return true; // this shouldn't happen
// Check whether the user is permitted to export all of the parts in the SOG. If any
// part can't be exported then the entire SOG can't be exported.
bool permitted = true;
//int primNumber = 1;
foreach (SceneObjectPart obj in objGroup.Parts)
{
uint perm;
PermissionClass permissionClass = module.GetPermissionClass(user, obj);
switch (permissionClass)
{
case PermissionClass.Owner:
perm = obj.BaseMask;
break;
case PermissionClass.Group:
perm = obj.GroupMask | obj.EveryoneMask;
break;
case PermissionClass.Everyone:
default:
perm = obj.EveryoneMask;
break;
}
bool canCopy = (perm & (uint)PermissionMask.Copy) != 0;
bool canTransfer = (perm & (uint)PermissionMask.Transfer) != 0;
// Special case: if Everyone can copy the object then this implies it can also be
// Transferred.
// However, if the user is the Owner then we don't check EveryoneMask, because it seems that the mask
// always (incorrectly) includes the Copy bit set in this case. But that's a mistake: the viewer
// does NOT show that the object has Everyone-Copy permissions, and doesn't allow it to be copied.
if (permissionClass != PermissionClass.Owner)
{
canTransfer |= (obj.EveryoneMask & (uint)PermissionMask.Copy) != 0;
}
bool partPermitted = true;
if (checkPermissions.Contains("C") && !canCopy)
partPermitted = false;
if (checkPermissions.Contains("T") && !canTransfer)
partPermitted = false;
//string name = (objGroup.PrimCount == 1) ? objGroup.Name : string.Format("{0} ({1}/{2})", obj.Name, primNumber, objGroup.PrimCount);
//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}",
// name, obj.BaseMask, obj.OwnerMask, obj.EveryoneMask,
// permissionClass, checkPermissions, canCopy, canTransfer, permitted);
if (!partPermitted)
{
permitted = false;
break;
}
//++primNumber;
}
return permitted;
}
/// <summary> /// <summary>
/// Create the control file for the most up to date archive /// Create the control file for the most up to date archive
/// </summary> /// </summary>

View File

@ -128,6 +128,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver
// ops.Add("v|version=", delegate(string v) { options["version"] = v; }); // ops.Add("v|version=", delegate(string v) { options["version"] = v; });
ops.Add("p|profile=", delegate(string v) { options["profile"] = v; }); ops.Add("p|profile=", delegate(string v) { options["profile"] = v; });
ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; }); ops.Add("noassets", delegate(string v) { options["noassets"] = v != null; });
ops.Add("perm=", delegate(string v) { options["checkPermissions"] = v; });
List<string> mainParams = ops.Parse(cmdparams); List<string> mainParams = ops.Parse(cmdparams);

View File

@ -318,6 +318,10 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>())); new ArchiveWriteRequestPreparation(null, (Stream)null, Guid.Empty).CreateControlFile(new Dictionary<string, Object>()));
SceneObjectPart part1 = CreateSceneObjectPart1(); SceneObjectPart part1 = CreateSceneObjectPart1();
part1.SitTargetOrientation = new Quaternion(0.2f, 0.3f, 0.4f, 0.5f);
part1.SitTargetPosition = new Vector3(1, 2, 3);
SceneObjectGroup object1 = new SceneObjectGroup(part1); SceneObjectGroup object1 = new SceneObjectGroup(part1);
// Let's put some inventory items into our object // Let's put some inventory items into our object
@ -390,6 +394,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests
object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal"); object1PartLoaded.RotationOffset, Is.EqualTo(part1.RotationOffset), "object1 rotation offset not equal");
Assert.That( Assert.That(
object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal"); object1PartLoaded.OffsetPosition, Is.EqualTo(part1.OffsetPosition), "object1 offset position not equal");
Assert.That(object1PartLoaded.SitTargetOrientation, Is.EqualTo(part1.SitTargetOrientation));
Assert.That(object1PartLoaded.SitTargetPosition, Is.EqualTo(part1.SitTargetPosition));
TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0]; TaskInventoryItem loadedSoundItem = object1PartLoaded.Inventory.GetInventoryItems(soundItemName)[0];
Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null"); Assert.That(loadedSoundItem, Is.Not.Null, "loaded sound item was null");

View File

@ -992,6 +992,11 @@ namespace OpenSim.Region.CoreModules.World.Estate
args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3; args.terrainDetail2 = Scene.RegionInfo.RegionSettings.TerrainTexture3;
args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4; args.terrainDetail3 = Scene.RegionInfo.RegionSettings.TerrainTexture4;
// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 1 {0} for region {1}", args.terrainDetail0, Scene.RegionInfo.RegionName);
// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 2 {0} for region {1}", args.terrainDetail1, Scene.RegionInfo.RegionName);
// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 3 {0} for region {1}", args.terrainDetail2, Scene.RegionInfo.RegionName);
// m_log.DebugFormat("[ESTATE MANAGEMENT MODULE]: Sending terrain texture 4 {0} for region {1}", args.terrainDetail3, Scene.RegionInfo.RegionName);
remoteClient.SendRegionHandshake(Scene.RegionInfo,args); remoteClient.SendRegionHandshake(Scene.RegionInfo,args);
} }

View File

@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces;
namespace OpenSim.Region.CoreModules.World.Permissions namespace OpenSim.Region.CoreModules.World.Permissions
{ {
public class PermissionsModule : IRegionModule public class PermissionsModule : IRegionModule, IPermissionsModule
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -150,6 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
else else
m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks"); m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
scene.RegisterModuleInterface<IPermissionsModule>(this);
//Register functions with Scene External Checks! //Register functions with Scene External Checks!
m_scene.Permissions.OnBypassPermissions += BypassPermissions; m_scene.Permissions.OnBypassPermissions += BypassPermissions;
m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions; m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions;
@ -574,46 +576,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (objectOwner != UUID.Zero) if (objectOwner != UUID.Zero)
objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner; objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner;
if (m_bypassPermissions) PermissionClass permissionClass = GetPermissionClass(user, task);
return objectOwnerMask;
// Object owners should be able to edit their own content switch (permissionClass)
if (user == objectOwner)
return objectOwnerMask;
if (IsFriendWithPerms(user, objectOwner))
{ {
return objectOwnerMask; case PermissionClass.Owner:
}
// Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
{
return objectOwnerMask;
}
// Admin should be able to edit anything in the sim (including admin objects)
if (IsAdministrator(user))
{
return objectOwnerMask;
}
// Users should be able to edit what is over their land.
Vector3 taskPos = task.AbsolutePosition;
ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
{
// Admin objects should not be editable by the above
if (!IsAdministrator(objectOwner))
{
return objectOwnerMask; return objectOwnerMask;
} case PermissionClass.Group:
return objectGroupMask | objectEveryoneMask;
case PermissionClass.Everyone:
default:
return objectEveryoneMask;
} }
// Group permissions
if ((task.GroupID != UUID.Zero) && IsGroupMember(task.GroupID, user, 0))
return objectGroupMask | objectEveryoneMask;
return objectEveryoneMask;
} }
private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask) private uint ApplyObjectModifyMasks(uint setPermissionMask, uint objectFlagsMask)
@ -644,6 +618,47 @@ namespace OpenSim.Region.CoreModules.World.Permissions
return objectFlagsMask; return objectFlagsMask;
} }
public PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj)
{
if (obj == null)
return PermissionClass.Everyone;
if (m_bypassPermissions)
return PermissionClass.Owner;
// Object owners should be able to edit their own content
UUID objectOwner = obj.OwnerID;
if (user == objectOwner)
return PermissionClass.Owner;
if (IsFriendWithPerms(user, objectOwner))
return PermissionClass.Owner;
// Estate users should be able to edit anything in the sim if RegionOwnerIsGod is set
if (m_RegionOwnerIsGod && IsEstateManager(user) && !IsAdministrator(objectOwner))
return PermissionClass.Owner;
// Admin should be able to edit anything in the sim (including admin objects)
if (IsAdministrator(user))
return PermissionClass.Owner;
// Users should be able to edit what is over their land.
Vector3 taskPos = obj.AbsolutePosition;
ILandObject parcel = m_scene.LandChannel.GetLandObject(taskPos.X, taskPos.Y);
if (parcel != null && parcel.LandData.OwnerID == user && m_ParcelOwnerIsGod)
{
// Admin objects should not be editable by the above
if (!IsAdministrator(objectOwner))
return PermissionClass.Owner;
}
// Group permissions
if ((obj.GroupID != UUID.Zero) && IsGroupMember(obj.GroupID, user, 0))
return PermissionClass.Group;
return PermissionClass.Everyone;
}
/// <summary> /// <summary>
/// General permissions checks for any operation involving an object. These supplement more specific checks /// General permissions checks for any operation involving an object. These supplement more specific checks
/// implemented by callers. /// implemented by callers.

View File

@ -89,18 +89,13 @@ namespace OpenSim.Region.Framework.Interfaces
ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt); ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt);
/// <summary> /// <summary>
/// Rez an attachment from user inventory /// Rez an attachment from user inventory and change inventory status to match.
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="sp"></param>
/// <param name="itemID"></param> /// <param name="itemID"></param>
/// <param name="AttachmentPt"></param> /// <param name="AttachmentPt"></param>
/// <param name="updateinventoryStatus"> /// <returns>The scene object that was attached. Null if the scene object could not be found</returns>
/// If true, we also update the user's inventory to show that the attachment is set. If false, we do not. ISceneEntity RezSingleAttachmentFromInventory(ScenePresence sp, UUID itemID, uint AttachmentPt);
/// False is required so that we don't attempt to update information when a user enters a scene with the
/// attachment already correctly set up in inventory.
/// <returns>The uuid of the scene object that was attached. Null if the scene object could not be found</returns>
ISceneEntity RezSingleAttachmentFromInventory(
IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus);
// Same as above, but also load script states from a separate doc // Same as above, but also load script states from a separate doc
ISceneEntity RezSingleAttachmentFromInventory( ISceneEntity RezSingleAttachmentFromInventory(
@ -146,13 +141,10 @@ namespace OpenSim.Region.Framework.Interfaces
/// </param> /// </param>
void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient); void DetachSingleAttachmentToInv(UUID itemID, IClientAPI remoteClient);
/// <summary> /// Update the position of an attachment.
/// Update the user inventory with a changed attachment
/// </summary> /// </summary>
/// <param name="remoteClient"></param> /// <param name="sog"></param>
/// <param name="grp"></param> /// <param name="pos"></param>
/// <param name="itemID"></param> void UpdateAttachmentPosition(SceneObjectGroup sog, Vector3 pos);
/// <param name="agentID"></param>
void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID);
} }
} }

View File

@ -0,0 +1,54 @@
/*
* Copyright (c) Contributors, http://opensimulator.org/
* See CONTRIBUTORS.TXT for a full list of copyright holders.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the OpenSimulator Project nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
* EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
using OpenMetaverse;
using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
/// <value>
/// Which set of permissions a user has.
/// </value>
public enum PermissionClass
{
Owner,
Group,
Everyone
};
public interface IPermissionsModule
{
/// <summary>
/// Returns the type of permissions that the user has over an object.
/// </summary>
/// <param name="user">The user</param>
/// <param name="obj">The object</param>
/// <returns>The type of permissions the user has over the object</returns>
PermissionClass GetPermissionClass(UUID user, SceneObjectPart obj);
}
}

View File

@ -60,6 +60,14 @@ namespace OpenSim.Region.Framework.Interfaces
/// </remarks> /// </remarks>
AvatarAppearance Appearance { get; set; } AvatarAppearance Appearance { get; set; }
/// <summary>
/// The AttachmentsModule synchronizes on this to avoid race conditions between commands to add and remove attachments.
/// </summary>
/// <remarks>
/// All add and remove attachment operations must synchronize on this for the lifetime of their operations.
/// </remarks>
Object AttachmentsSyncLock { get; }
/// <summary> /// <summary>
/// The scene objects attached to this avatar. /// The scene objects attached to this avatar.
/// </summary> /// </summary>

View File

@ -30,12 +30,21 @@ using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces namespace OpenSim.Region.Framework.Interfaces
{ {
/// <summary>
/// Sends scheduled updates to it's associated ScenePresence.
/// </summary>
public interface ISceneViewer public interface ISceneViewer
{ {
void Reset(); // void Reset();
void Close(); void Close();
/// <summary>
/// Add the part to the queue of parts for which we need to send an update to the client
/// </summary>
/// <param name="part"></param>
void QueuePartForUpdate(SceneObjectPart part); void QueuePartForUpdate(SceneObjectPart part);
void SendPrimUpdates(); void SendPrimUpdates();
int GetPendingObjectsCount(); int GetPendingObjectsCount();
} }
} }

View File

@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
bool HasScript(UUID itemID, out bool running); bool HasScript(UUID itemID, out bool running);
void SaveAllState(); void SaveAllState();
/// <summary>
/// Starts the processing threads.
/// </summary>
void StartProcessing();
} }
} }

View File

@ -57,11 +57,11 @@ namespace OpenSim.Region.Framework.Scenes
protected AsyncInventorySender m_asyncInventorySender; protected AsyncInventorySender m_asyncInventorySender;
/// <summary> /// <summary>
/// Start all the scripts in the scene which should be started. /// Creates all the scripts in the scene which should be started.
/// </summary> /// </summary>
public void CreateScriptInstances() public void CreateScriptInstances()
{ {
m_log.Info("[PRIM INVENTORY]: Starting scripts in scene"); m_log.Info("[PRIM INVENTORY]: Creating scripts in scene");
EntityBase[] entities = Entities.GetEntities(); EntityBase[] entities = Entities.GetEntities();
foreach (EntityBase group in entities) foreach (EntityBase group in entities)
@ -74,6 +74,26 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
/// <summary>
/// Lets the script engines start processing scripts.
/// </summary>
public void StartScripts()
{
m_log.Info("[PRIM INVENTORY]: Starting scripts in scene");
IScriptModule[] engines = RequestModuleInterfaces<IScriptModule>();
if (engines != null)
{
foreach (IScriptModule engine in engines)
{
if (engine != null)
{
engine.StartProcessing();
}
}
}
}
public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item) public void AddUploadedInventoryItem(UUID agentID, InventoryItemBase item)
{ {
IMoneyModule money = RequestModuleInterface<IMoneyModule>(); IMoneyModule money = RequestModuleInterface<IMoneyModule>();

View File

@ -610,9 +610,42 @@ namespace OpenSim.Region.Framework.Scenes
#region Region Settings #region Region Settings
// Load region settings // Load region settings
m_regInfo.WindlightSettings = SimulationDataService.LoadRegionWindlightSettings(m_regInfo.RegionID); // LoadRegionSettings creates new region settings in persistence if they don't already exist for this region.
// However, in this case, the default textures are not set in memory properly, so we need to do it here and
// resave.
// FIXME: It shouldn't be up to the database plugins to create this data - we should do it when a new
// region is set up and avoid these gyrations.
RegionSettings rs = simDataService.LoadRegionSettings(m_regInfo.RegionID);
bool updatedTerrainTextures = false;
if (rs.TerrainTexture1 == UUID.Zero)
{
rs.TerrainTexture1 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_1;
updatedTerrainTextures = true;
}
if (rs.TerrainTexture2 == UUID.Zero)
{
rs.TerrainTexture2 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_2;
updatedTerrainTextures = true;
}
if (rs.TerrainTexture3 == UUID.Zero)
{
rs.TerrainTexture3 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_3;
updatedTerrainTextures = true;
}
if (rs.TerrainTexture4 == UUID.Zero)
{
rs.TerrainTexture4 = RegionSettings.DEFAULT_TERRAIN_TEXTURE_4;
updatedTerrainTextures = true;
}
if (updatedTerrainTextures)
rs.Save();
m_regInfo.RegionSettings = rs;
m_regInfo.RegionSettings = simDataService.LoadRegionSettings(m_regInfo.RegionID);
if (estateDataService != null) if (estateDataService != null)
m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false); m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@ -645,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
EventManager.OnLandObjectRemoved += EventManager.OnLandObjectRemoved +=
new EventManager.LandObjectRemoved(simDataService.RemoveLandObject); new EventManager.LandObjectRemoved(simDataService.RemoveLandObject);
m_sceneGraph = new SceneGraph(this, m_regInfo); m_sceneGraph = new SceneGraph(this);
// If the scene graph has an Unrecoverable error, restart this sim. // If the scene graph has an Unrecoverable error, restart this sim.
// Currently the only thing that causes it to happen is two kinds of specific // Currently the only thing that causes it to happen is two kinds of specific
@ -1575,7 +1608,9 @@ namespace OpenSim.Region.Framework.Scenes
msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID; msg.ParentEstateID = RegionInfo.EstateSettings.ParentEstateID;
msg.Position = Vector3.Zero; msg.Position = Vector3.Zero;
msg.RegionID = RegionInfo.RegionID.Guid; msg.RegionID = RegionInfo.RegionID.Guid;
msg.binaryBucket = new byte[0];
// We must fill in a null-terminated 'empty' string here since bytes[0] will crash viewer 3.
msg.binaryBucket = Util.StringToBytes256("\0");
if (ret.Value.count > 1) if (ret.Value.count > 1)
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); 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);
else else
@ -2492,14 +2527,16 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>False</returns> /// <returns>False</returns>
public virtual bool IncomingCreateObject(UUID userID, UUID itemID) public virtual bool IncomingCreateObject(UUID userID, UUID itemID)
{ {
//m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID); m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID);
ScenePresence sp = GetScenePresence(userID); // Commented out since this is as yet unused and is arguably not the appropriate place to do this, as
if (sp != null && AttachmentsModule != null) // attachments are being rezzed elsewhere in AddNewClient()
{ // ScenePresence sp = GetScenePresence(userID);
uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID); // if (sp != null && AttachmentsModule != null)
AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt); // {
} // uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID);
// AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt);
// }
return false; return false;
} }
@ -3272,8 +3309,8 @@ namespace OpenSim.Region.Framework.Scenes
if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc) if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
AttachmentsModule.SaveChangedAttachments(avatar); AttachmentsModule.SaveChangedAttachments(avatar);
if (avatar != null && (!avatar.IsChildAgent)) if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
avatar.SaveChangedAttachments(); AttachmentsModule.SaveChangedAttachments(avatar);
ForEachClient( ForEachClient(
delegate(IClientAPI client) delegate(IClientAPI client)

View File

@ -83,7 +83,6 @@ namespace OpenSim.Region.Framework.Scenes
protected internal EntityManager Entities = new EntityManager(); protected internal EntityManager Entities = new EntityManager();
protected RegionInfo m_regInfo;
protected Scene m_parentScene; protected Scene m_parentScene;
protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>(); protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>();
protected int m_numRootAgents = 0; protected int m_numRootAgents = 0;
@ -117,10 +116,9 @@ namespace OpenSim.Region.Framework.Scenes
#endregion #endregion
protected internal SceneGraph(Scene parent, RegionInfo regInfo) protected internal SceneGraph(Scene parent)
{ {
m_parentScene = parent; m_parentScene = parent;
m_regInfo = regInfo;
} }
public PhysicsScene PhysicsScene public PhysicsScene PhysicsScene
@ -131,7 +129,6 @@ namespace OpenSim.Region.Framework.Scenes
// If we're not doing the initial set // If we're not doing the initial set
// Then we've got to remove the previous // Then we've got to remove the previous
// event handler // event handler
if (_PhyScene != null) if (_PhyScene != null)
_PhyScene.OnPhysicsCrash -= physicsBasedCrash; _PhyScene.OnPhysicsCrash -= physicsBasedCrash;
@ -413,12 +410,12 @@ namespace OpenSim.Region.Framework.Scenes
// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}", // "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName); // sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
SceneObjectPart[] children = sceneObject.Parts; SceneObjectPart[] parts = sceneObject.Parts;
// Clamp child prim sizes and add child prims to the m_numPrim count // Clamp child prim sizes and add child prims to the m_numPrim count
if (m_parentScene.m_clampPrimSize) if (m_parentScene.m_clampPrimSize)
{ {
foreach (SceneObjectPart part in children) foreach (SceneObjectPart part in parts)
{ {
Vector3 scale = part.Shape.Scale; Vector3 scale = part.Shape.Scale;
@ -432,7 +429,7 @@ namespace OpenSim.Region.Framework.Scenes
part.Shape.Scale = scale; part.Shape.Scale = scale;
} }
} }
m_numPrim += children.Length; m_numPrim += parts.Length;
sceneObject.AttachToScene(m_parentScene); sceneObject.AttachToScene(m_parentScene);
@ -452,15 +449,17 @@ namespace OpenSim.Region.Framework.Scenes
lock (SceneObjectGroupsByFullPartID) lock (SceneObjectGroupsByFullPartID)
{ {
SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject; foreach (SceneObjectPart part in parts)
foreach (SceneObjectPart part in children)
SceneObjectGroupsByFullPartID[part.UUID] = sceneObject; SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
} }
lock (SceneObjectGroupsByLocalPartID) lock (SceneObjectGroupsByLocalPartID)
{ {
SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject; // m_log.DebugFormat(
foreach (SceneObjectPart part in children) // "[SCENE GRAPH]: Adding scene object {0} {1} {2} to SceneObjectGroupsByLocalPartID in {3}",
// sceneObject.Name, sceneObject.UUID, sceneObject.LocalId, m_parentScene.RegionInfo.RegionName);
foreach (SceneObjectPart part in parts)
SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject; SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
} }
@ -473,6 +472,10 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>true if the object was deleted, false if there was no object to delete</returns> /// <returns>true if the object was deleted, false if there was no object to delete</returns>
public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked) public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked)
{ {
// m_log.DebugFormat(
// "[SCENE GRAPH]: Deleting scene object with uuid {0}, resultOfObjectLinked = {1}",
// uuid, resultOfObjectLinked);
EntityBase entity; EntityBase entity;
if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup))) if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup)))
return false; return false;
@ -501,7 +504,6 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart[] parts = grp.Parts; SceneObjectPart[] parts = grp.Parts;
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
SceneObjectGroupsByFullPartID.Remove(parts[i].UUID); SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID);
} }
lock (SceneObjectGroupsByLocalPartID) lock (SceneObjectGroupsByLocalPartID)
@ -509,7 +511,6 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart[] parts = grp.Parts; SceneObjectPart[] parts = grp.Parts;
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId); SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId);
} }
return Entities.Remove(uuid); return Entities.Remove(uuid);
@ -654,7 +655,7 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence newAvatar = null; ScenePresence newAvatar = null;
// ScenePresence always defaults to child agent // ScenePresence always defaults to child agent
newAvatar = new ScenePresence(client, m_parentScene, m_regInfo, appearance, type); newAvatar = new ScenePresence(client, m_parentScene, appearance, type);
AddScenePresence(newAvatar); AddScenePresence(newAvatar);
@ -721,7 +722,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!Entities.Remove(agentID)) if (!Entities.Remove(agentID))
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", "[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
agentID); agentID);
} }
@ -745,7 +746,7 @@ namespace OpenSim.Region.Framework.Scenes
} }
else else
{ {
m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); m_log.WarnFormat("[SCENE GRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
} }
} }
finally finally
@ -956,7 +957,8 @@ namespace OpenSim.Region.Framework.Scenes
if (Entities.TryGetValue(localID, out entity)) if (Entities.TryGetValue(localID, out entity))
return entity as SceneObjectGroup; return entity as SceneObjectGroup;
//m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); // m_log.DebugFormat("[SCENE GRAPH]: Entered GetGroupByPrim with localID {0}", localID);
SceneObjectGroup sog; SceneObjectGroup sog;
lock (SceneObjectGroupsByLocalPartID) lock (SceneObjectGroupsByLocalPartID)
SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog); SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog);
@ -964,8 +966,24 @@ namespace OpenSim.Region.Framework.Scenes
if (sog != null) if (sog != null)
{ {
if (sog.HasChildPrim(localID)) if (sog.HasChildPrim(localID))
{
// m_log.DebugFormat(
// "[SCENE GRAPH]: Found scene object {0} {1} {2} containing part with local id {3} in {4}. Returning.",
// sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
return sog; return sog;
SceneObjectGroupsByLocalPartID.Remove(localID); }
else
{
lock (SceneObjectGroupsByLocalPartID)
{
m_log.WarnFormat(
"[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}.",
sog.Name, sog.UUID, sog.LocalId, localID, m_parentScene.RegionInfo.RegionName);
SceneObjectGroupsByLocalPartID.Remove(localID);
}
}
} }
EntityBase[] entityList = GetEntities(); EntityBase[] entityList = GetEntities();

View File

@ -388,5 +388,18 @@ namespace OpenSim.Region.Framework.Scenes
for (int i = 0; i < parts.Length; i++) for (int i = 0; i < parts.Length; i++)
parts[i].Inventory.ResumeScripts(); parts[i].Inventory.ResumeScripts();
} }
/// <summary>
/// Returns true if any part in the scene object contains scripts, false otherwise.
/// </summary>
/// <returns></returns>
public bool ContainsScripts()
{
foreach (SceneObjectPart part in Parts)
if (part.Inventory.ContainsScripts())
return true;
return false;
}
} }
} }

View File

@ -1239,10 +1239,15 @@ namespace OpenSim.Region.Framework.Scenes
item.CurrentPermissions = perms; item.CurrentPermissions = perms;
item.BasePermissions = perms; item.BasePermissions = perms;
} }
m_inventorySerial++; m_inventorySerial++;
HasInventoryChanged = true; HasInventoryChanged = true;
} }
/// <summary>
/// Returns true if this part inventory contains any scripts. False otherwise.
/// </summary>
/// <returns></returns>
public bool ContainsScripts() public bool ContainsScripts()
{ {
foreach (TaskInventoryItem item in m_items.Values) foreach (TaskInventoryItem item in m_items.Values)

View File

@ -124,6 +124,8 @@ namespace OpenSim.Region.Framework.Scenes
protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>(); protected List<SceneObjectGroup> m_attachments = new List<SceneObjectGroup>();
public Object AttachmentsSyncLock { get; private set; }
private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>(); private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO; private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO; private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
@ -199,7 +201,6 @@ namespace OpenSim.Region.Framework.Scenes
private float m_health = 100f; private float m_health = 100f;
protected RegionInfo m_regionInfo;
protected ulong crossingFromRegion; protected ulong crossingFromRegion;
private readonly Vector3[] Dir_Vectors = new Vector3[11]; private readonly Vector3[] Dir_Vectors = new Vector3[11];
@ -770,23 +771,24 @@ namespace OpenSim.Region.Framework.Scenes
#endregion #endregion
#region Constructor(s) #region Constructor(s)
public ScenePresence( public ScenePresence(
IClientAPI client, Scene world, RegionInfo reginfo, AvatarAppearance appearance, PresenceType type) IClientAPI client, Scene world, AvatarAppearance appearance, PresenceType type)
{ {
AttachmentsSyncLock = new Object();
m_sendCourseLocationsMethod = SendCoarseLocationsDefault; m_sendCourseLocationsMethod = SendCoarseLocationsDefault;
m_sceneViewer = new SceneViewer(this); m_sceneViewer = new SceneViewer(this);
m_animator = new ScenePresenceAnimator(this); m_animator = new ScenePresenceAnimator(this);
PresenceType = type; PresenceType = type;
m_DrawDistance = world.DefaultDrawDistance; m_DrawDistance = world.DefaultDrawDistance;
m_rootRegionHandle = reginfo.RegionHandle; m_rootRegionHandle = world.RegionInfo.RegionHandle;
m_controllingClient = client; m_controllingClient = client;
m_firstname = m_controllingClient.FirstName; m_firstname = m_controllingClient.FirstName;
m_lastname = m_controllingClient.LastName; m_lastname = m_controllingClient.LastName;
m_name = String.Format("{0} {1}", m_firstname, m_lastname); m_name = String.Format("{0} {1}", m_firstname, m_lastname);
m_scene = world; m_scene = world;
m_uuid = client.AgentId; m_uuid = client.AgentId;
m_regionInfo = reginfo;
m_localId = m_scene.AllocateLocalId(); m_localId = m_scene.AllocateLocalId();
UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid); UserAccount account = m_scene.UserAccountService.GetUserAccount(m_scene.RegionInfo.ScopeID, m_uuid);
@ -1302,7 +1304,7 @@ namespace OpenSim.Region.Framework.Scenes
//m_log.DebugFormat("Completed movement"); //m_log.DebugFormat("Completed movement");
m_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look); m_controllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
SendInitialData(); SendInitialData();
// Create child agents in neighbouring regions // Create child agents in neighbouring regions
@ -3226,8 +3228,8 @@ namespace OpenSim.Region.Framework.Scenes
/// </returns> /// </returns>
protected int HaveNeighbor(Cardinals car, ref int[] fix) protected int HaveNeighbor(Cardinals car, ref int[] fix)
{ {
uint neighbourx = m_regionInfo.RegionLocX; uint neighbourx = m_scene.RegionInfo.RegionLocX;
uint neighboury = m_regionInfo.RegionLocY; uint neighboury = m_scene.RegionInfo.RegionLocY;
int dir = (int)car; int dir = (int)car;
@ -3247,8 +3249,8 @@ namespace OpenSim.Region.Framework.Scenes
if (neighbourRegion == null) if (neighbourRegion == null)
{ {
fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx); fix[0] = (int)(m_scene.RegionInfo.RegionLocX - neighbourx);
fix[1] = (int)(m_regionInfo.RegionLocY - neighboury); fix[1] = (int)(m_scene.RegionInfo.RegionLocY - neighboury);
return dir * (-1); return dir * (-1);
} }
else else
@ -3494,26 +3496,30 @@ namespace OpenSim.Region.Framework.Scenes
catch { } catch { }
// Attachment objects // Attachment objects
if (m_attachments != null && m_attachments.Count > 0) lock (m_attachments)
{ {
cAgent.AttachmentObjects = new List<ISceneObject>(); if (m_attachments.Count > 0)
cAgent.AttachmentObjectStates = new List<string>();
// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
m_InTransitScriptStates.Clear();
foreach (SceneObjectGroup sog in m_attachments)
{ {
// We need to make a copy and pass that copy cAgent.AttachmentObjects = new List<ISceneObject>();
// because of transfers withn the same sim cAgent.AttachmentObjectStates = new List<string>();
ISceneObject clone = sog.CloneForNewScene(); // IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
// Attachment module assumes that GroupPosition holds the offsets...! m_InTransitScriptStates.Clear();
((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
((SceneObjectGroup)clone).IsAttachment = false; foreach (SceneObjectGroup sog in m_attachments)
cAgent.AttachmentObjects.Add(clone); {
string state = sog.GetStateSnapshot(); // We need to make a copy and pass that copy
cAgent.AttachmentObjectStates.Add(state); // because of transfers withn the same sim
m_InTransitScriptStates.Add(state); ISceneObject clone = sog.CloneForNewScene();
// Let's remove the scripts of the original object here // Attachment module assumes that GroupPosition holds the offsets...!
sog.RemoveScriptInstances(true); ((SceneObjectGroup)clone).RootPart.GroupPosition = sog.RootPart.AttachedPos;
((SceneObjectGroup)clone).IsAttachment = false;
cAgent.AttachmentObjects.Add(clone);
string state = sog.GetStateSnapshot();
cAgent.AttachmentObjectStates.Add(state);
m_InTransitScriptStates.Add(state);
// Let's remove the scripts of the original object here
sog.RemoveScriptInstances(true);
}
} }
} }
} }
@ -3931,7 +3937,8 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
public void Close() public void Close()
{ {
m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false); if (!IsChildAgent)
m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false);
lock (m_knownChildRegions) lock (m_knownChildRegions)
{ {
@ -4035,8 +4042,13 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
m_attachments.Clear(); m_attachments.Clear();
} }
/// <summary>
/// This is currently just being done for information.
/// </summary>
public bool ValidateAttachments() public bool ValidateAttachments()
{ {
bool validated = true;
lock (m_attachments) lock (m_attachments)
{ {
// Validate // Validate
@ -4045,21 +4057,22 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
if (gobj == null) if (gobj == null)
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null", Name); "[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null. Continuing", Name);
return false;
}
if (gobj.IsDeleted) validated = false;
}
else if (gobj.IsDeleted)
{ {
m_log.WarnFormat( m_log.WarnFormat(
"[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted", "[SCENE PRESENCE]: Failed to validate attachment {0} {1} for {2} since it had been deleted. Continuing",
gobj.Name, gobj.UUID, Name); gobj.Name, gobj.UUID, Name);
return false;
validated = false;
} }
} }
} }
return true; return validated;
} }
/// <summary> /// <summary>
@ -4091,29 +4104,6 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
} }
} }
public void initializeScenePresence(IClientAPI client, RegionInfo region, Scene scene)
{
m_controllingClient = client;
m_regionInfo = region;
m_scene = scene;
RegisterToEvents();
/*
AbsolutePosition = client.StartPos;
Animations = new AvatarAnimations();
Animations.LoadAnims();
m_animations = new List<UUID>();
m_animations.Add(Animations.AnimsUUID["STAND"]);
m_animationSeqs.Add(m_controllingClient.NextAnimationSequenceNumber);
SetDirectionVectors();
*/
}
internal void PushForce(Vector3 impulse) internal void PushForce(Vector3 impulse)
{ {
if (PhysicsActor != null) if (PhysicsActor != null)
@ -4141,6 +4131,7 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
obj.ignoreControls = (ScriptControlled)controls; obj.ignoreControls = (ScriptControlled)controls;
obj.eventControls = (ScriptControlled)controls; obj.eventControls = (ScriptControlled)controls;
} }
if (pass_on == 1 && accept == 1) if (pass_on == 1 && accept == 1)
{ {
IgnoredControls = ScriptControlled.CONTROL_ZERO; IgnoredControls = ScriptControlled.CONTROL_ZERO;
@ -4161,6 +4152,7 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
scriptedcontrols[Script_item_UUID] = obj; scriptedcontrols[Script_item_UUID] = obj;
} }
} }
ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true); ControllingClient.SendTakeControls(controls, pass_on == 1 ? true : false, true);
} }
@ -4351,29 +4343,6 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
return(new Vector3(x,y,z)); return(new Vector3(x,y,z));
} }
public void SaveChangedAttachments()
{
// Need to copy this list because DetachToInventoryPrep mods it
List<SceneObjectGroup> attachments = new List<SceneObjectGroup>(GetAttachments().ToArray());
IAttachmentsModule attachmentsModule = m_scene.AttachmentsModule;
if (attachmentsModule != null)
{
foreach (SceneObjectGroup grp in attachments)
{
if (grp.HasGroupChanged) // Resizer scripts?
{
grp.IsAttachment = false;
grp.AbsolutePosition = grp.RootPart.AttachedPos;
// grp.DetachToInventoryPrep();
attachmentsModule.UpdateKnownItem(ControllingClient,
grp, grp.GetFromItemID(), grp.OwnerID);
grp.IsAttachment = true;
}
}
}
}
private void CheckLandingPoint(ref Vector3 pos) private void CheckLandingPoint(ref Vector3 pos)
{ {
// Never constrain lures // Never constrain lures

View File

@ -38,27 +38,42 @@ namespace OpenSim.Region.Framework.Scenes
{ {
public class SceneViewer : ISceneViewer public class SceneViewer : ISceneViewer
{ {
/// <summary>
/// Is this scene viewer enabled?
/// </summary>
private bool IsEnabled { get; set; }
/// <summary>
/// The scene presence serviced by this viewer.
/// </summary>
protected ScenePresence m_presence; protected ScenePresence m_presence;
/// <summary>
/// The queue of parts for which we need to send out updates.
/// </summary>
protected UpdateQueue m_partsUpdateQueue = new UpdateQueue(); protected UpdateQueue m_partsUpdateQueue = new UpdateQueue();
/// <summary>
/// The queue of objects for which we need to send out updates.
/// </summary>
protected Queue<SceneObjectGroup> m_pendingObjects; protected Queue<SceneObjectGroup> m_pendingObjects;
/// <summary>
/// The last update assocated with a given part update.
/// </summary>
protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>(); protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
public SceneViewer()
{
}
public SceneViewer(ScenePresence presence) public SceneViewer(ScenePresence presence)
{ {
m_presence = presence; m_presence = presence;
IsEnabled = true;
} }
/// <summary>
/// Add the part to the queue of parts for which we need to send an update to the client
/// </summary>
/// <param name="part"></param>
public void QueuePartForUpdate(SceneObjectPart part) public void QueuePartForUpdate(SceneObjectPart part)
{ {
if (!IsEnabled)
return;
lock (m_partsUpdateQueue) lock (m_partsUpdateQueue)
{ {
m_partsUpdateQueue.Enqueue(part); m_partsUpdateQueue.Enqueue(part);
@ -87,6 +102,11 @@ namespace OpenSim.Region.Framework.Scenes
lock (m_pendingObjects) lock (m_pendingObjects)
{ {
// We must do this under lock so that we don't suffer a race condition if another thread closes the
// viewer
if (!IsEnabled)
return;
while (m_pendingObjects != null && m_pendingObjects.Count > 0) while (m_pendingObjects != null && m_pendingObjects.Count > 0)
{ {
SceneObjectGroup g = m_pendingObjects.Dequeue(); SceneObjectGroup g = m_pendingObjects.Dequeue();
@ -119,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes
// We deal with the possibility that two updates occur at // We deal with the possibility that two updates occur at
// the same unix time at the update point itself. // the same unix time at the update point itself.
if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment) if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment)
{ {
// m_log.DebugFormat( // m_log.DebugFormat(
@ -135,9 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
// this update. If this happened, then subsequent // this update. If this happened, then subsequent
// updates which occurred on the same tick or the // updates which occurred on the same tick or the
// next tick of the last update would be ignored. // next tick of the last update would be ignored.
update.LastFullUpdateTime = part.TimeStampFull; update.LastFullUpdateTime = part.TimeStampFull;
} }
else if (update.LastTerseUpdateTime <= part.TimeStampTerse) else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
{ {
@ -176,38 +193,46 @@ namespace OpenSim.Region.Framework.Scenes
} }
} }
public void Reset() // public void Reset()
{ // {
if (m_pendingObjects == null) // if (m_pendingObjects == null)
return; // return;
//
lock (m_pendingObjects) // lock (m_pendingObjects)
{ // {
if (m_pendingObjects != null) // if (m_pendingObjects != null)
{ // {
m_pendingObjects.Clear(); // m_pendingObjects.Clear();
m_pendingObjects = null; // m_pendingObjects = null;
} // }
} // }
} // }
public void Close() public void Close()
{ {
lock (m_updateTimes) lock (m_pendingObjects)
{ {
m_updateTimes.Clear(); // We perform this under the m_pendingObjects lock in order to avoid a race condition with another
// thread on SendPrimUpdates()
IsEnabled = false;
lock (m_updateTimes)
{
m_updateTimes.Clear();
}
lock (m_partsUpdateQueue)
{
m_partsUpdateQueue.Clear();
}
} }
lock (m_partsUpdateQueue)
{
m_partsUpdateQueue.Clear();
}
Reset();
} }
public int GetPendingObjectsCount() public int GetPendingObjectsCount()
{ {
if (m_pendingObjects != null) if (m_pendingObjects != null)
return m_pendingObjects.Count; lock (m_pendingObjects)
return m_pendingObjects.Count;
return 0; return 0;
} }

View File

@ -52,22 +52,25 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestHelpers.InMethod(); TestHelpers.InMethod();
Scene scene = SceneHelpers.SetupScene(); Scene scene = SceneHelpers.SetupScene();
int partsToTestCount = 3;
string objName = "obj1"; SceneObjectGroup so
UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001"); = SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
SceneObjectPart[] parts = so.Parts;
SceneObjectPart part Assert.That(scene.AddNewSceneObject(so, false), Is.True);
= new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero) SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID);
{ Name = objName, UUID = objUuid }; SceneObjectPart[] retrievedParts = retrievedSo.Parts;
Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part), false), Is.True);
SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid);
//m_log.Debug("retrievedPart : {0}", retrievedPart); //m_log.Debug("retrievedPart : {0}", retrievedPart);
// If the parts have the same UUID then we will consider them as one and the same // If the parts have the same UUID then we will consider them as one and the same
Assert.That(retrievedPart.Name, Is.EqualTo(objName)); Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount));
Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid));
for (int i = 0; i < partsToTestCount; i++)
{
Assert.That(retrievedParts[i].Name, Is.EqualTo(parts[i].Name));
Assert.That(retrievedParts[i].UUID, Is.EqualTo(parts[i].UUID));
}
} }
[Test] [Test]
@ -103,6 +106,39 @@ namespace OpenSim.Region.Framework.Scenes.Tests
Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name)); Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name));
Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid)); Assert.That(retrievedPart.UUID, Is.EqualTo(objUuid));
} }
/// <summary>
/// Test retrieving a scene object via the local id of one of its parts.
/// </summary>
[Test]
public void TestGetSceneObjectByPartLocalId()
{
TestHelpers.InMethod();
Scene scene = SceneHelpers.SetupScene();
int partsToTestCount = 3;
SceneObjectGroup so
= SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
SceneObjectPart[] parts = so.Parts;
scene.AddNewSceneObject(so, false);
// Test getting via the root part's local id
Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Not.Null);
// Test getting via a non root part's local id
Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Not.Null);
// Test that we don't get back an object for a local id that doesn't exist
Assert.That(scene.GetGroupByPrim(999), Is.Null);
// Now delete the scene object and check again
scene.DeleteSceneObject(so, false);
Assert.That(scene.GetGroupByPrim(so.LocalId), Is.Null);
Assert.That(scene.GetGroupByPrim(parts[partsToTestCount - 1].LocalId), Is.Null);
}
/// <summary> /// <summary>
/// Test deleting an object from a scene. /// Test deleting an object from a scene.

View File

@ -43,11 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Gather uuids for a given entity. /// Gather uuids for a given entity.
/// </summary> /// </summary>
/// /// <remarks>
/// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts /// This does a deep inspection of the entity to retrieve all the assets it uses (whether as textures, as scripts
/// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets /// contained in inventory, as scripts contained in objects contained in another object's inventory, etc. Assets
/// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be /// are only retrieved when they are necessary to carry out the inspection (i.e. a serialized object needs to be
/// retrieved to work out which assets it references). /// retrieved to work out which assets it references).
/// </remarks>
public class UuidGatherer public class UuidGatherer
{ {
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -76,11 +77,11 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Gather all the asset uuids associated with the asset referenced by a given uuid /// Gather all the asset uuids associated with the asset referenced by a given uuid
/// </summary> /// </summary>
/// /// <remarks>
/// This includes both those directly associated with /// This includes both those directly associated with
/// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
/// within this object). /// within this object).
/// /// </remarks>
/// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param> /// <param name="assetUuid">The uuid of the asset for which to gather referenced assets</param>
/// <param name="assetType">The type of the asset for the uuid given</param> /// <param name="assetType">The type of the asset for the uuid given</param>
/// <param name="assetUuids">The assets gathered</param> /// <param name="assetUuids">The assets gathered</param>
@ -119,11 +120,11 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary> /// <summary>
/// Gather all the asset uuids associated with a given object. /// Gather all the asset uuids associated with a given object.
/// </summary> /// </summary>
/// /// <remarks>
/// This includes both those directly associated with /// This includes both those directly associated with
/// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained /// it (e.g. face textures) and recursively, those of items within it's inventory (e.g. objects contained
/// within this object). /// within this object).
/// /// </remarks>
/// <param name="sceneObject">The scene object for which to gather assets</param> /// <param name="sceneObject">The scene object for which to gather assets</param>
/// <param name="assetUuids">The assets gathered</param> /// <param name="assetUuids">The assets gathered</param>
public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids) public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids)

View File

@ -26,6 +26,7 @@
*/ */
using System; using System;
using System.Collections.Generic;
using System.Reflection; using System.Reflection;
using log4net; using log4net;
using Nini.Config; using Nini.Config;
@ -33,7 +34,9 @@ using NUnit.Framework;
using OpenMetaverse; using OpenMetaverse;
using OpenSim.Framework; using OpenSim.Framework;
using OpenSim.Framework.Communications; using OpenSim.Framework.Communications;
using OpenSim.Region.CoreModules.Avatar.Attachments;
using OpenSim.Region.CoreModules.Avatar.AvatarFactory; using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
using OpenSim.Region.CoreModules.Framework.InventoryAccess;
using OpenSim.Region.CoreModules.Framework.UserManagement; using OpenSim.Region.CoreModules.Framework.UserManagement;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar; using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar;
using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Interfaces;
@ -47,21 +50,49 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
[TestFixture] [TestFixture]
public class NPCModuleTests public class NPCModuleTests
{ {
private TestScene scene;
private AvatarFactoryModule afm;
private UserManagementModule umm;
private AttachmentsModule am;
[TestFixtureSetUp]
public void FixtureInit()
{
// Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
Util.FireAndForgetMethod = FireAndForgetMethod.None;
}
[TestFixtureTearDown]
public void TearDown()
{
// We must set this back afterwards, otherwise later tests will fail since they're expecting multiple
// threads. Possibly, later tests should be rewritten not to worry about such things.
Util.FireAndForgetMethod = Util.DefaultFireAndForgetMethod;
}
[SetUp]
public void Init()
{
IConfigSource config = new IniConfigSource();
config.AddConfig("NPC");
config.Configs["NPC"].Set("Enabled", "true");
config.AddConfig("Modules");
config.Configs["Modules"].Set("InventoryAccessModule", "BasicInventoryAccessModule");
afm = new AvatarFactoryModule();
umm = new UserManagementModule();
am = new AttachmentsModule();
scene = SceneHelpers.SetupScene();
SceneHelpers.SetupSceneModules(scene, config, afm, umm, am, new BasicInventoryAccessModule(), new NPCModule());
}
[Test] [Test]
public void TestCreate() public void TestCreate()
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // log4net.Config.XmlConfigurator.Configure();
IConfigSource config = new IniConfigSource();
config.AddConfig("NPC");
config.Configs["NPC"].Set("Enabled", "true");
AvatarFactoryModule afm = new AvatarFactoryModule();
UserManagementModule umm = new UserManagementModule();
TestScene scene = SceneHelpers.SetupScene();
SceneHelpers.SetupSceneModules(scene, config, afm, umm, new NPCModule());
ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); // ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);
@ -87,19 +118,54 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
Assert.That(umm.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname))); Assert.That(umm.GetUserName(npc.UUID), Is.EqualTo(string.Format("{0} {1}", npc.Firstname, npc.Lastname)));
} }
[Test]
public void TestAttachments()
{
TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure();
UUID userId = TestHelpers.ParseTail(0x1);
UserAccountHelpers.CreateUserWithInventory(scene, userId);
ScenePresence sp = SceneHelpers.AddScenePresence(scene, userId);
UUID attItemId = TestHelpers.ParseTail(0x2);
UUID attAssetId = TestHelpers.ParseTail(0x3);
string attName = "att";
UserInventoryHelpers.CreateInventoryItem(
scene, attName, attItemId, attAssetId, sp.UUID, InventoryType.Object);
am.RezSingleAttachmentFromInventory(
sp.ControllingClient, attItemId, (uint)AttachmentPoint.Chest);
INPCModule npcModule = scene.RequestModuleInterface<INPCModule>();
UUID npcId = npcModule.CreateNPC("John", "Smith", new Vector3(128, 128, 30), scene, sp.Appearance);
ScenePresence npc = scene.GetScenePresence(npcId);
// Check scene presence status
Assert.That(npc.HasAttachments(), Is.True);
List<SceneObjectGroup> attachments = npc.GetAttachments();
Assert.That(attachments.Count, Is.EqualTo(1));
SceneObjectGroup attSo = attachments[0];
// Just for now, we won't test the name since this is (wrongly) the asset part name rather than the item
// name. TODO: Do need to fix ultimately since the item may be renamed before being passed on to an NPC.
// Assert.That(attSo.Name, Is.EqualTo(attName));
Assert.That(attSo.AttachmentPoint, Is.EqualTo((byte)AttachmentPoint.Chest));
Assert.That(attSo.IsAttachment);
Assert.That(attSo.UsesPhysics, Is.False);
Assert.That(attSo.IsTemporary, Is.False);
Assert.That(attSo.OwnerID, Is.EqualTo(npc.UUID));
}
[Test] [Test]
public void TestMove() public void TestMove()
{ {
TestHelpers.InMethod(); TestHelpers.InMethod();
// log4net.Config.XmlConfigurator.Configure(); // log4net.Config.XmlConfigurator.Configure();
IConfigSource config = new IniConfigSource();
config.AddConfig("NPC");
config.Configs["NPC"].Set("Enabled", "true");
TestScene scene = SceneHelpers.SetupScene();
SceneHelpers.SetupSceneModules(scene, config, new NPCModule());
ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1)); ScenePresence sp = SceneHelpers.AddScenePresence(scene, TestHelpers.ParseTail(0x1));
// ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId); // ScenePresence originalAvatar = scene.GetScenePresence(originalClient.AgentId);

View File

@ -7040,6 +7040,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve) protected ObjectShapePacket.ObjectDataBlock SetPrimitiveBlockShapeParams(SceneObjectPart part, int holeshape, LSL_Vector cut, float hollow, LSL_Vector twist, byte profileshape, byte pathcurve)
{ {
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock(); ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return shapeBlock; return shapeBlock;
@ -7123,8 +7124,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
twist.y = 1.0f; twist.y = 1.0f;
} }
shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x); // A fairly large precision error occurs for some calculations,
shapeBlock.PathTwist = (sbyte)(100 * twist.y); // if a float or double is directly cast to a byte or sbyte
// variable, in both .Net and Mono. In .Net, coding
// "(sbyte)(float)(some expression)" corrects the precision
// errors. But this does not work for Mono. This longer coding
// form of creating a tempoary float variable from the
// expression first, then casting that variable to a byte or
// sbyte, works for both .Net and Mono. These types of
// assignments occur in SetPrimtiveBlockShapeParams and
// SetPrimitiveShapeParams in support of llSetPrimitiveParams.
tempFloat = (float)(100.0d * twist.x);
shapeBlock.PathTwistBegin = (sbyte)tempFloat;
tempFloat = (float)(100.0d * twist.y);
shapeBlock.PathTwist = (sbyte)tempFloat;
shapeBlock.ObjectLocalID = part.LocalId; shapeBlock.ObjectLocalID = part.LocalId;
@ -7138,6 +7151,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return; return;
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock; ObjectShapePacket.ObjectDataBlock shapeBlock;
shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@ -7158,8 +7172,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
taper_b.y = 2f; taper_b.y = 2f;
} }
shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x)); tempFloat = (float)(100.0d * (2.0d - taper_b.x));
shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y)); shapeBlock.PathScaleX = (byte)tempFloat;
tempFloat = (float)(100.0d * (2.0d - taper_b.y));
shapeBlock.PathScaleY = (byte)tempFloat;
if (topshear.x < -0.5f) if (topshear.x < -0.5f)
{ {
topshear.x = -0.5f; topshear.x = -0.5f;
@ -7176,8 +7192,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
topshear.y = 0.5f; topshear.y = 0.5f;
} }
shapeBlock.PathShearX = (byte)(100 * topshear.x); tempFloat = (float)(100.0d * topshear.x);
shapeBlock.PathShearY = (byte)(100 * topshear.y); shapeBlock.PathShearX = (byte)tempFloat;
tempFloat = (float)(100.0d * topshear.y);
shapeBlock.PathShearY = (byte)tempFloat;
part.Shape.SculptEntry = false; part.Shape.SculptEntry = false;
part.UpdateShape(shapeBlock); part.UpdateShape(shapeBlock);
@ -7233,6 +7251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted) if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return; return;
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock; ObjectShapePacket.ObjectDataBlock shapeBlock;
shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve); shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@ -7257,8 +7276,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
holesize.y = 0.5f; holesize.y = 0.5f;
} }
shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x)); tempFloat = (float)(100.0d * (2.0d - holesize.x));
shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y)); shapeBlock.PathScaleX = (byte)tempFloat;
tempFloat = (float)(100.0d * (2.0d - holesize.y));
shapeBlock.PathScaleY = (byte)tempFloat;
if (topshear.x < -0.5f) if (topshear.x < -0.5f)
{ {
topshear.x = -0.5f; topshear.x = -0.5f;
@ -7275,8 +7296,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
topshear.y = 0.5f; topshear.y = 0.5f;
} }
shapeBlock.PathShearX = (byte)(100 * topshear.x); tempFloat = (float)(100.0d * topshear.x);
shapeBlock.PathShearY = (byte)(100 * topshear.y); shapeBlock.PathShearX = (byte)tempFloat;
tempFloat = (float)(100.0d * topshear.y);
shapeBlock.PathShearY = (byte)tempFloat;
if (profilecut.x < 0f) if (profilecut.x < 0f)
{ {
profilecut.x = 0f; profilecut.x = 0f;
@ -7320,8 +7343,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
taper_a.y = 1f; taper_a.y = 1f;
} }
shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x); tempFloat = (float)(100.0d * taper_a.x);
shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y); shapeBlock.PathTaperX = (sbyte)tempFloat;
tempFloat = (float)(100.0d * taper_a.y);
shapeBlock.PathTaperY = (sbyte)tempFloat;
if (revolutions < 1f) if (revolutions < 1f)
{ {
revolutions = 1f; revolutions = 1f;
@ -7330,7 +7355,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
revolutions = 4f; revolutions = 4f;
} }
shapeBlock.PathRevolutions = (byte)(66.666667 * (revolutions - 1.0)); tempFloat = 66.66667f * (revolutions - 1.0f);
shapeBlock.PathRevolutions = (byte)tempFloat;
// limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1 // limits on radiusoffset depend on revolutions and hole size (how?) seems like the maximum range is 0 to 1
if (radiusoffset < 0f) if (radiusoffset < 0f)
{ {
@ -7340,7 +7366,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
radiusoffset = 1f; radiusoffset = 1f;
} }
shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset); tempFloat = 100.0f * radiusoffset;
shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
if (skew < -0.95f) if (skew < -0.95f)
{ {
skew = -0.95f; skew = -0.95f;
@ -7349,7 +7376,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{ {
skew = 0.95f; skew = 0.95f;
} }
shapeBlock.PathSkew = (sbyte)(100 * skew); tempFloat = 100.0f * skew;
shapeBlock.PathSkew = (sbyte)tempFloat;
part.Shape.SculptEntry = false; part.Shape.SculptEntry = false;
part.UpdateShape(shapeBlock); part.UpdateShape(shapeBlock);
@ -8268,10 +8296,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0)); res.Add(new LSL_Vector(Shape.PathTaperX / 100.0, Shape.PathTaperY / 100.0, 0));
// float revolutions // float revolutions
res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
// byte is being used to represent the entire // Slightly inaccurate, because an unsigned byte is being used to represent
// range of floating-point values from 1.0 // the entire range of floating-point values from 1.0 through 4.0 (which is how
// through 4.0 (which is how SL does it). // SL does it).
//
// Using these formulas to store and retrieve PathRevolutions, it is not
// possible to use all values between 1.00 and 4.00. For instance, you can't
// represent 1.10. You can represent 1.09 and 1.11, but not 1.10. So, if you
// use llSetPrimitiveParams to set revolutions to 1.10 and then retreive them
// with llGetPrimitiveParams, you'll retrieve 1.09. You can also see a similar
// behavior in the viewer as you cannot set 1.10. The viewer jumps to 1.11.
// In SL, llSetPrimitveParams and llGetPrimitiveParams can set and get a value
// such as 1.10. So, SL must store and retreive the actual user input rather
// than only storing the encoded value.
// float radiusoffset // float radiusoffset
res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0)); res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));

View File

@ -712,9 +712,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
== World.LandChannel.GetLandObject( == World.LandChannel.GetLandObject(
presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
{ {
World.RequestTeleportLocation(presence.ControllingClient, regionName, // We will launch the teleport on a new thread so that when the script threads are terminated
new Vector3((float)position.x, (float)position.y, (float)position.z), // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); Util.FireAndForget(
o => World.RequestTeleportLocation(presence.ControllingClient, regionName,
new Vector3((float)position.x, (float)position.y, (float)position.z),
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
ScriptSleep(5000); ScriptSleep(5000);
} }
@ -750,9 +753,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
== World.LandChannel.GetLandObject( == World.LandChannel.GetLandObject(
presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID) presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
{ {
World.RequestTeleportLocation(presence.ControllingClient, regionHandle, // We will launch the teleport on a new thread so that when the script threads are terminated
new Vector3((float)position.x, (float)position.y, (float)position.z), // before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation); Util.FireAndForget(
o => World.RequestTeleportLocation(presence.ControllingClient, regionHandle,
new Vector3((float)position.x, (float)position.y, (float)position.z),
new Vector3((float)lookat.x, (float)lookat.y, (float)lookat.z), (uint)TPFlags.ViaLocation));
ScriptSleep(5000); ScriptSleep(5000);
} }
} }

View File

@ -49,7 +49,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6; private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d; private const double VECTOR_COMPONENT_ACCURACY = 0.0000005d;
private const double FLOAT_ACCURACY = 0.00005d; private const float FLOAT_ACCURACY = 0.00005f;
private LSL_Api m_lslApi; private LSL_Api m_lslApi;
[SetUp] [SetUp]
@ -194,10 +194,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 0.075d, 0.0d), // Prim cut
0.80d, // Prim hollow 0.80f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple new LSL_Types.Vector3(0.32d, 0.76d, 0.0d), // Prim dimple
0.80d); // Prim hollow check 0.80f); // Prim hollow check
// Test a prism. // Test a prism.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -206,11 +206,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.90d, // Prim hollow 0.90f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.90d); // Prim hollow check 0.90f); // Prim hollow check
// Test a box. // Test a box.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -219,11 +219,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_BOX, // Prim type ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95d, // Prim hollow 0.95f, // Prim hollow
new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist new LSL_Types.Vector3(1.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper new LSL_Types.Vector3(1.0d, 1.0d, 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.95d); // Prim hollow check 0.95f); // Prim hollow check
// Test a tube. // Test a tube.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -232,16 +232,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.00d, // Prim hollow 0.00f, // Prim hollow
new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist new LSL_Types.Vector3(1.0d, -1.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(1.0d, 0.5d, 0.0d), // Prim hole size new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear // Expression for y selected to test precision problems during byte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(0.0d, 0.35d + 0.1d, 0.0d), // Prim shear
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim profile cut
new LSL_Types.Vector3(-1.0d, 1.0d, 0.0d), // Prim taper // Expression for y selected to test precision problems during sbyte
1.0d, // Prim revolutions // cast in SetPrimitiveShapeParams.
1.0d, // Prim radius new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
0.0d, // Prim skew 1.11f, // Prim revolutions
0.00d); // Prim hollow check 0.88f, // Prim radius
0.95f, // Prim skew
0.00f); // Prim hollow check
// Test a prism. // Test a prism.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -250,11 +254,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95d, // Prim hollow 0.95f, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist // Expression for x selected to test precision problems during sbyte
new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper // cast in SetPrimitiveShapeBlockParams.
new LSL_Types.Vector3(0.7d + 0.2d, 0.0d, 0.0d), // Prim twist
// Expression for y selected to test precision problems during sbyte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(2.0d, (1.3d + 0.1d), 0.0d), // Prim taper
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
0.70d); // Prim hollow check 0.70f); // Prim hollow check
// Test a sculpted prim. // Test a sculpted prim.
CheckllSetPrimitiveParams( CheckllSetPrimitiveParams(
@ -268,8 +276,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
// Set prim params for a box, cylinder or prism and check results. // Set prim params for a box, cylinder or prism and check results.
public void CheckllSetPrimitiveParams(string primTest, public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
double primHollowCheck) float primHollowCheck)
{ {
// Set the prim params. // Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@ -297,7 +305,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
// Set prim params for a sphere and check results. // Set prim params for a sphere and check results.
public void CheckllSetPrimitiveParams(string primTest, public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, double primHollowCheck) float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primDimple, float primHollowCheck)
{ {
// Set the prim params. // Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@ -324,9 +332,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
// Set prim params for a torus, tube or ring and check results. // Set prim params for a torus, tube or ring and check results.
public void CheckllSetPrimitiveParams(string primTest, public void CheckllSetPrimitiveParams(string primTest,
LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut, LSL_Types.Vector3 primSize, int primType, int primHoleType, LSL_Types.Vector3 primCut,
double primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize, float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primHoleSize,
LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear, LSL_Types.Vector3 primProfCut, LSL_Types.Vector3 primTaper,
double primRev, double primRadius, double primSkew, double primHollowCheck) float primRev, float primRadius, float primSkew, float primHollowCheck)
{ {
// Set the prim params. // Set the prim params.
m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize, m_lslApi.llSetPrimitiveParams(new LSL_Types.list(ScriptBaseClass.PRIM_SIZE, primSize,
@ -353,7 +361,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut"); CheckllSetPrimitiveParamsVector(primProfCut, m_lslApi.llList2Vector(primParams, 8), primTest + " prim profile cut");
CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper"); CheckllSetPrimitiveParamsVector(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY, Assert.AreEqual(primRev, m_lslApi.llList2Float(primParams, 10), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim revolution fail"); "TestllSetPrimitiveParams " + primTest + " prim revolutions fail");
Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY, Assert.AreEqual(primRadius, m_lslApi.llList2Float(primParams, 11), FLOAT_ACCURACY,
"TestllSetPrimitiveParams " + primTest + " prim radius fail"); "TestllSetPrimitiveParams " + primTest + " prim radius fail");
Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY, Assert.AreEqual(primSkew, m_lslApi.llList2Float(primParams, 12), FLOAT_ACCURACY,

View File

@ -409,7 +409,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine
m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup), m_ThreadPool.QueueWorkItem(new WorkItemCallback(this.DoBackup),
new Object[] { m_SaveTime }); new Object[] { m_SaveTime });
} }
}
public void StartProcessing()
{
m_ThreadPool.Start(); m_ThreadPool.Start();
} }
@ -659,7 +662,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
SceneObjectPart part = m_Scene.GetSceneObjectPart(localID); SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
if (part == null) if (part == null)
{ {
m_log.Error("[Script] SceneObjectPart unavailable. Script NOT started."); m_log.ErrorFormat("[Script]: SceneObjectPart with localID {0} unavailable. Script NOT started.", localID);
m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n"; m_ScriptErrorMessage += "SceneObjectPart unavailable. Script NOT started.\n";
m_ScriptFailCount++; m_ScriptFailCount++;
return false; return false;

View File

@ -439,14 +439,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
} }
catch catch
{ {
m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for StatusNotification", m_ServerURL);
// reason = "Exception: " + e.Message; // reason = "Exception: " + e.Message;
return friendsOnline; return friendsOnline;
} }
if (response.IsFault) if (response.IsFault)
{ {
m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for StatusNotification returned an error: {1}", m_ServerURL, response.FaultString);
// reason = "XMLRPC Fault"; // reason = "XMLRPC Fault";
return friendsOnline; return friendsOnline;
} }
@ -510,14 +510,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
} }
catch catch
{ {
m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetOnlineFriends", m_ServerURL);
// reason = "Exception: " + e.Message; // reason = "Exception: " + e.Message;
return online; return online;
} }
if (response.IsFault) if (response.IsFault)
{ {
m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetOnlineFriends returned an error: {1}", m_ServerURL, response.FaultString);
// reason = "XMLRPC Fault"; // reason = "XMLRPC Fault";
return online; return online;
} }
@ -575,14 +575,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
} }
catch catch
{ {
m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetServerURLs", m_ServerURL);
// reason = "Exception: " + e.Message; // reason = "Exception: " + e.Message;
return serverURLs; return serverURLs;
} }
if (response.IsFault) if (response.IsFault)
{ {
m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetServerURLs returned an error: {1}", m_ServerURL, response.FaultString);
// reason = "XMLRPC Fault"; // reason = "XMLRPC Fault";
return serverURLs; return serverURLs;
} }
@ -639,14 +639,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
} }
catch catch
{ {
m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for LocateUser", m_ServerURL);
// reason = "Exception: " + e.Message; // reason = "Exception: " + e.Message;
return url; return url;
} }
if (response.IsFault) if (response.IsFault)
{ {
m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for LocateUser returned an error: {1}", m_ServerURL, response.FaultString);
// reason = "XMLRPC Fault"; // reason = "XMLRPC Fault";
return url; return url;
} }
@ -698,14 +698,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
} }
catch catch
{ {
m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetUUI", m_ServerURL);
// reason = "Exception: " + e.Message; // reason = "Exception: " + e.Message;
return uui; return uui;
} }
if (response.IsFault) if (response.IsFault)
{ {
m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetUUI returned an error: {1}", m_ServerURL, response.FaultString);
// reason = "XMLRPC Fault"; // reason = "XMLRPC Fault";
return uui; return uui;
} }
@ -746,14 +746,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
} }
catch (Exception e) catch (Exception e)
{ {
m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0}", m_ServerURL); m_log.DebugFormat("[USER AGENT CONNECTOR]: Unable to contact remote server {0} for GetBoolResponse", m_ServerURL);
reason = "Exception: " + e.Message; reason = "Exception: " + e.Message;
return false; return false;
} }
if (response.IsFault) if (response.IsFault)
{ {
m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} returned an error: {1}", m_ServerURL, response.FaultString); m_log.ErrorFormat("[USER AGENT CONNECTOR]: remote call to {0} for GetBoolResponse returned an error: {1}", m_ServerURL, response.FaultString);
reason = "XMLRPC Fault"; reason = "XMLRPC Fault";
return false; return false;
} }

View File

@ -262,7 +262,6 @@ namespace OpenSim.Services.Interfaces
UUID.Parse(Data["SkirtItem"]), UUID.Parse(Data["SkirtItem"]),
UUID.Parse(Data["SkirtAsset"])); UUID.Parse(Data["SkirtAsset"]));
if (Data.ContainsKey("VisualParams")) if (Data.ContainsKey("VisualParams"))
{ {
string[] vps = Data["VisualParams"].Split(new char[] {','}); string[] vps = Data["VisualParams"].Split(new char[] {','});
@ -291,7 +290,6 @@ namespace OpenSim.Services.Interfaces
} }
} }
// Attachments // Attachments
Dictionary<string, string> attchs = new Dictionary<string, string>(); Dictionary<string, string> attchs = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> _kvp in Data) foreach (KeyValuePair<string, string> _kvp in Data)
@ -308,7 +306,7 @@ namespace OpenSim.Services.Interfaces
UUID uuid = UUID.Zero; UUID uuid = UUID.Zero;
UUID.TryParse(_kvp.Value, out uuid); UUID.TryParse(_kvp.Value, out uuid);
appearance.SetAttachment(point,uuid,UUID.Zero); appearance.SetAttachment(point, uuid, UUID.Zero);
} }
if (appearance.Wearables[AvatarWearable.BODY].Count == 0) if (appearance.Wearables[AvatarWearable.BODY].Count == 0)

View File

@ -88,8 +88,7 @@ namespace OpenSim.Tests.Common
if (type == InventoryType.Notecard) if (type == InventoryType.Notecard)
asset = AssetHelpers.CreateAsset(scene, userId); asset = AssetHelpers.CreateAsset(scene, userId);
else if (type == InventoryType.Object) else if (type == InventoryType.Object)
asset asset = AssetHelpers.CreateAsset(assetId, SceneHelpers.CreateSceneObject(1, userId));
= AssetHelpers.CreateAsset(assetId, SceneHelpers.CreateSceneObject(1, userId));
else else
throw new Exception(string.Format("Inventory type {0} not supported", type)); throw new Exception(string.Format("Inventory type {0} not supported", type));

View File

@ -163,6 +163,10 @@ namespace OpenSim.Data.Null
{ {
RegionSettings rs = null; RegionSettings rs = null;
m_regionSettings.TryGetValue(regionUUID, out rs); m_regionSettings.TryGetValue(regionUUID, out rs);
if (rs == null)
rs = new RegionSettings();
return rs; return rs;
} }

View File

@ -740,7 +740,7 @@
;; "config-include/StandaloneCommon.ini.example" to "config-include/StandaloneCommon.ini" before ;; "config-include/StandaloneCommon.ini.example" to "config-include/StandaloneCommon.ini" before
;; editing it to set the database and backend services that OpenSim will use. ;; editing it to set the database and backend services that OpenSim will use.
;; ;;
; Include-Architecture = "config-include/Standalone.ini" Include-Architecture = "config-include/Standalone.ini"
; Include-Architecture = "config-include/StandaloneHypergrid.ini" ; Include-Architecture = "config-include/StandaloneHypergrid.ini"
; Include-Architecture = "config-include/Grid.ini" ; Include-Architecture = "config-include/Grid.ini"
; Include-Architecture = "config-include/GridHypergrid.ini" ; Include-Architecture = "config-include/GridHypergrid.ini"