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
* Omar Vera Ustariz (IBM)
* openlifegrid.com
* Oren Hurvitz (Kitely)
* otakup0pe
* ralphos
* RemedyTomm

View File

@ -812,6 +812,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController
// ok, client wants us to use an explicit UUID
// regardless of what the avatar name provided
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"))
{
@ -823,6 +831,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController
IUserAccountService accountService = currentOrFirst.UserAccountService;
UserAccount user = accountService.GetUserAccount(currentOrFirst.RegionInfo.ScopeID,
ownerFirst, ownerLast);
// Check that the specified user exists
if (user == null)
throw new Exception("Specified user was not found.");
userID = user.PrincipalID;
}
else

View File

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

View File

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

View File

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

View File

@ -405,31 +405,40 @@ namespace OpenSim.Framework
/// </remarks>
public List<AvatarAttachment> GetAttachments()
{
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 (AvatarAttachment attach in kvp.Value)
alist.Add(new AvatarAttachment(attach));
}
return alist;
}
}
return alist;
} }
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)
{
if (!m_attachments.ContainsKey(attach.AttachPoint))
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
m_attachments[attach.AttachPoint].Add(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)
{
m_attachments[attach.AttachPoint] = new List<AvatarAttachment>();
@ -438,7 +447,7 @@ namespace OpenSim.Framework
}
/// <summary>
/// Add an attachment
/// Set an attachment
/// </summary>
/// <remarks>
/// If the attachpoint has the
@ -454,13 +463,13 @@ namespace OpenSim.Framework
/// </returns>
public bool SetAttachment(int attachpoint, UUID item, UUID asset)
{
if (attachpoint == 0)
return false;
// m_log.DebugFormat(
// "[AVATAR APPEARANCE]: Setting attachment at {0} with item ID {1}, asset ID {2}",
// attachpoint, item, asset);
if (attachpoint == 0)
return false;
if (item == UUID.Zero)
{
lock (m_attachments)
@ -470,12 +479,21 @@ namespace OpenSim.Framework
m_attachments.Remove(attachpoint);
return true;
}
return false;
}
return false;
}
// check if the item is already attached at this point
if (GetAttachpoint(item) == (attachpoint & 0x7F))
// When a user logs in, the attachment item ids are pulled from persistence in the Avatars table. However,
// 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);
return false;
@ -492,9 +510,30 @@ namespace OpenSim.Framework
{
ReplaceAttachment(new AvatarAttachment(attachpoint,item, asset));
}
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)
{
lock (m_attachments)
@ -505,9 +544,8 @@ namespace OpenSim.Framework
if (index >= 0)
return kvp.Key;
}
return 0;
}
return 0;
}
public bool DetachAttachment(UUID itemID)
@ -521,23 +559,23 @@ namespace OpenSim.Framework
{
// Remove it from the list of attachments at that attach point
m_attachments[kvp.Key].RemoveAt(index);
// And remove the list if there are no more attachments here
if (m_attachments[kvp.Key].Count == 0)
m_attachments.Remove(kvp.Key);
return true;
}
}
}
return false;
}
public void ClearAttachments()
{
lock (m_attachments)
{
m_attachments.Clear();
}
}
#region Packing Functions

View File

@ -441,7 +441,6 @@ namespace OpenSim.Framework
args["controllers"] = controls;
}
if ((CallbackURI != null) && (!CallbackURI.Equals("")))
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
// append rather than replace to ensure multiple attachments
// per point continues to work
// m_log.DebugFormat("[CHILDAGENTDATAUPDATE]: Appending attachments for {0}", AgentID);
Appearance.AppendAttachment(new AvatarAttachment((OSDMap)o));
}
}

View File

@ -1384,11 +1384,30 @@ namespace OpenSim.Framework
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)
{
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)
{
if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }
@ -1407,11 +1426,30 @@ namespace OpenSim.Framework
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)
{
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)
{
if (String.IsNullOrEmpty(str)) { return Utils.EmptyBytes; }

View File

@ -269,13 +269,15 @@ namespace OpenSim
m_console.Commands.AddCommand("region", false, "save oar",
//"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.",
// "-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
+ " 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." + Environment.NewLine
+ "--noassets stops assets being saved to the OAR.",
+ "--noassets stops assets being saved to the OAR." + Environment.NewLine
+ "--perm stops objects with insufficient permissions from being saved to the OAR." + Environment.NewLine
+ " <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);
m_console.Commands.AddCommand("region", false, "edit scale",

View File

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

View File

@ -144,20 +144,26 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
public void SaveChangedAttachments(IScenePresence sp)
{
// m_log.DebugFormat("[ATTACHMENTS MODULE]: Saving changed attachments for {0}", sp.Name);
foreach (SceneObjectGroup grp in sp.GetAttachments())
{
if (grp.HasGroupChanged) // Resizer scripts?
{
// if (grp.HasGroupChanged) // Resizer scripts?
// {
grp.IsAttachment = false;
grp.AbsolutePosition = grp.RootPart.AttachedPos;
UpdateKnownItem(sp.ControllingClient, grp, grp.GetFromItemID(), grp.OwnerID);
UpdateKnownItem(sp.ControllingClient, grp);
grp.IsAttachment = true;
}
// }
}
}
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())
{
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);
// Save avatar attachment information
m_log.Info(
m_log.Debug(
"[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId
+ ", AttachmentPoint: " + AttachmentPt);
@ -248,75 +254,83 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
private bool AttachObject(IScenePresence sp, SceneObjectGroup group, uint attachmentPt, bool silent)
{
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
// group.Name, group.LocalId, sp.Name, AttachmentPt, silent);
if (sp.GetAttachments(attachmentPt).Contains(group))
lock (sp.AttachmentsSyncLock)
{
// m_log.WarnFormat(
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
// group.Name, group.LocalId, sp.Name, AttachmentPt);
return false;
}
Vector3 attachPos = group.AbsolutePosition;
// 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();
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: Attaching object {0} {1} to {2} point {3} from ground (silent = {4})",
// group.Name, group.LocalId, sp.Name, attachmentPt, silent);
if (itemID != UUID.Zero)
DetachSingleAttachmentToInv(itemID, sp);
if (sp.GetAttachments(attachmentPt).Contains(group))
{
// m_log.WarnFormat(
// "[ATTACHMENTS MODULE]: Ignoring request to attach {0} {1} to {2} on {3} since it's already attached",
// group.Name, group.LocalId, sp.Name, AttachmentPt);
itemID = group.GetFromItemID();
if (itemID == UUID.Zero)
itemID = AddSceneObjectAsAttachment(sp.ControllingClient, group).ID;
return false;
}
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;
}
@ -325,20 +339,28 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
RezMultipleAttachmentsFromInvPacket.HeaderDataBlock header,
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(
IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
{
return RezSingleAttachmentFromInventory(remoteClient, itemID, AttachmentPt, true);
}
public ISceneEntity RezSingleAttachmentFromInventory(
IClientAPI remoteClient, UUID itemID, uint AttachmentPt, bool updateInventoryStatus)
public ISceneEntity RezSingleAttachmentFromInventory(IClientAPI remoteClient, UUID itemID, uint AttachmentPt)
{
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)
{
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
// be removed when that functionality is implemented in opensim
AttachmentPt &= 0x7f;
SceneObjectGroup att = RezSingleAttachmentFromInventoryInternal(sp, itemID, UUID.Zero, AttachmentPt, doc);
if (updateInventoryStatus)
// 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.
// 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)
DetachSingleAttachmentToInv(itemID, sp.ControllingClient);
else
ShowAttachInUserInventory(att, sp, itemID, AttachmentPt);
if (so.GetFromItemID() == itemID)
{
alreadyOn = true;
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;
}
@ -371,50 +431,67 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
IInventoryAccessModule invAccess = m_scene.RequestModuleInterface<IInventoryAccessModule>();
if (invAccess != null)
{
SceneObjectGroup objatt;
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)
lock (sp.AttachmentsSyncLock)
{
// Loading the inventory from XML will have set this, but
// there is no way the object could have changed yet,
// since scripts aren't running yet. So, clear it here.
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;
}
SceneObjectGroup objatt;
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 (tainted)
objatt.HasGroupChanged = true;
if (objatt != null)
{
// 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)
{
@ -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
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;
}
/// <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>
/// 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)
{
// m_log.DebugFormat(
// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
// att.Name, remoteClient.Name, AttachmentPt, itemID);
// "[USER INVENTORY]: Updating attachment {0} for {1} at {2} using item ID {3}",
// att.Name, sp.Name, AttachmentPt, itemID);
if (UUID.Zero == itemID)
{
@ -518,6 +558,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
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);
if (group != null)
{
@ -530,14 +573,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ScenePresence presence;
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{
// Save avatar attachment information
m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
lock (presence.AttachmentsSyncLock)
{
// Save avatar attachment information
m_log.Debug("[ATTACHMENTS MODULE]: Detaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID);
bool changed = presence.Appearance.DetachAttachment(itemID);
if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
DetachSingleAttachmentToInv(itemID, presence);
bool changed = presence.Appearance.DetachAttachment(itemID);
if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
DetachSingleAttachmentToInv(itemID, presence);
}
}
}
@ -545,7 +591,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
{
// m_log.DebugFormat(
// "[ATTACHMENTS MODULE]: DetachSingleAttachmentToGround() for {0}, object {1}",
// remoteClient.Name, sceneObjectID);
// remoteClient.Name, soLocalId);
SceneObjectGroup so = m_scene.GetGroupByPrim(soLocalId);
@ -564,24 +610,27 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
ScenePresence presence;
if (m_scene.TryGetScenePresence(remoteClient.AgentId, out presence))
{
if (!m_scene.Permissions.CanRezObject(
so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
return;
lock (presence.AttachmentsSyncLock)
{
if (!m_scene.Permissions.CanRezObject(
so.PrimCount, remoteClient.AgentId, presence.AbsolutePosition))
return;
bool changed = presence.Appearance.DetachAttachment(inventoryID);
if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
bool changed = presence.Appearance.DetachAttachment(inventoryID);
if (changed && m_scene.AvatarFactory != null)
m_scene.AvatarFactory.QueueAppearanceSave(remoteClient.AgentId);
presence.RemoveAttachment(so);
DetachSceneObjectToGround(so, presence);
presence.RemoveAttachment(so);
DetachSceneObjectToGround(so, presence);
List<UUID> uuids = new List<UUID>();
uuids.Add(inventoryID);
m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids);
remoteClient.SendRemoveInventoryItem(inventoryID);
List<UUID> uuids = new List<UUID>();
uuids.Add(inventoryID);
m_scene.InventoryService.DeleteItems(remoteClient.AgentId, uuids);
remoteClient.SendRemoveInventoryItem(inventoryID);
}
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
}
m_scene.EventManager.TriggerOnAttach(so.LocalId, so.UUID, UUID.Zero);
}
/// <summary>
@ -615,6 +664,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
// To LocalId or UUID, *THAT* is the question. How now Brown UUID??
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....
return;
@ -623,40 +674,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
EntityBase[] detachEntities = m_scene.GetEntities();
SceneObjectGroup group;
foreach (EntityBase entity in detachEntities)
lock (sp.AttachmentsSyncLock)
{
if (entity is SceneObjectGroup)
foreach (EntityBase entity in detachEntities)
{
group = (SceneObjectGroup)entity;
if (group.GetFromItemID() == itemID)
if (entity is SceneObjectGroup)
{
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
//SceneObjectSerializer.ToOriginalXmlFormat(group);
group.DetachToInventoryPrep();
m_log.Debug("[ATTACHMENTS MODULE]: Saving attachpoint: " + ((uint)group.GetAttachmentPoint()).ToString());
// Prepare sog for storage
group.AttachedAvatar = UUID.Zero;
// Prepare sog for storage
group.AttachedAvatar = UUID.Zero;
group.RootPart.SetParentLocalId(0);
group.IsAttachment = false;
group.AbsolutePosition = group.RootPart.AttachedPos;
group.ForEachPart(
delegate(SceneObjectPart part)
{
// If there are any scripts,
// then always trigger a new object and state persistence in UpdateKnownItem()
if (part.Inventory.ContainsScripts())
group.HasGroupChanged = true;
}
);
UpdateKnownItem(sp.ControllingClient, group);
m_scene.DeleteSceneObject(group, false);
group.RootPart.SetParentLocalId(0);
group.IsAttachment = false;
group.AbsolutePosition = group.RootPart.AttachedPos;
UpdateKnownItem(sp.ControllingClient, group, group.GetFromItemID(), group.OwnerID);
m_scene.DeleteSceneObject(group, false);
return;
return;
}
}
}
}
@ -687,28 +727,17 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
/// </remarks>
/// <param name="remoteClient"></param>
/// <param name="grp"></param>
/// <param name="itemID"></param>
/// <param name="agentID"></param>
public void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp, UUID itemID, UUID agentID)
private void UpdateKnownItem(IClientAPI remoteClient, SceneObjectGroup grp)
{
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(
"[ATTACHMENTS MODULE]: Updating asset for attachment {0}, attachpoint {1}",
grp.UUID, grp.AttachmentPoint);
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);
if (item != null)
@ -734,6 +763,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
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>
@ -751,7 +786,8 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
private void AttachToAgent(
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.DetachFromBackup();
@ -788,14 +824,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
}
/// <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>
/// <param name="remoteClient"></param>
/// <param name="grp"></param>
/// <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
(((grp.AbsolutePosition.X > (int)Constants.RegionSize)
@ -879,4 +917,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments
return item;
}
}
}
}

View File

@ -58,12 +58,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
private AttachmentsModule m_attMod;
private ScenePresence m_presence;
[SetUp]
public void Init()
[TestFixtureSetUp]
public void FixtureInit()
{
// Don't allow tests to be bamboozled by asynchronous events. Execute everything on the same thread.
Util.FireAndForgetMethod = FireAndForgetMethod.None;
}
[SetUp]
public void Init()
{
IConfigSource config = new IniConfigSource();
config.AddConfig("Modules");
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());
}
[TearDown]
[TestFixtureTearDown]
public void TearDown()
{
// 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);
// 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));
}
@ -215,6 +220,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
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]
public void TestRezAttachmentsOnAvatarEntrance()
{
@ -246,6 +283,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments.Tests
Assert.That(attSo.IsAttachment);
Assert.That(attSo.UsesPhysics, 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

View File

@ -59,7 +59,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
get { return m_MaxTransferDistance; }
set { m_MaxTransferDistance = value; }
}
protected bool m_Enabled = false;
protected Scene m_aScene;
@ -68,7 +67,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
private ExpiringCache<UUID, ExpiringCache<ulong, DateTime>> m_bannedRegions =
new ExpiringCache<UUID, ExpiringCache<ulong, DateTime>>();
#region ISharedRegionModule
public Type ReplaceableInterface
@ -210,7 +208,10 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.Teleport(position);
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
{
@ -328,10 +329,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
sp.StandUp();
if (!sp.ValidateAttachments())
{
sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
return;
}
m_log.DebugFormat(
"[ENTITY TRANSFER MODULE]: Failed validation of all attachments for teleport of {0} from {1} to {2}. Continuing.",
sp.Name, sp.Scene.RegionInfo.RegionName, finalDestination.RegionName);
// if (!sp.ValidateAttachments())
// {
// sp.ControllingClient.SendTeleportFailed("Inconsistent attachment state");
// return;
// }
string reason;
string version;
@ -955,7 +961,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
/// This Closes child agents on neighbouring regions
/// Calls an asynchronous method to do so.. so it doesn't lag the sim.
/// </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));
@ -963,8 +971,13 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
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);
SetInTransit(agent.UUID);
@ -1789,16 +1802,16 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer
List<SceneObjectGroup> m_attachments = sp.GetAttachments();
// Validate
foreach (SceneObjectGroup gobj in m_attachments)
{
if (gobj == null || gobj.IsDeleted)
return false;
}
// foreach (SceneObjectGroup gobj in m_attachments)
// {
// if (gobj == null || gobj.IsDeleted)
// return false;
// }
foreach (SceneObjectGroup gobj in m_attachments)
{
// 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.
gobj.RootPart.SetParentLocalId(0);

View File

@ -726,8 +726,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
SceneObjectGroup group = null;
string xmlData = Utils.BytesToString(rezAsset.Data);
List<SceneObjectGroup> objlist =
new List<SceneObjectGroup>();
List<SceneObjectGroup> objlist = new List<SceneObjectGroup>();
List<Vector3> veclist = new List<Vector3>();
byte bRayEndIsIntersection = (byte)(RayEndIsIntersection ? 1 : 0);
Vector3 pos;
@ -799,6 +798,13 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
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 it's rezzed in world, select it. Much easier to
@ -839,7 +845,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if (!attachment)
{
if (group.RootPart.Shape.PCode == (byte)PCode.Prim)
if (rootPart.Shape.PCode == (byte)PCode.Prim)
group.ClearPartAttachmentData();
// Fire on_rez
@ -1017,11 +1023,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess
if ((part.OwnerID != item.Owner) ||
(item.CurrentPermissions & 16) != 0)
{
part.LastOwnerID = part.OwnerID;
part.OwnerID = item.Owner;
part.Inventory.ChangeInventoryOwner(item.Owner);
part.GroupMask = 0; // DO NOT propagate here
}
part.EveryoneMask = item.EveryOnePermissions;
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",
String.Empty,
HandleShowUsers);
}
public bool IsSharedModule
@ -365,9 +363,9 @@ namespace OpenSim.Region.CoreModules.Framework.UserManagement
lock (m_UserCache)
m_UserCache[user.Id] = user;
m_log.DebugFormat(
"[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
user.Id, user.FirstName, user.LastName, user.HomeURL);
// m_log.DebugFormat(
// "[USER MANAGEMENT MODULE]: Added user {0} {1} {2} {3}",
// user.Id, user.FirstName, user.LastName, user.HomeURL);
}
//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>();
foreach (SceneObjectGroup sog in attachments)
{
targets.Add(sog.UUID);
if (!sog.IsDeleted)
targets.Add(sog.UUID);
}
// Need to check each attachment

View File

@ -64,7 +64,15 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
get
{
if (m_UserManagement == null)
{
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;
}
}
@ -140,8 +148,29 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
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)
@ -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);
@ -338,7 +367,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
}
public bool AddFolder(InventoryFolderBase folder)
public bool AddFolder(InventoryFolderBase folder)
{
if (folder == null)
return false;
@ -355,7 +384,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.AddFolder(folder);
}
public bool UpdateFolder(InventoryFolderBase folder)
public bool UpdateFolder(InventoryFolderBase folder)
{
if (folder == null)
return false;
@ -372,7 +401,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.UpdateFolder(folder);
}
public bool DeleteFolders(UUID ownerID, List<UUID> folderIDs)
public bool DeleteFolders(UUID ownerID, List<UUID> folderIDs)
{
if (folderIDs == null)
return false;
@ -391,7 +420,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.DeleteFolders(ownerID, folderIDs);
}
public bool MoveFolder(InventoryFolderBase folder)
public bool MoveFolder(InventoryFolderBase folder)
{
if (folder == null)
return false;
@ -408,7 +437,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.MoveFolder(folder);
}
public bool PurgeFolder(InventoryFolderBase folder)
public bool PurgeFolder(InventoryFolderBase folder)
{
if (folder == null)
return false;
@ -442,7 +471,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.AddItem(item);
}
public bool UpdateItem(InventoryItemBase item)
public bool UpdateItem(InventoryItemBase item)
{
if (item == null)
return false;
@ -459,7 +488,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.UpdateItem(item);
}
public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
public bool MoveItems(UUID ownerID, List<InventoryItemBase> items)
{
if (items == null)
return false;
@ -478,7 +507,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
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);
@ -497,7 +526,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.DeleteItems(ownerID, itemIDs);
}
public InventoryItemBase GetItem(InventoryItemBase item)
public InventoryItemBase GetItem(InventoryItemBase item)
{
if (item == null)
return null;
@ -513,7 +542,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.GetItem(item);
}
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
public InventoryFolderBase GetFolder(InventoryFolderBase folder)
{
if (folder == null)
return null;
@ -530,17 +559,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
return connector.GetFolder(folder);
}
public bool HasInventoryForUser(UUID userID)
public bool HasInventoryForUser(UUID userID)
{
return false;
}
public List<InventoryItemBase> GetActiveGestures(UUID userId)
public List<InventoryItemBase> GetActiveGestures(UUID userId)
{
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);
@ -572,14 +601,21 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
string connectorType = new HeloServicesConnector(url).Helo();
m_log.DebugFormat("[HG INVENTORY SERVICE]: HELO returned {0}", connectorType);
if (connectorType == "opensim-simian")
{
connector = new SimianInventoryServiceConnector(url);
}
else
connector = new RemoteXInventoryServicesConnector(url);
{
RemoteXInventoryServicesConnector rxisc = new RemoteXInventoryServicesConnector(url);
rxisc.Scene = m_Scenes[0];
connector = rxisc;
}
m_connectors.Add(url, connector);
}
}
return connector;
}
}
}
}

View File

@ -47,9 +47,12 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
LogManager.GetLogger(
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 UserManager
@ -58,7 +61,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
{
if (m_UserManager == null)
{
m_UserManager = m_Scene.RequestModuleInterface<IUserManagement>();
m_UserManager = Scene.RequestModuleInterface<IUserManagement>();
}
return m_UserManager;
}
@ -131,8 +134,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
scene.RegisterModuleInterface<IInventoryService>(this);
if (m_Scene == null)
m_Scene = scene;
if (Scene == null)
Scene = scene;
}
public void RemoveRegion(Scene scene)
@ -185,8 +188,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
Util.FireAndForget(delegate
{
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);
}
});
return invCol;

View File

@ -45,19 +45,30 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
private static readonly ILog m_log =
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 Scene m_Scene;
private XInventoryServicesConnector m_RemoteConnector;
private IUserManagement m_UserManager;
private IUserManagement UserManager
public IUserManagement UserManager
{
get
{
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;
}
}
@ -86,12 +97,11 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
Init(source);
}
protected void Init(IConfigSource source)
protected void Init(IConfigSource source)
{
m_RemoteConnector = new XInventoryServicesConnector(source);
}
#region ISharedRegionModule
public void Initialise(IConfigSource source)
@ -128,15 +138,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
scene.RegisterModuleInterface<IInventoryService>(this);
if (m_Scene == null)
m_Scene = scene;
if (Scene == null)
Scene = scene;
}
public void RemoveRegion(Scene scene)
{
if (!m_Enabled)
return;
}
public void RegionLoaded(Scene scene)
@ -181,14 +190,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory
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);
Util.FireAndForget(delegate
{
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);
}
});
return invCol;

View File

@ -284,8 +284,8 @@ namespace OpenSim.Region.CoreModules.World.Archiver
part.LastOwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
// And zap any troublesome sit target information
part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
part.SitTargetPosition = new Vector3(0, 0, 0);
// part.SitTargetOrientation = new Quaternion(0, 0, 0, 1);
// part.SitTargetPosition = new Vector3(0, 0, 0);
// Fix ownership/creator of 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();
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.
// 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)
{
SceneObjectGroup sceneObject = (SceneObjectGroup)entity;
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");
}
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
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>
/// Create the control file for the most up to date archive
/// </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("p|profile=", delegate(string v) { options["profile"] = v; });
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);

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>()));
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);
// 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");
Assert.That(
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];
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.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);
}

View File

@ -39,7 +39,7 @@ using OpenSim.Services.Interfaces;
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);
@ -150,6 +150,8 @@ namespace OpenSim.Region.CoreModules.World.Permissions
else
m_log.Debug("[PERMISSIONS]: Enabling all region service permission checks");
scene.RegisterModuleInterface<IPermissionsModule>(this);
//Register functions with Scene External Checks!
m_scene.Permissions.OnBypassPermissions += BypassPermissions;
m_scene.Permissions.OnSetBypassPermissions += SetBypassPermissions;
@ -574,46 +576,18 @@ namespace OpenSim.Region.CoreModules.World.Permissions
if (objectOwner != UUID.Zero)
objectEveryoneMask |= (uint)PrimFlags.ObjectAnyOwner;
if (m_bypassPermissions)
return objectOwnerMask;
PermissionClass permissionClass = GetPermissionClass(user, task);
// Object owners should be able to edit their own content
if (user == objectOwner)
return objectOwnerMask;
if (IsFriendWithPerms(user, objectOwner))
switch (permissionClass)
{
return objectOwnerMask;
}
// 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))
{
case PermissionClass.Owner:
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)
@ -644,6 +618,47 @@ namespace OpenSim.Region.CoreModules.World.Permissions
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>
/// General permissions checks for any operation involving an object. These supplement more specific checks
/// implemented by callers.

View File

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

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>
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>
/// The scene objects attached to this avatar.
/// </summary>

View File

@ -30,12 +30,21 @@ using OpenSim.Region.Framework.Scenes;
namespace OpenSim.Region.Framework.Interfaces
{
/// <summary>
/// Sends scheduled updates to it's associated ScenePresence.
/// </summary>
public interface ISceneViewer
{
void Reset();
// void Reset();
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 SendPrimUpdates();
int GetPendingObjectsCount();
}
}
}

View File

@ -54,5 +54,10 @@ namespace OpenSim.Region.Framework.Interfaces
bool HasScript(UUID itemID, out bool running);
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;
/// <summary>
/// Start all the scripts in the scene which should be started.
/// Creates all the scripts in the scene which should be started.
/// </summary>
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();
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)
{
IMoneyModule money = RequestModuleInterface<IMoneyModule>();

View File

@ -610,9 +610,42 @@ namespace OpenSim.Region.Framework.Scenes
#region 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)
m_regInfo.EstateSettings = estateDataService.LoadEstateSettings(m_regInfo.RegionID, false);
@ -645,7 +678,7 @@ namespace OpenSim.Region.Framework.Scenes
EventManager.OnLandObjectRemoved +=
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.
// 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.Position = Vector3.Zero;
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)
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
@ -2492,14 +2527,16 @@ namespace OpenSim.Region.Framework.Scenes
/// <returns>False</returns>
public virtual bool IncomingCreateObject(UUID userID, UUID itemID)
{
//m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID);
ScenePresence sp = GetScenePresence(userID);
if (sp != null && AttachmentsModule != null)
{
uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID);
AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt);
}
m_log.DebugFormat(" >>> IncomingCreateObject(userID, itemID) <<< {0} {1}", userID, itemID);
// Commented out since this is as yet unused and is arguably not the appropriate place to do this, as
// attachments are being rezzed elsewhere in AddNewClient()
// ScenePresence sp = GetScenePresence(userID);
// if (sp != null && AttachmentsModule != null)
// {
// uint attPt = (uint)sp.Appearance.GetAttachpoint(itemID);
// AttachmentsModule.RezSingleAttachmentFromInventory(sp.ControllingClient, itemID, attPt);
// }
return false;
}
@ -3272,8 +3309,8 @@ namespace OpenSim.Region.Framework.Scenes
if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
AttachmentsModule.SaveChangedAttachments(avatar);
if (avatar != null && (!avatar.IsChildAgent))
avatar.SaveChangedAttachments();
if (AttachmentsModule != null && !avatar.IsChildAgent && avatar.PresenceType != PresenceType.Npc)
AttachmentsModule.SaveChangedAttachments(avatar);
ForEachClient(
delegate(IClientAPI client)

View File

@ -83,7 +83,6 @@ namespace OpenSim.Region.Framework.Scenes
protected internal EntityManager Entities = new EntityManager();
protected RegionInfo m_regInfo;
protected Scene m_parentScene;
protected Dictionary<UUID, SceneObjectGroup> m_updateList = new Dictionary<UUID, SceneObjectGroup>();
protected int m_numRootAgents = 0;
@ -117,10 +116,9 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
protected internal SceneGraph(Scene parent, RegionInfo regInfo)
protected internal SceneGraph(Scene parent)
{
m_parentScene = parent;
m_regInfo = regInfo;
}
public PhysicsScene PhysicsScene
@ -131,7 +129,6 @@ namespace OpenSim.Region.Framework.Scenes
// If we're not doing the initial set
// Then we've got to remove the previous
// event handler
if (_PhyScene != null)
_PhyScene.OnPhysicsCrash -= physicsBasedCrash;
@ -413,12 +410,12 @@ namespace OpenSim.Region.Framework.Scenes
// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
// 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
if (m_parentScene.m_clampPrimSize)
{
foreach (SceneObjectPart part in children)
foreach (SceneObjectPart part in parts)
{
Vector3 scale = part.Shape.Scale;
@ -432,7 +429,7 @@ namespace OpenSim.Region.Framework.Scenes
part.Shape.Scale = scale;
}
}
m_numPrim += children.Length;
m_numPrim += parts.Length;
sceneObject.AttachToScene(m_parentScene);
@ -452,15 +449,17 @@ namespace OpenSim.Region.Framework.Scenes
lock (SceneObjectGroupsByFullPartID)
{
SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject;
foreach (SceneObjectPart part in children)
foreach (SceneObjectPart part in parts)
SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
}
lock (SceneObjectGroupsByLocalPartID)
{
SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject;
foreach (SceneObjectPart part in children)
// m_log.DebugFormat(
// "[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;
}
@ -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>
public bool DeleteSceneObject(UUID uuid, bool resultOfObjectLinked)
{
// m_log.DebugFormat(
// "[SCENE GRAPH]: Deleting scene object with uuid {0}, resultOfObjectLinked = {1}",
// uuid, resultOfObjectLinked);
EntityBase entity;
if (!Entities.TryGetValue(uuid, out entity) || (!(entity is SceneObjectGroup)))
return false;
@ -501,7 +504,6 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart[] parts = grp.Parts;
for (int i = 0; i < parts.Length; i++)
SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID);
}
lock (SceneObjectGroupsByLocalPartID)
@ -509,7 +511,6 @@ namespace OpenSim.Region.Framework.Scenes
SceneObjectPart[] parts = grp.Parts;
for (int i = 0; i < parts.Length; i++)
SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId);
}
return Entities.Remove(uuid);
@ -654,7 +655,7 @@ namespace OpenSim.Region.Framework.Scenes
ScenePresence newAvatar = null;
// 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);
@ -721,7 +722,7 @@ namespace OpenSim.Region.Framework.Scenes
if (!Entities.Remove(agentID))
{
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);
}
@ -745,7 +746,7 @@ namespace OpenSim.Region.Framework.Scenes
}
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
@ -956,7 +957,8 @@ namespace OpenSim.Region.Framework.Scenes
if (Entities.TryGetValue(localID, out entity))
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;
lock (SceneObjectGroupsByLocalPartID)
SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog);
@ -964,8 +966,24 @@ namespace OpenSim.Region.Framework.Scenes
if (sog != null)
{
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;
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();

View File

@ -388,5 +388,18 @@ namespace OpenSim.Region.Framework.Scenes
for (int i = 0; i < parts.Length; i++)
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.BasePermissions = perms;
}
m_inventorySerial++;
HasInventoryChanged = true;
}
/// <summary>
/// Returns true if this part inventory contains any scripts. False otherwise.
/// </summary>
/// <returns></returns>
public bool ContainsScripts()
{
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>();
public Object AttachmentsSyncLock { get; private set; }
private Dictionary<UUID, ScriptControllers> scriptedcontrols = new Dictionary<UUID, ScriptControllers>();
private ScriptControlled IgnoredControls = ScriptControlled.CONTROL_ZERO;
private ScriptControlled LastCommands = ScriptControlled.CONTROL_ZERO;
@ -199,7 +201,6 @@ namespace OpenSim.Region.Framework.Scenes
private float m_health = 100f;
protected RegionInfo m_regionInfo;
protected ulong crossingFromRegion;
private readonly Vector3[] Dir_Vectors = new Vector3[11];
@ -770,23 +771,24 @@ namespace OpenSim.Region.Framework.Scenes
#endregion
#region Constructor(s)
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_sceneViewer = new SceneViewer(this);
m_animator = new ScenePresenceAnimator(this);
PresenceType = type;
m_DrawDistance = world.DefaultDrawDistance;
m_rootRegionHandle = reginfo.RegionHandle;
m_rootRegionHandle = world.RegionInfo.RegionHandle;
m_controllingClient = client;
m_firstname = m_controllingClient.FirstName;
m_lastname = m_controllingClient.LastName;
m_name = String.Format("{0} {1}", m_firstname, m_lastname);
m_scene = world;
m_uuid = client.AgentId;
m_regionInfo = reginfo;
m_localId = m_scene.AllocateLocalId();
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_controllingClient.MoveAgentIntoRegion(m_regionInfo, AbsolutePosition, look);
m_controllingClient.MoveAgentIntoRegion(m_scene.RegionInfo, AbsolutePosition, look);
SendInitialData();
// Create child agents in neighbouring regions
@ -3226,8 +3228,8 @@ namespace OpenSim.Region.Framework.Scenes
/// </returns>
protected int HaveNeighbor(Cardinals car, ref int[] fix)
{
uint neighbourx = m_regionInfo.RegionLocX;
uint neighboury = m_regionInfo.RegionLocY;
uint neighbourx = m_scene.RegionInfo.RegionLocX;
uint neighboury = m_scene.RegionInfo.RegionLocY;
int dir = (int)car;
@ -3247,8 +3249,8 @@ namespace OpenSim.Region.Framework.Scenes
if (neighbourRegion == null)
{
fix[0] = (int)(m_regionInfo.RegionLocX - neighbourx);
fix[1] = (int)(m_regionInfo.RegionLocY - neighboury);
fix[0] = (int)(m_scene.RegionInfo.RegionLocX - neighbourx);
fix[1] = (int)(m_scene.RegionInfo.RegionLocY - neighboury);
return dir * (-1);
}
else
@ -3494,26 +3496,30 @@ namespace OpenSim.Region.Framework.Scenes
catch { }
// Attachment objects
if (m_attachments != null && m_attachments.Count > 0)
lock (m_attachments)
{
cAgent.AttachmentObjects = new List<ISceneObject>();
cAgent.AttachmentObjectStates = new List<string>();
// IScriptModule se = m_scene.RequestModuleInterface<IScriptModule>();
m_InTransitScriptStates.Clear();
foreach (SceneObjectGroup sog in m_attachments)
if (m_attachments.Count > 0)
{
// We need to make a copy and pass that copy
// because of transfers withn the same sim
ISceneObject clone = sog.CloneForNewScene();
// Attachment module assumes that GroupPosition holds the offsets...!
((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);
cAgent.AttachmentObjects = new List<ISceneObject>();
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
// because of transfers withn the same sim
ISceneObject clone = sog.CloneForNewScene();
// Attachment module assumes that GroupPosition holds the offsets...!
((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()
{
m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false);
if (!IsChildAgent)
m_scene.AttachmentsModule.DeleteAttachmentsFromScene(this, false);
lock (m_knownChildRegions)
{
@ -4035,8 +4042,13 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
m_attachments.Clear();
}
/// <summary>
/// This is currently just being done for information.
/// </summary>
public bool ValidateAttachments()
{
bool validated = true;
lock (m_attachments)
{
// Validate
@ -4045,21 +4057,22 @@ if (m_animator.m_jumping) force.Z = m_animator.m_jumpVelocity; // add for ju
if (gobj == null)
{
m_log.WarnFormat(
"[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null", Name);
return false;
}
"[SCENE PRESENCE]: Failed to validate an attachment for {0} since it was null. Continuing", Name);
if (gobj.IsDeleted)
validated = false;
}
else if (gobj.IsDeleted)
{
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);
return false;
validated = false;
}
}
}
return true;
return validated;
}
/// <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)
{
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.eventControls = (ScriptControlled)controls;
}
if (pass_on == 1 && accept == 1)
{
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;
}
}
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));
}
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)
{
// Never constrain lures

View File

@ -38,27 +38,42 @@ namespace OpenSim.Region.Framework.Scenes
{
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;
/// <summary>
/// The queue of parts for which we need to send out updates.
/// </summary>
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;
/// <summary>
/// The last update assocated with a given part update.
/// </summary>
protected Dictionary<UUID, ScenePartUpdate> m_updateTimes = new Dictionary<UUID, ScenePartUpdate>();
public SceneViewer()
{
}
public SceneViewer(ScenePresence 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)
{
if (!IsEnabled)
return;
lock (m_partsUpdateQueue)
{
m_partsUpdateQueue.Enqueue(part);
@ -87,6 +102,11 @@ namespace OpenSim.Region.Framework.Scenes
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)
{
SceneObjectGroup g = m_pendingObjects.Dequeue();
@ -119,7 +139,6 @@ namespace OpenSim.Region.Framework.Scenes
// We deal with the possibility that two updates occur at
// the same unix time at the update point itself.
if ((update.LastFullUpdateTime < part.TimeStampFull) || part.ParentGroup.IsAttachment)
{
// m_log.DebugFormat(
@ -135,9 +154,7 @@ namespace OpenSim.Region.Framework.Scenes
// this update. If this happened, then subsequent
// updates which occurred on the same tick or the
// next tick of the last update would be ignored.
update.LastFullUpdateTime = part.TimeStampFull;
}
else if (update.LastTerseUpdateTime <= part.TimeStampTerse)
{
@ -176,38 +193,46 @@ namespace OpenSim.Region.Framework.Scenes
}
}
public void Reset()
{
if (m_pendingObjects == null)
return;
lock (m_pendingObjects)
{
if (m_pendingObjects != null)
{
m_pendingObjects.Clear();
m_pendingObjects = null;
}
}
}
// public void Reset()
// {
// if (m_pendingObjects == null)
// return;
//
// lock (m_pendingObjects)
// {
// if (m_pendingObjects != null)
// {
// m_pendingObjects.Clear();
// m_pendingObjects = null;
// }
// }
// }
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()
{
if (m_pendingObjects != null)
return m_pendingObjects.Count;
lock (m_pendingObjects)
return m_pendingObjects.Count;
return 0;
}

View File

@ -52,22 +52,25 @@ namespace OpenSim.Region.Framework.Scenes.Tests
TestHelpers.InMethod();
Scene scene = SceneHelpers.SetupScene();
int partsToTestCount = 3;
string objName = "obj1";
UUID objUuid = new UUID("00000000-0000-0000-0000-000000000001");
SceneObjectGroup so
= SceneHelpers.CreateSceneObject(partsToTestCount, TestHelpers.ParseTail(0x1), "obj1", 0x10);
SceneObjectPart[] parts = so.Parts;
SceneObjectPart part
= new SceneObjectPart(UUID.Zero, PrimitiveBaseShape.Default, Vector3.Zero, Quaternion.Identity, Vector3.Zero)
{ Name = objName, UUID = objUuid };
Assert.That(scene.AddNewSceneObject(new SceneObjectGroup(part), false), Is.True);
SceneObjectPart retrievedPart = scene.GetSceneObjectPart(objUuid);
Assert.That(scene.AddNewSceneObject(so, false), Is.True);
SceneObjectGroup retrievedSo = scene.GetSceneObjectGroup(so.UUID);
SceneObjectPart[] retrievedParts = retrievedSo.Parts;
//m_log.Debug("retrievedPart : {0}", retrievedPart);
// 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(retrievedPart.UUID, Is.EqualTo(objUuid));
Assert.That(retrievedSo.PrimCount, Is.EqualTo(partsToTestCount));
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]
@ -103,6 +106,39 @@ namespace OpenSim.Region.Framework.Scenes.Tests
Assert.That(retrievedPart.Name, Is.EqualTo(obj1Name));
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>
/// Test deleting an object from a scene.

View File

@ -43,11 +43,12 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary>
/// Gather uuids for a given entity.
/// </summary>
///
/// <remarks>
/// 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
/// 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).
/// </remarks>
public class UuidGatherer
{
private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
@ -76,11 +77,11 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary>
/// Gather all the asset uuids associated with the asset referenced by a given uuid
/// </summary>
///
/// <remarks>
/// 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
/// within this object).
///
/// </remarks>
/// <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="assetUuids">The assets gathered</param>
@ -119,11 +120,11 @@ namespace OpenSim.Region.Framework.Scenes
/// <summary>
/// Gather all the asset uuids associated with a given object.
/// </summary>
///
/// <remarks>
/// 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
/// within this object).
///
/// </remarks>
/// <param name="sceneObject">The scene object for which to gather assets</param>
/// <param name="assetUuids">The assets gathered</param>
public void GatherAssetUuids(SceneObjectGroup sceneObject, IDictionary<UUID, AssetType> assetUuids)

View File

@ -26,6 +26,7 @@
*/
using System;
using System.Collections.Generic;
using System.Reflection;
using log4net;
using Nini.Config;
@ -33,7 +34,9 @@ using NUnit.Framework;
using OpenMetaverse;
using OpenSim.Framework;
using OpenSim.Framework.Communications;
using OpenSim.Region.CoreModules.Avatar.Attachments;
using OpenSim.Region.CoreModules.Avatar.AvatarFactory;
using OpenSim.Region.CoreModules.Framework.InventoryAccess;
using OpenSim.Region.CoreModules.Framework.UserManagement;
using OpenSim.Region.CoreModules.ServiceConnectorsOut.Avatar;
using OpenSim.Region.Framework.Interfaces;
@ -47,21 +50,49 @@ namespace OpenSim.Region.OptionalModules.World.NPC.Tests
[TestFixture]
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]
public void TestCreate()
{
TestHelpers.InMethod();
// 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 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)));
}
[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]
public void TestMove()
{
TestHelpers.InMethod();
// 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 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)
{
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock = new ObjectShapePacket.ObjectDataBlock();
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return shapeBlock;
@ -7123,8 +7124,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
twist.y = 1.0f;
}
shapeBlock.PathTwistBegin = (sbyte)(100 * twist.x);
shapeBlock.PathTwist = (sbyte)(100 * twist.y);
// A fairly large precision error occurs for some calculations,
// 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;
@ -7138,6 +7151,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock;
shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@ -7158,8 +7172,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
taper_b.y = 2f;
}
shapeBlock.PathScaleX = (byte)(100 * (2.0 - taper_b.x));
shapeBlock.PathScaleY = (byte)(100 * (2.0 - taper_b.y));
tempFloat = (float)(100.0d * (2.0d - taper_b.x));
shapeBlock.PathScaleX = (byte)tempFloat;
tempFloat = (float)(100.0d * (2.0d - taper_b.y));
shapeBlock.PathScaleY = (byte)tempFloat;
if (topshear.x < -0.5f)
{
topshear.x = -0.5f;
@ -7176,8 +7192,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
topshear.y = 0.5f;
}
shapeBlock.PathShearX = (byte)(100 * topshear.x);
shapeBlock.PathShearY = (byte)(100 * topshear.y);
tempFloat = (float)(100.0d * topshear.x);
shapeBlock.PathShearX = (byte)tempFloat;
tempFloat = (float)(100.0d * topshear.y);
shapeBlock.PathShearY = (byte)tempFloat;
part.Shape.SculptEntry = false;
part.UpdateShape(shapeBlock);
@ -7233,6 +7251,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
if (part == null || part.ParentGroup == null || part.ParentGroup.IsDeleted)
return;
float tempFloat; // Use in float expressions below to avoid byte cast precision issues.
ObjectShapePacket.ObjectDataBlock shapeBlock;
shapeBlock = SetPrimitiveBlockShapeParams(part, holeshape, cut, hollow, twist, profileshape, pathcurve);
@ -7257,8 +7276,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
holesize.y = 0.5f;
}
shapeBlock.PathScaleX = (byte)(100 * (2 - holesize.x));
shapeBlock.PathScaleY = (byte)(100 * (2 - holesize.y));
tempFloat = (float)(100.0d * (2.0d - holesize.x));
shapeBlock.PathScaleX = (byte)tempFloat;
tempFloat = (float)(100.0d * (2.0d - holesize.y));
shapeBlock.PathScaleY = (byte)tempFloat;
if (topshear.x < -0.5f)
{
topshear.x = -0.5f;
@ -7275,8 +7296,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
topshear.y = 0.5f;
}
shapeBlock.PathShearX = (byte)(100 * topshear.x);
shapeBlock.PathShearY = (byte)(100 * topshear.y);
tempFloat = (float)(100.0d * topshear.x);
shapeBlock.PathShearX = (byte)tempFloat;
tempFloat = (float)(100.0d * topshear.y);
shapeBlock.PathShearY = (byte)tempFloat;
if (profilecut.x < 0f)
{
profilecut.x = 0f;
@ -7320,8 +7343,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
taper_a.y = 1f;
}
shapeBlock.PathTaperX = (sbyte)(100 * taper_a.x);
shapeBlock.PathTaperY = (sbyte)(100 * taper_a.y);
tempFloat = (float)(100.0d * taper_a.x);
shapeBlock.PathTaperX = (sbyte)tempFloat;
tempFloat = (float)(100.0d * taper_a.y);
shapeBlock.PathTaperY = (sbyte)tempFloat;
if (revolutions < 1f)
{
revolutions = 1f;
@ -7330,7 +7355,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
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
if (radiusoffset < 0f)
{
@ -7340,7 +7366,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
radiusoffset = 1f;
}
shapeBlock.PathRadiusOffset = (sbyte)(100 * radiusoffset);
tempFloat = 100.0f * radiusoffset;
shapeBlock.PathRadiusOffset = (sbyte)tempFloat;
if (skew < -0.95f)
{
skew = -0.95f;
@ -7349,7 +7376,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
{
skew = 0.95f;
}
shapeBlock.PathSkew = (sbyte)(100 * skew);
tempFloat = 100.0f * skew;
shapeBlock.PathSkew = (sbyte)tempFloat;
part.Shape.SculptEntry = false;
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));
// float revolutions
res.Add(new LSL_Float((Shape.PathRevolutions * 0.015) + 1.0)); // Slightly inaccurate, because an unsigned
// byte is being used to represent the entire
// range of floating-point values from 1.0
// through 4.0 (which is how SL does it).
res.Add(new LSL_Float(Math.Round(Shape.PathRevolutions * 0.015d, 2, MidpointRounding.AwayFromZero)) + 1.0d);
// Slightly inaccurate, because an unsigned byte is being used to represent
// the entire range of floating-point values from 1.0 through 4.0 (which is how
// 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
res.Add(new LSL_Float(Shape.PathRadiusOffset / 100.0));

View File

@ -712,9 +712,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
== World.LandChannel.GetLandObject(
presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
{
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);
// We will launch the teleport on a new thread so that when the script threads are terminated
// before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
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);
}
@ -750,9 +753,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api
== World.LandChannel.GetLandObject(
presence.AbsolutePosition.X, presence.AbsolutePosition.Y).LandData.OwnerID)
{
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);
// We will launch the teleport on a new thread so that when the script threads are terminated
// before teleport in ScriptInstance.GetXMLState(), we don't end up aborting the one doing the teleporting.
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);
}
}

View File

@ -49,7 +49,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
private const double ANGLE_ACCURACY_IN_RADIANS = 1E-6;
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;
[SetUp]
@ -194,10 +194,10 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_SPHERE, // Prim type
ScriptBaseClass.PRIM_HOLE_DEFAULT, // Prim hole type
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.32d, 0.76d, 0.0d), // Prim dimple
0.80d); // Prim hollow check
0.80f); // Prim hollow check
// Test a prism.
CheckllSetPrimitiveParams(
@ -206,11 +206,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_CIRCLE, // Prim hole type
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(2.0d, 1.0d, 0.0d), // Prim taper
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.
CheckllSetPrimitiveParams(
@ -219,11 +219,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_BOX, // Prim type
ScriptBaseClass.PRIM_HOLE_TRIANGLE, // Prim hole type
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, 1.0d, 0.0d), // Prim taper
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.
CheckllSetPrimitiveParams(
@ -232,16 +232,20 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_TUBE, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
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, 0.5d, 0.0d), // Prim hole size
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim shear
new LSL_Types.Vector3(1.0d, 0.05d, 0.0d), // Prim hole size
// 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(-1.0d, 1.0d, 0.0d), // Prim taper
1.0d, // Prim revolutions
1.0d, // Prim radius
0.0d, // Prim skew
0.00d); // Prim hollow check
// Expression for y selected to test precision problems during sbyte
// cast in SetPrimitiveShapeParams.
new LSL_Types.Vector3(-1.0d, 0.70d + 0.1d + 0.1d, 0.0d), // Prim taper
1.11f, // Prim revolutions
0.88f, // Prim radius
0.95f, // Prim skew
0.00f); // Prim hollow check
// Test a prism.
CheckllSetPrimitiveParams(
@ -250,11 +254,15 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
ScriptBaseClass.PRIM_TYPE_PRISM, // Prim type
ScriptBaseClass.PRIM_HOLE_SQUARE, // Prim hole type
new LSL_Types.Vector3(0.0d, 1.0d, 0.0d), // Prim cut
0.95d, // Prim hollow
new LSL_Types.Vector3(0.0d, 0.0d, 0.0d), // Prim twist
new LSL_Types.Vector3(2.0d, 1.0d, 0.0d), // Prim taper
0.95f, // Prim hollow
// Expression for x selected to test precision problems during sbyte
// 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
0.70d); // Prim hollow check
0.70f); // Prim hollow check
// Test a sculpted prim.
CheckllSetPrimitiveParams(
@ -268,8 +276,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Tests
// Set prim params for a box, cylinder or prism and check results.
public void CheckllSetPrimitiveParams(string primTest,
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,
double primHollowCheck)
float primHollow, LSL_Types.Vector3 primTwist, LSL_Types.Vector3 primTaper, LSL_Types.Vector3 primShear,
float primHollowCheck)
{
// Set the prim params.
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.
public void CheckllSetPrimitiveParams(string primTest,
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.
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.
public void CheckllSetPrimitiveParams(string primTest,
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,
double primRev, double primRadius, double primSkew, double primHollowCheck)
float primRev, float primRadius, float primSkew, float primHollowCheck)
{
// Set the prim params.
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(primTaper, m_lslApi.llList2Vector(primParams, 9), primTest + " prim taper");
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,
"TestllSetPrimitiveParams " + primTest + " prim radius fail");
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),
new Object[] { m_SaveTime });
}
}
public void StartProcessing()
{
m_ThreadPool.Start();
}
@ -659,7 +662,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine
SceneObjectPart part = m_Scene.GetSceneObjectPart(localID);
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_ScriptFailCount++;
return false;

View File

@ -439,14 +439,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
}
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;
return friendsOnline;
}
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";
return friendsOnline;
}
@ -510,14 +510,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
}
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;
return online;
}
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";
return online;
}
@ -575,14 +575,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
}
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;
return serverURLs;
}
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";
return serverURLs;
}
@ -639,14 +639,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
}
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;
return url;
}
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";
return url;
}
@ -698,14 +698,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
}
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;
return uui;
}
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";
return uui;
}
@ -746,14 +746,14 @@ namespace OpenSim.Services.Connectors.Hypergrid
}
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;
return false;
}
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";
return false;
}

View File

@ -262,7 +262,6 @@ namespace OpenSim.Services.Interfaces
UUID.Parse(Data["SkirtItem"]),
UUID.Parse(Data["SkirtAsset"]));
if (Data.ContainsKey("VisualParams"))
{
string[] vps = Data["VisualParams"].Split(new char[] {','});
@ -291,7 +290,6 @@ namespace OpenSim.Services.Interfaces
}
}
// Attachments
Dictionary<string, string> attchs = new Dictionary<string, string>();
foreach (KeyValuePair<string, string> _kvp in Data)
@ -308,7 +306,7 @@ namespace OpenSim.Services.Interfaces
UUID uuid = UUID.Zero;
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)

View File

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

View File

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

View File

@ -740,7 +740,7 @@
;; "config-include/StandaloneCommon.ini.example" to "config-include/StandaloneCommon.ini" before
;; 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/Grid.ini"
; Include-Architecture = "config-include/GridHypergrid.ini"